diff options
Diffstat (limited to 'source/blender')
233 files changed, 3743 insertions, 2768 deletions
diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c index dfebaecb96e..44a1d08f1fd 100644 --- a/source/blender/blenfont/intern/blf_font.c +++ b/source/blender/blenfont/intern/blf_font.c @@ -370,12 +370,10 @@ static void blf_font_draw_buffer_ex( fbuf[3] = 1.0f; } else { - float alphatest; fbuf[0] = (b_col_float[0] * a) + (fbuf[0] * (1.0f - a)); fbuf[1] = (b_col_float[1] * a) + (fbuf[1] * (1.0f - a)); fbuf[2] = (b_col_float[2] * a) + (fbuf[2] * (1.0f - a)); - fbuf[3] = (alphatest = (fbuf[3] + a)) < 1.0f ? - alphatest : 1.0f; + fbuf[3] = MIN2(fbuf[3] + a, 1.0f); /* clamp to 1.0 */ } } } @@ -407,12 +405,10 @@ static void blf_font_draw_buffer_ex( cbuf[3] = 255; } else { - int alphatest; cbuf[0] = (unsigned char)((b_col_char[0] * a) + (cbuf[0] * (1.0f - a))); cbuf[1] = (unsigned char)((b_col_char[1] * a) + (cbuf[1] * (1.0f - a))); cbuf[2] = (unsigned char)((b_col_char[2] * a) + (cbuf[2] * (1.0f - a))); - cbuf[3] = (unsigned char)(((alphatest = ((int)cbuf[3] + (int)(a * 255))) < 255) ? - alphatest : 255); + cbuf[3] = (unsigned char)MIN2((int)cbuf[3] + (int)(a * 255), 255); /* clamp to 255 */ } } } diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 5874f95502b..6527ba7f94f 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -63,7 +63,7 @@ struct bAction *BKE_action_copy(struct Main *bmain, struct bAction *src); /* Deallocate all of the Action's data, but not the Action itself */ void BKE_action_free(struct bAction *act); -void BKE_action_make_local(struct Main *bmain, struct bAction *act); +void BKE_action_make_local(struct Main *bmain, struct bAction *act, const bool lib_local); /* Action API ----------------- */ diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 326c335338f..c2323100205 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -76,7 +76,7 @@ struct bArmature *BKE_armature_from_object(struct Object *ob); int BKE_armature_bonelist_count(struct ListBase *lb); void BKE_armature_bonelist_free(struct ListBase *lb); void BKE_armature_free(struct bArmature *arm); -void BKE_armature_make_local(struct Main *bmain, struct bArmature *arm); +void BKE_armature_make_local(struct Main *bmain, struct bArmature *arm, const bool lib_local); struct bArmature *BKE_armature_copy(struct Main *bmain, struct bArmature *arm); /* Bounding box. */ @@ -95,6 +95,7 @@ float distfactor_to_bone(const float vec[3], const float b1[3], const float b2[3 void BKE_armature_where_is(struct bArmature *arm); void BKE_armature_where_is_bone(struct Bone *bone, struct Bone *prevbone, const bool use_recursion); +void BKE_pose_clear_pointers(struct bPose *pose); void BKE_pose_rebuild(struct Object *ob, struct bArmature *arm); void BKE_pose_where_is(struct Scene *scene, struct Object *ob); void BKE_pose_where_is_bone(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime, bool do_extra); diff --git a/source/blender/blenkernel/BKE_asset.h b/source/blender/blenkernel/BKE_asset_engine.h index 4a5ed587c3f..db6769e1c74 100644 --- a/source/blender/blenkernel/BKE_asset.h +++ b/source/blender/blenkernel/BKE_asset_engine.h @@ -25,12 +25,12 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file BKE_asset.h +/** \file BKE_asset_engine.h * \ingroup bke */ -#ifndef __BKE_ASSET_H__ -#define __BKE_ASSET_H__ +#ifndef __BKE_ASSET_ENGINE_H__ +#define __BKE_ASSET_ENGINE_H__ #ifdef __cplusplus extern "C" { @@ -234,12 +234,13 @@ void BKE_filedir_entryarr_clear(struct FileDirEntryArr *array); ASSETUUID_SUB_COMPARE(_uuida, _uuidb, uuid_variant) && \ ASSETUUID_SUB_COMPARE(_uuida, _uuidb, uuid_revision)) -/* GHash helpers */ +/* Various helpers */ unsigned int BKE_asset_uuid_hash(const void *key); bool BKE_asset_uuid_cmp(const void *a, const void *b); +void BKE_asset_uuid_print(const struct AssetUUID *uuid); #ifdef __cplusplus } #endif -#endif /* __BKE_ASSET_H__ */ +#endif /* __BKE_ASSET_ENGINE_H__ */ diff --git a/source/blender/blenkernel/BKE_brush.h b/source/blender/blenkernel/BKE_brush.h index c7116bf2ef6..8bd4bdf89e1 100644 --- a/source/blender/blenkernel/BKE_brush.h +++ b/source/blender/blenkernel/BKE_brush.h @@ -45,7 +45,7 @@ void BKE_brush_init(struct Brush *brush); struct Brush *BKE_brush_add(struct Main *bmain, const char *name, short ob_mode); struct Brush *BKE_brush_first_search(struct Main *bmain, short ob_mode); struct Brush *BKE_brush_copy(struct Main *bmain, struct Brush *brush); -void BKE_brush_make_local(struct Main *bmain, struct Brush *brush); +void BKE_brush_make_local(struct Main *bmain, struct Brush *brush, const bool lib_local); void BKE_brush_unlink(struct Main *bmain, struct Brush *brush); void BKE_brush_free(struct Brush *brush); diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h index 97f4b30894b..31a732cf7e5 100644 --- a/source/blender/blenkernel/BKE_camera.h +++ b/source/blender/blenkernel/BKE_camera.h @@ -53,7 +53,7 @@ struct GPUFXSettings; void BKE_camera_init(struct Camera *cam); void *BKE_camera_add(struct Main *bmain, const char *name); struct Camera *BKE_camera_copy(struct Main *bmain, struct Camera *cam); -void BKE_camera_make_local(struct Main *bmain, struct Camera *cam); +void BKE_camera_make_local(struct Main *bmain, struct Camera *cam, const bool lib_local); void BKE_camera_free(struct Camera *ca); /* Camera Usage */ diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 89dbe246910..5558786d254 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -71,7 +71,7 @@ void BKE_curve_editfont_free(struct Curve *cu); void BKE_curve_init(struct Curve *cu); struct Curve *BKE_curve_add(struct Main *bmain, const char *name, int type); struct Curve *BKE_curve_copy(struct Main *bmain, struct Curve *cu); -void BKE_curve_make_local(struct Main *bmain, struct Curve *cu); +void BKE_curve_make_local(struct Main *bmain, struct Curve *cu, const bool lib_local); short BKE_curve_type_get(struct Curve *cu); void BKE_curve_type_test(struct Object *ob); void BKE_curve_curve_dimension_update(struct Curve *cu); diff --git a/source/blender/blenkernel/BKE_font.h b/source/blender/blenkernel/BKE_font.h index 0711c423d1c..6775639125f 100644 --- a/source/blender/blenkernel/BKE_font.h +++ b/source/blender/blenkernel/BKE_font.h @@ -82,6 +82,8 @@ struct VFont *BKE_vfont_load(struct Main *bmain, const char *filepath); struct VFont *BKE_vfont_load_exists_ex(struct Main *bmain, const char *filepath, bool *r_exists); struct VFont *BKE_vfont_load_exists(struct Main *bmain, const char *filepath); +void BKE_vfont_make_local(struct Main *bmain, struct VFont *vfont, const bool lib_local); + bool BKE_vfont_to_curve_ex(struct Main *bmain, struct Object *ob, int mode, struct ListBase *r_nubase, const wchar_t **r_text, int *r_text_len, bool *r_text_free, diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index 6159531d8bd..e9e3cd3b16e 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -56,6 +56,8 @@ struct bGPDframe *gpencil_frame_duplicate(struct bGPDframe *src); struct bGPDlayer *gpencil_layer_duplicate(struct bGPDlayer *src); struct bGPdata *gpencil_data_duplicate(struct Main *bmain, struct bGPdata *gpd, bool internal_copy); +void BKE_gpencil_make_local(struct Main *bmain, struct bGPdata *gpd, const bool lib_local); + void gpencil_frame_delete_laststroke(struct bGPDlayer *gpl, struct bGPDframe *gpf); diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h index 4f2c89070cb..09a069ee36f 100644 --- a/source/blender/blenkernel/BKE_group.h +++ b/source/blender/blenkernel/BKE_group.h @@ -43,6 +43,7 @@ struct Scene; void BKE_group_free(struct Group *group); struct Group *BKE_group_add(struct Main *bmain, const char *name); struct Group *BKE_group_copy(struct Main *bmain, struct Group *group); +void BKE_group_make_local(struct Main *bmain, struct Group *group, const bool lib_local); bool BKE_group_object_add(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base); bool BKE_group_object_unlink(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base); struct Group *BKE_group_object_find(struct Group *group, struct Object *ob); diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h index 763a3874d4e..efef8d4be78 100644 --- a/source/blender/blenkernel/BKE_icons.h +++ b/source/blender/blenkernel/BKE_icons.h @@ -55,7 +55,7 @@ void BKE_icons_init(int first_dyn_id); /* return icon id for library object or create new icon if not found */ int BKE_icon_id_ensure(struct ID *id); -int BKE_icon_preview_ensure(struct PreviewImage *preview); +int BKE_icon_preview_ensure(struct ID *id, struct PreviewImage *preview); /* retrieve icon for id */ struct Icon *BKE_icon_get(int icon_id); @@ -99,6 +99,8 @@ struct PreviewImage *BKE_previewimg_create(void); /* create a copy of the preview image */ struct PreviewImage *BKE_previewimg_copy(struct PreviewImage *prv); +void BKE_previewimg_id_copy(struct ID *new_id, struct ID *old_id); + /* retrieve existing or create new preview image */ struct PreviewImage *BKE_previewimg_id_ensure(struct ID *id); diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index 0895feef983..132c73209d1 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -108,7 +108,7 @@ struct anim *openanim_noload(const char *name, int flags, int streamindex, char void BKE_image_de_interlace(struct Image *ima, int odd); -void BKE_image_make_local(struct Main *bmain, struct Image *ima); +void BKE_image_make_local(struct Main *bmain, struct Image *ima, const bool lib_local); void BKE_image_tag_time(struct Image *ima); diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index f30f9eac4e8..e590ff148d7 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -53,7 +53,6 @@ void BKE_key_free_nolib(struct Key *key); struct Key *BKE_key_add(struct ID *id); struct Key *BKE_key_copy(struct Main *bmain, struct Key *key); struct Key *BKE_key_copy_nolib(struct Key *key); -void BKE_key_make_local(struct Main *bmain, struct Key *key); void BKE_key_sort(struct Key *key); void key_curve_position_weights(float t, float data[4], int type); diff --git a/source/blender/blenkernel/BKE_lamp.h b/source/blender/blenkernel/BKE_lamp.h index 49b43550e67..4d53850c572 100644 --- a/source/blender/blenkernel/BKE_lamp.h +++ b/source/blender/blenkernel/BKE_lamp.h @@ -46,7 +46,7 @@ void BKE_lamp_init(struct Lamp *la); struct Lamp *BKE_lamp_add(struct Main *bmain, const char *name) ATTR_WARN_UNUSED_RESULT; struct Lamp *BKE_lamp_copy(struct Main *bmain, struct Lamp *la) ATTR_WARN_UNUSED_RESULT; struct Lamp *localize_lamp(struct Lamp *la) ATTR_WARN_UNUSED_RESULT; -void BKE_lamp_make_local(struct Main *bmain, struct Lamp *la); +void BKE_lamp_make_local(struct Main *bmain, struct Lamp *la, const bool lib_local); void BKE_lamp_free(struct Lamp *la); void lamp_drivers_update(struct Scene *scene, struct Lamp *la, float ctime); diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h index 606df9dcec8..226c82da295 100644 --- a/source/blender/blenkernel/BKE_lattice.h +++ b/source/blender/blenkernel/BKE_lattice.h @@ -49,7 +49,7 @@ void BKE_lattice_init(struct Lattice *lt); struct Lattice *BKE_lattice_add(struct Main *bmain, const char *name); struct Lattice *BKE_lattice_copy(struct Main *bmain, struct Lattice *lt); void BKE_lattice_free(struct Lattice *lt); -void BKE_lattice_make_local(struct Main *bmain, struct Lattice *lt); +void BKE_lattice_make_local(struct Main *bmain, struct Lattice *lt, const bool lib_local); void calc_lat_fudu(int flag, int res, float *r_fu, float *r_du); struct LatticeDeformData; diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index 396a3486b06..95d50fbd396 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -82,15 +82,17 @@ void id_us_min(struct ID *id); void id_fake_user_set(struct ID *id); void id_fake_user_clear(struct ID *id); -bool id_make_local(struct Main *bmain, struct ID *id, bool test); +void BKE_id_make_local_generic(struct Main *bmain, struct ID *id, const bool id_in_mainlist, const bool lib_local); +bool id_make_local(struct Main *bmain, struct ID *id, const bool test, const bool force_local); bool id_single_user(struct bContext *C, struct ID *id, struct PointerRNA *ptr, struct PropertyRNA *prop); bool id_copy(struct Main *bmain, struct ID *id, struct ID **newid, bool test); void id_sort_by_name(struct ListBase *lb, struct ID *id); void BKE_id_expand_local(struct ID *id); +void BKE_id_copy_ensure_local(struct Main *bmain, struct ID *old_id, struct ID *new_id); bool new_id(struct ListBase *lb, struct ID *id, const char *name); void id_clear_lib_data(struct Main *bmain, struct ID *id); -void id_clear_lib_data_ex(struct Main *bmain, struct ID *id, bool id_in_mainlist); +void id_clear_lib_data_ex(struct Main *bmain, struct ID *id, const bool id_in_mainlist); struct ListBase *which_libbase(struct Main *mainlib, short type); diff --git a/source/blender/blenkernel/BKE_linestyle.h b/source/blender/blenkernel/BKE_linestyle.h index e343cd29622..e96ef4e7be3 100644 --- a/source/blender/blenkernel/BKE_linestyle.h +++ b/source/blender/blenkernel/BKE_linestyle.h @@ -54,6 +54,8 @@ FreestyleLineStyle *BKE_linestyle_new(struct Main *bmain, const char *name); void BKE_linestyle_free(FreestyleLineStyle *linestyle); FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, FreestyleLineStyle *linestyle); +void BKE_linestyle_make_local(struct Main *bmain, struct FreestyleLineStyle *linestyle, const bool lib_local); + FreestyleLineStyle *BKE_linestyle_active_from_scene(struct Scene *scene); LineStyleModifier *BKE_linestyle_color_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type); diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 97bfd0f3f07..3349bffac85 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -125,6 +125,8 @@ struct Mask *BKE_mask_new(struct Main *bmain, const char *name); struct Mask *BKE_mask_copy_nolib(struct Mask *mask); struct Mask *BKE_mask_copy(struct Main *bmain, struct Mask *mask); +void BKE_mask_make_local(struct Main *bmain, struct Mask *mask, const bool lib_local); + void BKE_mask_free(struct Mask *mask); void BKE_mask_coord_from_frame(float r_co[2], const float co[2], const float frame_size[2]); diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index 0bc54ee4a16..df739996c54 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -57,7 +57,7 @@ struct Material *BKE_material_add(struct Main *bmain, const char *name); struct Material *BKE_material_copy(struct Main *bmain, struct Material *ma); struct Material *localize_material(struct Material *ma); struct Material *give_node_material(struct Material *ma); /* returns node material or self */ -void BKE_material_make_local(struct Main *bmain, struct Material *ma); +void BKE_material_make_local(struct Main *bmain, struct Material *ma, const bool lib_local); /* UNUSED */ // void automatname(struct Material *); @@ -78,15 +78,13 @@ enum { }; struct Material *give_current_material(struct Object *ob, short act); -struct ID *material_from(struct Object *ob, short act); void assign_material_id(struct ID *id, struct Material *ma, short act); void assign_material(struct Object *ob, struct Material *ma, short act, int assign_type); void assign_matarar(struct Object *ob, struct Material ***matar, short totcol); -short find_material_index(struct Object *ob, struct Material *ma); - -bool object_add_material_slot(struct Object *ob); -bool object_remove_material_slot(struct Object *ob); +short BKE_object_material_slot_find_index(struct Object *ob, struct Material *ma); +bool BKE_object_material_slot_add(struct Object *ob); +bool BKE_object_material_slot_remove(struct Object *ob); void BKE_texpaint_slot_refresh_cache(struct Scene *scene, struct Material *ma); void BKE_texpaint_slots_refresh_object(struct Scene *scene, struct Object *ob); diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h index 42704c1b2db..64320a20281 100644 --- a/source/blender/blenkernel/BKE_mball.h +++ b/source/blender/blenkernel/BKE_mball.h @@ -43,7 +43,7 @@ void BKE_mball_init(struct MetaBall *mb); struct MetaBall *BKE_mball_add(struct Main *bmain, const char *name); struct MetaBall *BKE_mball_copy(struct Main *bmain, struct MetaBall *mb); -void BKE_mball_make_local(struct Main *bmain, struct MetaBall *mb); +void BKE_mball_make_local(struct Main *bmain, struct MetaBall *mb, const bool lib_local); bool BKE_mball_is_basis_for(struct Object *ob1, struct Object *ob2); bool BKE_mball_is_basis(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index d3bb34d7a41..d41878825bb 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -91,7 +91,7 @@ struct Mesh *BKE_mesh_copy(struct Main *bmain, struct Mesh *me); void BKE_mesh_update_customdata_pointers(struct Mesh *me, const bool do_ensure_tess_cd); void BKE_mesh_ensure_skin_customdata(struct Mesh *me); -void BKE_mesh_make_local(struct Main *bmain, struct Mesh *me); +void BKE_mesh_make_local(struct Main *bmain, struct Mesh *me, const bool lib_local); void BKE_mesh_boundbox_calc(struct Mesh *me, float r_loc[3], float r_size[3]); void BKE_mesh_texspace_calc(struct Mesh *me); float (*BKE_mesh_orco_verts_get(struct Object *ob))[3]; diff --git a/source/blender/blenkernel/BKE_mesh_mapping.h b/source/blender/blenkernel/BKE_mesh_mapping.h index dff79b6cc22..b5b5443574c 100644 --- a/source/blender/blenkernel/BKE_mesh_mapping.h +++ b/source/blender/blenkernel/BKE_mesh_mapping.h @@ -125,6 +125,11 @@ void BKE_mesh_vert_edge_map_create( void BKE_mesh_vert_edge_vert_map_create( MeshElemMap **r_map, int **r_mem, const struct MEdge *medge, int totvert, int totedge); +void BKE_mesh_edge_loop_map_create( + MeshElemMap **r_map, int **r_mem, + const struct MEdge *medge, const int totedge, + const struct MPoly *mpoly, const int totpoly, + const struct MLoop *mloop, const int totloop); void BKE_mesh_edge_poly_map_create( MeshElemMap **r_map, int **r_mem, const struct MEdge *medge, const int totedge, @@ -186,11 +191,19 @@ typedef bool (*MeshRemapIslandsCalc)( /* Above vert/UV mapping stuff does not do what we need here, but does things we do not need here. * So better keep them separated for now, I think. */ -bool BKE_mesh_calc_islands_loop_poly_uv( +bool BKE_mesh_calc_islands_loop_poly_edgeseam( + struct MVert *verts, const int totvert, + struct MEdge *edges, const int totedge, + struct MPoly *polys, const int totpoly, + struct MLoop *loops, const int totloop, + MeshIslandStore *r_island_store); + +bool BKE_mesh_calc_islands_loop_poly_uvmap( struct MVert *verts, const int totvert, struct MEdge *edges, const int totedge, struct MPoly *polys, const int totpoly, struct MLoop *loops, const int totloop, + const struct MLoopUV *luvs, MeshIslandStore *r_island_store); int *BKE_mesh_calc_smoothgroups( diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index b44cb226f0d..95f06e9f695 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -346,7 +346,7 @@ void ntreeUserDecrefID(struct bNodeTree *ntree); struct bNodeTree *ntreeFromID(struct ID *id); -void ntreeMakeLocal(struct Main *bmain, struct bNodeTree *ntree, bool id_in_mainlist); +void ntreeMakeLocal(struct Main *bmain, struct bNodeTree *ntree, bool id_in_mainlist, const bool lib_local); struct bNode *ntreeFindType(const struct bNodeTree *ntree, int type); bool ntreeHasType(const struct bNodeTree *ntree, int type); bool ntreeHasTree(const struct bNodeTree *ntree, const struct bNodeTree *lookup); diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 1f0dc5f1814..1b3e05d11ae 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -107,7 +107,7 @@ struct Object *BKE_object_lod_matob_get(struct Object *ob, struct Scene *scene); struct Object *BKE_object_copy_ex(struct Main *bmain, struct Object *ob, bool copy_caches); struct Object *BKE_object_copy(struct Main *bmain, struct Object *ob); -void BKE_object_make_local(struct Main *bmain, struct Object *ob); +void BKE_object_make_local(struct Main *bmain, struct Object *ob, const bool lib_local); bool BKE_object_is_libdata(struct Object *ob); bool BKE_object_obdata_is_libdata(struct Object *ob); @@ -206,8 +206,6 @@ void BKE_object_eval_uber_data(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); -void BKE_object_eval_proxy_backlink(struct EvaluationContext *eval_ctx, struct Object *ob); - void BKE_object_handle_data_update(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 0b2e2383457..37831728e6f 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -324,7 +324,7 @@ struct ModifierData *object_add_particle_system(struct Scene *scene, struct Obje void object_remove_particle_system(struct Scene *scene, struct Object *ob); struct ParticleSettings *psys_new_settings(const char *name, struct Main *main); struct ParticleSettings *BKE_particlesettings_copy(struct Main *bmain, struct ParticleSettings *part); -void BKE_particlesettings_make_local(struct Main *bmain, struct ParticleSettings *part); +void BKE_particlesettings_make_local(struct Main *bmain, struct ParticleSettings *part, const bool lib_local); void psys_reset(struct ParticleSystem *psys, int mode); diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 03af0b7d6c9..d2152950bff 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -101,6 +101,8 @@ struct Scene *BKE_scene_set_name(struct Main *bmain, const char *name); struct Scene *BKE_scene_copy(struct Main *bmain, struct Scene *sce, int type); void BKE_scene_groups_relink(struct Scene *sce); +void BKE_scene_make_local(struct Main *bmain, struct Scene *sce, const bool lib_local); + struct Object *BKE_scene_camera_find(struct Scene *sc); #ifdef DURIAN_CAMERA_SWITCH struct Object *BKE_scene_camera_switch_find(struct Scene *scene); // DURIAN_CAMERA_SWITCH diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index 18d9fe061a8..28b15b2a310 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -80,6 +80,8 @@ void BKE_sound_load(struct Main *main, struct bSound *sound); void BKE_sound_free(struct bSound *sound); +void BKE_sound_make_local(struct Main *bmain, struct bSound *sound, const bool lib_local); + #if defined(__AUD_C_API_H__) || defined(WITH_SYSTEM_AUDASPACE) AUD_Device *BKE_sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume); #endif diff --git a/source/blender/blenkernel/BKE_speaker.h b/source/blender/blenkernel/BKE_speaker.h index 89b948a2126..b91b64c4b74 100644 --- a/source/blender/blenkernel/BKE_speaker.h +++ b/source/blender/blenkernel/BKE_speaker.h @@ -34,7 +34,7 @@ struct Speaker; void BKE_speaker_init(struct Speaker *spk); void *BKE_speaker_add(struct Main *bmain, const char *name); struct Speaker *BKE_speaker_copy(struct Main *bmain, struct Speaker *spk); -void BKE_speaker_make_local(struct Main *bmain, struct Speaker *spk); +void BKE_speaker_make_local(struct Main *bmain, struct Speaker *spk, const bool lib_local); void BKE_speaker_free(struct Speaker *spk); #endif diff --git a/source/blender/blenkernel/BKE_text.h b/source/blender/blenkernel/BKE_text.h index 858feeeab10..081b7589af6 100644 --- a/source/blender/blenkernel/BKE_text.h +++ b/source/blender/blenkernel/BKE_text.h @@ -53,6 +53,7 @@ struct Text *BKE_text_load_ex(struct Main *bmain, const char *file, const cha const bool is_internal); struct Text *BKE_text_load (struct Main *bmain, const char *file, const char *relpath); struct Text *BKE_text_copy (struct Main *bmain, struct Text *ta); +void BKE_text_make_local (struct Main *bmain, struct Text *text, const bool lib_local); void BKE_text_clear (struct Text *text); void BKE_text_write (struct Text *text, const char *str); int BKE_text_file_modified_check(struct Text *text); diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index 56f056c681a..1c5ea946f59 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -72,7 +72,7 @@ void BKE_texture_default(struct Tex *tex); struct Tex *BKE_texture_copy(struct Main *bmain, struct Tex *tex); struct Tex *BKE_texture_add(struct Main *bmain, const char *name); struct Tex *BKE_texture_localize(struct Tex *tex); -void BKE_texture_make_local(struct Main *bmain, struct Tex *tex); +void BKE_texture_make_local(struct Main *bmain, struct Tex *tex, const bool lib_local); void BKE_texture_type_set(struct Tex *tex, int type); void BKE_texture_mtex_default(struct MTex *mtex); diff --git a/source/blender/blenkernel/BKE_world.h b/source/blender/blenkernel/BKE_world.h index da5cca09b27..23bf9ec3d22 100644 --- a/source/blender/blenkernel/BKE_world.h +++ b/source/blender/blenkernel/BKE_world.h @@ -41,7 +41,7 @@ void BKE_world_init(struct World *wrld); struct World *add_world(struct Main *bmian, const char *name); struct World *BKE_world_copy(struct Main *bmain, struct World *wrld); struct World *localize_world(struct World *wrld); -void BKE_world_make_local(struct Main *bmain, struct World *wrld); +void BKE_world_make_local(struct Main *bmain, struct World *wrld, const bool lib_local); #endif diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 9007a6794a1..848ad252c45 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -70,7 +70,7 @@ set(SRC intern/appdir.c intern/armature.c intern/armature_update.c - intern/asset.c + intern/asset_engine.c intern/autoexec.c intern/blender.c intern/blender_copybuffer.c @@ -119,6 +119,7 @@ set(SRC intern/lamp.c intern/lattice.c intern/library.c + intern/library_asset.c intern/library_idmap.c intern/library_query.c intern/library_remap.c @@ -195,7 +196,7 @@ set(SRC BKE_animsys.h BKE_appdir.h BKE_armature.h - BKE_asset.h + BKE_asset_engine.h BKE_autoexec.h BKE_blender.h BKE_blender_copybuffer.h diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c index 828a6bb16ac..792e9195f12 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -313,12 +313,10 @@ CCGSubSurf *ccgSubSurf_new(CCGMeshIFC *ifc, int subdivLevels, CCGAllocatorIFC *a ss->osd_vao = 0; ss->skip_grids = false; ss->osd_compute = 0; - ss->osd_uvs_invalid = true; - ss->osd_subsurf_uv = 0; - ss->osd_uv_index = -1; ss->osd_next_face_ptex_index = 0; ss->osd_coarse_coords = NULL; ss->osd_num_coarse_coords = 0; + ss->osd_subdiv_uvs = false; #endif return ss; diff --git a/source/blender/blenkernel/intern/CCGSubSurf.h b/source/blender/blenkernel/intern/CCGSubSurf.h index a825cffe7a0..4c913e79586 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.h +++ b/source/blender/blenkernel/intern/CCGSubSurf.h @@ -205,7 +205,7 @@ void ccgSubSurf_checkTopologyChanged(CCGSubSurf *ss, struct DerivedMesh *dm); void ccgSubSurf_prepareTopologyRefiner(CCGSubSurf *ss, struct DerivedMesh *dm); /* Make sure GL mesh exists, up to date and ready to draw. */ -bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl); +bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl, int active_uv_index); /* Draw given partitions of the GL mesh. * @@ -244,6 +244,8 @@ void ccgSubSurf_free_osd_mesh(CCGSubSurf *ss); void ccgSubSurf_getMinMax(CCGSubSurf *ss, float r_min[3], float r_max[3]); +void ccgSubSurf__sync_subdivUvs(CCGSubSurf *ss, bool subsurf_uvs); + #endif #endif /* __CCGSUBSURF_H__ */ diff --git a/source/blender/blenkernel/intern/CCGSubSurf_intern.h b/source/blender/blenkernel/intern/CCGSubSurf_intern.h index 7ec9f329444..9df1c9021ef 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf_intern.h +++ b/source/blender/blenkernel/intern/CCGSubSurf_intern.h @@ -86,7 +86,7 @@ void ccg_ehashIterator_next(EHashIterator *ehi); int ccg_ehashIterator_isStopped(EHashIterator *ehi); /** - * Standard allocator implementarion. + * Standard allocator implementation. */ CCGAllocatorIFC *ccg_getStandardAllocatorIFC(void); @@ -255,10 +255,7 @@ struct CCGSubSurf { */ int osd_next_face_ptex_index; - /* ** Needs review. ** */ - bool osd_subsurf_uv; - int osd_uv_index; - bool osd_uvs_invalid; + bool osd_subdiv_uvs; #endif }; diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c index 2bb55c2d1ed..65cf899b42b 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c +++ b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c @@ -190,7 +190,6 @@ void ccgSubSurf_checkTopologyChanged(CCGSubSurf *ss, DerivedMesh *dm) /* ** Make sure both GPU and CPU backends are properly reset. ** */ ss->osd_coarse_coords_invalid = true; - ss->osd_uvs_invalid = true; /* Reset GPU part. */ ss->osd_mesh_invalid = true; @@ -216,7 +215,9 @@ static void ccgSubSurf__updateGLMeshCoords(CCGSubSurf *ss) ss->osd_num_coarse_coords); } -bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl) +bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, + bool use_osd_glsl, + int active_uv_index) { int compute_type; @@ -256,8 +257,7 @@ bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl) ss->osd_mesh = openSubdiv_createOsdGLMeshFromTopologyRefiner( ss->osd_topology_refiner, compute_type, - ss->subdivLevels, - ss->osd_subsurf_uv); + ss->subdivLevels); ss->osd_topology_refiner = NULL; if (UNLIKELY(ss->osd_mesh == NULL)) { @@ -290,7 +290,7 @@ bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, bool use_osd_glsl) ss->osd_coarse_coords_invalid = false; } - openSubdiv_osdGLMeshDisplayPrepare(use_osd_glsl, ss->osd_uv_index); + openSubdiv_osdGLMeshDisplayPrepare(use_osd_glsl, active_uv_index); return true; } @@ -984,6 +984,11 @@ void ccgSubSurf__delete_pending(void) BLI_spin_unlock(&delete_spin); } +void ccgSubSurf__sync_subdivUvs(CCGSubSurf *ss, bool subdiv_uvs) +{ + ss->osd_subdiv_uvs = subdiv_uvs; +} + /* ** Public API ** */ void BKE_subsurf_osd_init(void) diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c index c4317f4d740..f1f82f458aa 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c +++ b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv_converter.c @@ -62,6 +62,16 @@ typedef struct ConvDMStorage { *vert_poly_mem, *edge_poly_mem; #endif + + MVert *mvert; + MEdge *medge; + MLoop *mloop; + MPoly *mpoly; + + MeshIslandStore island_store; + int num_uvs; + float *uvs; + int *face_uvs; } ConvDMStorage; static OpenSubdiv_SchemeType conv_dm_get_type( @@ -74,6 +84,13 @@ static OpenSubdiv_SchemeType conv_dm_get_type( return OSD_SCHEME_CATMARK; } +static bool conv_dm_get_subdiv_uvs( + const OpenSubdiv_Converter *converter) +{ + ConvDMStorage *storage = converter->user_data; + return (storage->ss->osd_subdiv_uvs); +} + static int conv_dm_get_num_faces(const OpenSubdiv_Converter *converter) { ConvDMStorage *storage = converter->user_data; @@ -99,9 +116,7 @@ static int conv_dm_get_num_face_verts(const OpenSubdiv_Converter *converter, int face) { ConvDMStorage *storage = converter->user_data; - DerivedMesh *dm = storage->dm; - const MPoly *mp = dm->getPolyArray(dm); - const MPoly *mpoly = &mp[face]; + const MPoly *mpoly = &storage->mpoly[face]; return mpoly->totloop; } @@ -110,13 +125,10 @@ static void conv_dm_get_face_verts(const OpenSubdiv_Converter *converter, int *face_verts) { ConvDMStorage *storage = converter->user_data; - DerivedMesh *dm = storage->dm; - const MLoop *ml = dm->getLoopArray(dm); - const MPoly *mp = dm->getPolyArray(dm); - const MPoly *mpoly = &mp[face]; + const MPoly *mpoly = &storage->mpoly[face]; int loop; for (loop = 0; loop < mpoly->totloop; loop++) { - face_verts[loop] = ml[mpoly->loopstart + loop].v; + face_verts[loop] = storage->mloop[mpoly->loopstart + loop].v; } } @@ -125,13 +137,10 @@ static void conv_dm_get_face_edges(const OpenSubdiv_Converter *converter, int *face_edges) { ConvDMStorage *storage = converter->user_data; - DerivedMesh *dm = storage->dm; - const MLoop *ml = dm->getLoopArray(dm); - const MPoly *mp = dm->getPolyArray(dm); - const MPoly *mpoly = &mp[face]; + const MPoly *mpoly = &storage->mpoly[face]; int loop; for (loop = 0; loop < mpoly->totloop; loop++) { - face_edges[loop] = ml[mpoly->loopstart + loop].e; + face_edges[loop] = storage->mloop[mpoly->loopstart + loop].e; } } @@ -140,9 +149,7 @@ static void conv_dm_get_edge_verts(const OpenSubdiv_Converter *converter, int *edge_verts) { ConvDMStorage *storage = converter->user_data; - DerivedMesh *dm = storage->dm; - const MEdge *me = dm->getEdgeArray(dm); - const MEdge *medge = &me[edge]; + const MEdge *medge = &storage->medge[edge]; edge_verts[0] = medge->v1; edge_verts[1] = medge->v2; } @@ -153,14 +160,12 @@ static int conv_dm_get_num_edge_faces(const OpenSubdiv_Converter *converter, ConvDMStorage *storage = converter->user_data; #ifndef USE_MESH_ELEMENT_MAPPING DerivedMesh *dm = storage->dm; - const MLoop *ml = dm->getLoopArray(dm); - const MPoly *mp = dm->getPolyArray(dm); int num = 0, poly; for (poly = 0; poly < dm->getNumPolys(dm); poly++) { - const MPoly *mpoly = &mp[poly]; + const MPoly *mpoly = &user_data->mpoly[poly]; int loop; for (loop = 0; loop < mpoly->totloop; loop++) { - const MLoop *mloop = &ml[mpoly->loopstart + loop]; + const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop]; if (mloop->e == edge) { ++num; break; @@ -180,14 +185,12 @@ static void conv_dm_get_edge_faces(const OpenSubdiv_Converter *converter, ConvDMStorage *storage = converter->user_data; #ifndef USE_MESH_ELEMENT_MAPPING DerivedMesh *dm = storage->dm; - const MLoop *ml = dm->getLoopArray(dm); - const MPoly *mp = dm->getPolyArray(dm); int num = 0, poly; for (poly = 0; poly < dm->getNumPolys(dm); poly++) { - const MPoly *mpoly = &mp[poly]; + const MPoly *mpoly = &user_data->mpoly[poly]; int loop; for (loop = 0; loop < mpoly->totloop; loop++) { - const MLoop *mloop = &ml[mpoly->loopstart + loop]; + const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop]; if (mloop->e == edge) { edge_faces[num++] = poly; break; @@ -205,9 +208,8 @@ static float conv_dm_get_edge_sharpness(const OpenSubdiv_Converter *converter, int edge) { ConvDMStorage *storage = converter->user_data; - DerivedMesh *dm = storage->dm; CCGSubSurf *ss = storage->ss; - const MEdge *medge = dm->getEdgeArray(dm); + const MEdge *medge = storage->medge; return (float)medge[edge].crease / 255.0f * ss->subdivLevels; } @@ -217,10 +219,9 @@ static int conv_dm_get_num_vert_edges(const OpenSubdiv_Converter *converter, ConvDMStorage *storage = converter->user_data; #ifndef USE_MESH_ELEMENT_MAPPING DerivedMesh *dm = storage->dm; - const MEdge *me = dm->getEdgeArray(dm); int num = 0, edge; for (edge = 0; edge < dm->getNumEdges(dm); edge++) { - const MEdge *medge = &me[edge]; + const MEdge *medge = &user_data->medge[edge]; if (medge->v1 == vert || medge->v2 == vert) { ++num; } @@ -238,10 +239,9 @@ static void conv_dm_get_vert_edges(const OpenSubdiv_Converter *converter, ConvDMStorage *storage = converter->user_data; #ifndef USE_MESH_ELEMENT_MAPPING DerivedMesh *dm = storage->dm; - const MEdge *me = dm->getEdgeArray(dm); int num = 0, edge; for (edge = 0; edge < dm->getNumEdges(dm); edge++) { - const MEdge *medge = &me[edge]; + const MEdge *medge = &user_data->medge[edge]; if (medge->v1 == vert || medge->v2 == vert) { vert_edges[num++] = edge; } @@ -259,14 +259,12 @@ static int conv_dm_get_num_vert_faces(const OpenSubdiv_Converter *converter, ConvDMStorage *storage = converter->user_data; #ifndef USE_MESH_ELEMENT_MAPPING DerivedMesh *dm = storage->dm; - const MLoop *ml = dm->getLoopArray(dm); - const MPoly *mp = dm->getPolyArray(dm); int num = 0, poly; for (poly = 0; poly < dm->getNumPolys(dm); poly++) { - const MPoly *mpoly = &mp[poly]; + const MPoly *mpoly = &user_data->mpoly[poly]; int loop; for (loop = 0; loop < mpoly->totloop; loop++) { - const MLoop *mloop = &ml[mpoly->loopstart + loop]; + const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop]; if (mloop->v == vert) { ++num; break; @@ -286,14 +284,12 @@ static void conv_dm_get_vert_faces(const OpenSubdiv_Converter *converter, ConvDMStorage *storage = converter->user_data; #ifndef USE_MESH_ELEMENT_MAPPING DerivedMesh *dm = storage->dm; - const MLoop *ml = dm->getLoopArray(dm); - const MPoly *mp = dm->getPolyArray(dm); int num = 0, poly; for (poly = 0; poly < dm->getNumPolys(dm); poly++) { - const MPoly *mpoly = &mp[poly]; + const MPoly *mpoly = &storage->mpoly[poly]; int loop; for (loop = 0; loop < mpoly->totloop; loop++) { - const MLoop *mloop = &ml[mpoly->loopstart + loop]; + const MLoop *mloop = &storage->mloop[mpoly->loopstart + loop]; if (mloop->v == vert) { vert_faces[num++] = poly; break; @@ -307,9 +303,114 @@ static void conv_dm_get_vert_faces(const OpenSubdiv_Converter *converter, #endif } +static int conv_dm_get_num_uv_layers(const OpenSubdiv_Converter *converter) +{ + ConvDMStorage *storage = converter->user_data; + DerivedMesh *dm = storage->dm; + int num_uv_layers = CustomData_number_of_layers(&dm->loopData, CD_MLOOPUV); + return num_uv_layers; +} + +static void conv_dm_precalc_uv_layer(const OpenSubdiv_Converter *converter, + int layer) +{ + ConvDMStorage *storage = converter->user_data; + DerivedMesh *dm = storage->dm; + + const MLoopUV *mloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, layer); + const int num_loops = dm->getNumLoops(dm); + + /* Initialize memory required for the operations. */ + if (storage->uvs == NULL) { + storage->uvs = MEM_mallocN(sizeof(float) * 2 * num_loops, "osd uvs"); + } + if (storage->face_uvs == NULL) { + storage->face_uvs = MEM_mallocN(sizeof(int) * num_loops, "osd face uvs"); + } + + /* Calculate islands connectivity of the UVs. */ + BKE_mesh_calc_islands_loop_poly_uvmap( + storage->mvert, dm->getNumVerts(dm), + storage->medge, dm->getNumEdges(dm), + storage->mpoly, dm->getNumPolys(dm), + storage->mloop, dm->getNumLoops(dm), + mloopuv, + &storage->island_store); + + /* Here we "weld" duplicated vertices from island to the same UV value. + * The idea here is that we need to pass individual islands to OpenSubdiv. + */ + storage->num_uvs = 0; + for (int island = 0; island < storage->island_store.islands_num; ++island) { + MeshElemMap *island_poly_map = storage->island_store.islands[island]; + for (int poly = 0; poly < island_poly_map->count; ++poly) { + int poly_index = island_poly_map->indices[poly]; + /* Within the same UV island we should share UV points across + * loops. Otherwise each poly will be subdivided individually + * which we don't really want. + */ + const MPoly *mpoly = &storage->mpoly[poly_index]; + for (int loop = 0; loop < mpoly->totloop; ++loop) { + const MLoopUV *luv = &mloopuv[mpoly->loopstart + loop]; + bool found = false; + /* TODO(sergey): Quite bad loop, which gives us O(N^2) + * complexity here. But how can we do it smarter, hopefully + * without requiring lots of additional memory. + */ + for (int i = 0; i < storage->num_uvs; ++i) { + if (equals_v2v2(luv->uv, &storage->uvs[2 * i])) { + storage->face_uvs[mpoly->loopstart + loop] = i; + found = true; + break; + } + } + if (!found) { + copy_v2_v2(&storage->uvs[2 * storage->num_uvs], luv->uv); + storage->face_uvs[mpoly->loopstart + loop] = storage->num_uvs; + ++storage->num_uvs; + } + } + } + } +} + +static void conv_dm_finish_uv_layer(const OpenSubdiv_Converter *converter) +{ + ConvDMStorage *storage = converter->user_data; + BKE_mesh_loop_islands_free(&storage->island_store); +} + +static int conv_dm_get_num_uvs(const OpenSubdiv_Converter *converter) +{ + ConvDMStorage *storage = converter->user_data; + return storage->num_uvs; +} + +static void conv_dm_get_uvs(const OpenSubdiv_Converter *converter, float *uvs) +{ + ConvDMStorage *storage = converter->user_data; + memcpy(uvs, storage->uvs, sizeof(float) * 2 * storage->num_uvs); +} + +static int conv_dm_get_face_corner_uv_index(const OpenSubdiv_Converter *converter, + int face, + int corner) +{ + ConvDMStorage *storage = converter->user_data; + const MPoly *mpoly = &storage->mpoly[face]; + return storage->face_uvs[mpoly->loopstart + corner]; +} + static void conv_dm_free_user_data(const OpenSubdiv_Converter *converter) { ConvDMStorage *user_data = converter->user_data; + if (user_data->uvs != NULL) { + MEM_freeN(user_data->uvs); + } + if (user_data->face_uvs != NULL) { + MEM_freeN(user_data->face_uvs); + } + #ifdef USE_MESH_ELEMENT_MAPPING MEM_freeN(user_data->vert_edge_map); MEM_freeN(user_data->vert_edge_mem); @@ -330,6 +431,8 @@ void ccgSubSurf_converter_setup_from_derivedmesh( converter->get_type = conv_dm_get_type; + converter->get_subdiv_uvs = conv_dm_get_subdiv_uvs; + converter->get_num_faces = conv_dm_get_num_faces; converter->get_num_edges = conv_dm_get_num_edges; converter->get_num_verts = conv_dm_get_num_verts; @@ -348,9 +451,27 @@ void ccgSubSurf_converter_setup_from_derivedmesh( converter->get_num_vert_faces = conv_dm_get_num_vert_faces; converter->get_vert_faces = conv_dm_get_vert_faces; + converter->get_num_uv_layers = conv_dm_get_num_uv_layers; + converter->precalc_uv_layer = conv_dm_precalc_uv_layer; + converter->finish_uv_layer = conv_dm_finish_uv_layer; + converter->get_num_uvs = conv_dm_get_num_uvs; + converter->get_uvs = conv_dm_get_uvs; + converter->get_face_corner_uv_index = conv_dm_get_face_corner_uv_index; + user_data = MEM_mallocN(sizeof(ConvDMStorage), __func__); user_data->ss = ss; user_data->dm = dm; + + user_data->mvert = dm->getVertArray(dm); + user_data->medge = dm->getEdgeArray(dm); + user_data->mloop = dm->getLoopArray(dm); + user_data->mpoly = dm->getPolyArray(dm); + + memset(&user_data->island_store, 0, sizeof(user_data->island_store)); + + user_data->uvs = NULL; + user_data->face_uvs = NULL; + converter->free_user_data = conv_dm_free_user_data; converter->user_data = user_data; @@ -405,6 +526,13 @@ static OpenSubdiv_SchemeType conv_ccg_get_bilinear_type( } } +static bool conv_ccg_get_subdiv_uvs( + const OpenSubdiv_Converter *converter) +{ + CCGSubSurf *ss = converter->user_data; + return (ss->osd_subdiv_uvs); +} + static int conv_ccg_get_num_faces(const OpenSubdiv_Converter *converter) { CCGSubSurf *ss = converter->user_data; @@ -548,11 +676,44 @@ static void conv_ccg_get_vert_faces(const OpenSubdiv_Converter *converter, } } +static int conv_ccg_get_num_uv_layers(const OpenSubdiv_Converter *UNUSED(converter)) +{ + return 0; +} + +static void conv_ccg_precalc_uv_layer(const OpenSubdiv_Converter * UNUSED(converter), + int UNUSED(layer)) +{ +} + +static void conv_ccg_finish_uv_layer(const OpenSubdiv_Converter *UNUSED(converter)) +{ +} + +static int conv_ccg_get_num_uvs(const OpenSubdiv_Converter *UNUSED(converter)) +{ + return 0; +} + +static void conv_ccg_get_uvs(const OpenSubdiv_Converter * UNUSED(converter), + float *UNUSED(uvs)) +{ +} + +static int conv_ccg_get_face_corner_uv_index(const OpenSubdiv_Converter *UNUSED(converter), + int UNUSED(face), + int UNUSED(corner_)) +{ + return 0; +} + void ccgSubSurf_converter_setup_from_ccg(CCGSubSurf *ss, OpenSubdiv_Converter *converter) { converter->get_type = conv_ccg_get_bilinear_type; + converter->get_subdiv_uvs = conv_ccg_get_subdiv_uvs; + converter->get_num_faces = conv_ccg_get_num_faces; converter->get_num_edges = conv_ccg_get_num_edges; converter->get_num_verts = conv_ccg_get_num_verts; @@ -571,6 +732,13 @@ void ccgSubSurf_converter_setup_from_ccg(CCGSubSurf *ss, converter->get_num_vert_faces = conv_ccg_get_num_vert_faces; converter->get_vert_faces = conv_ccg_get_vert_faces; + converter->get_num_uv_layers = conv_ccg_get_num_uv_layers; + converter->precalc_uv_layer = conv_ccg_precalc_uv_layer; + converter->finish_uv_layer = conv_ccg_finish_uv_layer; + converter->get_num_uvs = conv_ccg_get_num_uvs; + converter->get_uvs = conv_ccg_get_uvs; + converter->get_face_corner_uv_index = conv_ccg_get_face_corner_uv_index; + converter->free_user_data = NULL; converter->user_data = ss; } diff --git a/source/blender/blenkernel/intern/CCGSubSurf_util.c b/source/blender/blenkernel/intern/CCGSubSurf_util.c index 9af69115559..c7ef528c02f 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf_util.c +++ b/source/blender/blenkernel/intern/CCGSubSurf_util.c @@ -184,7 +184,7 @@ int ccg_ehashIterator_isStopped(EHashIterator *ehi) } /** - * Standard allocator implementarion. + * Standard allocator implementation. */ static void *_stdAllocator_alloc(CCGAllocatorHDL UNUSED(a), int numBytes) diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index f7ff1261c8a..470098f8c7c 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -95,34 +95,9 @@ bAction *add_empty_action(Main *bmain, const char name[]) /* .................................. */ // does copy_fcurve... -void BKE_action_make_local(Main *bmain, bAction *act) +void BKE_action_make_local(Main *bmain, bAction *act, const bool lib_local) { - bool is_local = false, is_lib = false; - - /* - only lib users: do nothing - * - only local users: set flag - * - mixed: make copy - */ - - if (!ID_IS_LINKED_DATABLOCK(act)) { - return; - } - - BKE_library_ID_test_usages(bmain, act, &is_local, &is_lib); - - if (is_local) { - if (!is_lib) { - id_clear_lib_data(bmain, &act->id); - BKE_id_expand_local(&act->id); - } - else { - bAction *act_new = BKE_action_copy(bmain, act); - - act_new->id.us = 0; - - BKE_libblock_remap(bmain, act, act_new, ID_REMAP_SKIP_INDIRECT_USAGE); - } - } + BKE_id_make_local_generic(bmain, &act->id, true, lib_local); } /* .................................. */ @@ -181,10 +156,7 @@ bAction *BKE_action_copy(Main *bmain, bAction *src) } } - if (ID_IS_LINKED_DATABLOCK(src)) { - BKE_id_expand_local(&dst->id); - BKE_id_lib_local_paths(bmain, src->id.lib, &dst->id); - } + BKE_id_copy_ensure_local(bmain, &src->id, &dst->id); return dst; } diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index d6f93528262..d04b950c043 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -400,8 +400,8 @@ static void make_local_strips(ListBase *strips) NlaStrip *strip; for (strip = strips->first; strip; strip = strip->next) { - if (strip->act) BKE_action_make_local(G.main, strip->act); - if (strip->remap && strip->remap->target) BKE_action_make_local(G.main, strip->remap->target); + if (strip->act) BKE_action_make_local(G.main, strip->act, false); + if (strip->remap && strip->remap->target) BKE_action_make_local(G.main, strip->remap->target, false); make_local_strips(&strip->strips); } @@ -413,10 +413,10 @@ void BKE_animdata_make_local(AnimData *adt) NlaTrack *nlt; /* Actions - Active and Temp */ - if (adt->action) BKE_action_make_local(G.main, adt->action); - if (adt->tmpact) BKE_action_make_local(G.main, adt->tmpact); + if (adt->action) BKE_action_make_local(G.main, adt->action, false); + if (adt->tmpact) BKE_action_make_local(G.main, adt->tmpact, false); /* Remaps */ - if (adt->remap && adt->remap->target) BKE_action_make_local(G.main, adt->remap->target); + if (adt->remap && adt->remap->target) BKE_action_make_local(G.main, adt->remap->target, false); /* Drivers */ /* TODO: need to remap the ID-targets too? */ diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 5f564e1c4d2..c644fe09364 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -144,34 +144,9 @@ void BKE_armature_free(bArmature *arm) } } -void BKE_armature_make_local(Main *bmain, bArmature *arm) +void BKE_armature_make_local(Main *bmain, bArmature *arm, const bool lib_local) { - bool is_local = false, is_lib = false; - - /* - only lib users: do nothing - * - only local users: set flag - * - mixed: make copy - */ - - if (!ID_IS_LINKED_DATABLOCK(arm)) { - return; - } - - BKE_library_ID_test_usages(bmain, arm, &is_local, &is_lib); - - if (is_local) { - if (!is_lib) { - id_clear_lib_data(bmain, &arm->id); - BKE_id_expand_local(&arm->id); - } - else { - bArmature *arm_new = BKE_armature_copy(bmain, arm); - - arm_new->id.us = 0; - - BKE_libblock_remap(bmain, arm, arm_new, ID_REMAP_SKIP_INDIRECT_USAGE); - } - } + BKE_id_make_local_generic(bmain, &arm->id, true, lib_local); } static void copy_bonechildren(Bone *newBone, Bone *oldBone, Bone *actBone, Bone **newActBone) @@ -219,10 +194,7 @@ bArmature *BKE_armature_copy(Main *bmain, bArmature *arm) newArm->act_edbone = NULL; newArm->sketch = NULL; - if (ID_IS_LINKED_DATABLOCK(arm)) { - BKE_id_expand_local(&newArm->id); - BKE_id_lib_local_paths(bmain, arm->id.lib, &newArm->id); - } + BKE_id_copy_ensure_local(bmain, &arm->id, &newArm->id); return newArm; } @@ -1931,6 +1903,17 @@ static int rebuild_pose_bone(bPose *pose, Bone *bone, bPoseChannel *parchan, int return counter; } +/** + * Clear pointers of object's pose (needed in remap case, since we cannot always wait for a complete pose rebuild). + */ +void BKE_pose_clear_pointers(bPose *pose) +{ + for (bPoseChannel *pchan = pose->chanbase.first; pchan; pchan = pchan->next) { + pchan->bone = NULL; + pchan->child = NULL; + } +} + /* only after leave editmode, duplicating, validating older files, library syncing */ /* NOTE: pose->flag is set for it */ void BKE_pose_rebuild(Object *ob, bArmature *arm) @@ -1951,10 +1934,7 @@ void BKE_pose_rebuild(Object *ob, bArmature *arm) pose = ob->pose; /* clear */ - for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { - pchan->bone = NULL; - pchan->child = NULL; - } + BKE_pose_clear_pointers(pose); /* first step, check if all channels are there */ for (bone = arm->bonebase.first; bone; bone = bone->next) { diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index ece17335fa0..ef8a2f100dc 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -224,7 +224,7 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos } /* make a new Spline-IK chain, and store it in the IK chains */ - /* TODO: we should check if there is already an IK chain on this, since that would take presidence... */ + /* TODO: we should check if there is already an IK chain on this, since that would take precedence... */ { /* make new tree */ tSplineIK_Tree *tree = MEM_callocN(sizeof(tSplineIK_Tree), "SplineIK Tree"); @@ -696,7 +696,7 @@ void BKE_pose_eval_flush(EvaluationContext *UNUSED(eval_ctx), void BKE_pose_eval_proxy_copy(EvaluationContext *UNUSED(eval_ctx), Object *ob) { - BLI_assert(ID_IS_LINKED_DATABLOCK(ob) && ob->proxy_from != NULL); + BLI_assert(ID_IS_LINKED(ob) && ob->proxy_from != NULL); DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) { printf("Proxy copy error, lib Object: %s proxy Object: %s\n", diff --git a/source/blender/blenkernel/intern/asset.c b/source/blender/blenkernel/intern/asset_engine.c index 3f4894d41c5..8fa651bdef1 100644 --- a/source/blender/blenkernel/intern/asset.c +++ b/source/blender/blenkernel/intern/asset_engine.c @@ -25,7 +25,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/blenkernel/intern/asset.c +/** \file blender/blenkernel/intern/asset_engine.c * \ingroup bke */ @@ -48,7 +48,7 @@ #include "PIL_time.h" -#include "BKE_asset.h" +#include "BKE_asset_engine.h" #include "BKE_global.h" #include "BKE_idprop.h" #include "BKE_library.h" @@ -405,7 +405,7 @@ void BKE_filedir_entryarr_clear(FileDirEntryArr *array) array->nbr_entries_filtered = 0; } -/* GHash helpers */ +/* Various helpers */ unsigned int BKE_asset_uuid_hash(const void *key) { return BLI_hash_mm2((const unsigned char *)key, sizeof(AssetUUID), 0); @@ -418,4 +418,11 @@ bool BKE_asset_uuid_cmp(const void *a, const void *b) return !ASSETUUID_COMPARE(uuid1, uuid2); /* Expects false when compared equal... */ } - +void BKE_asset_uuid_print(const AssetUUID *uuid) +{ + /* TODO print nicer (as 128bit hexadecimal...). */ + printf("[%d,%d,%d,%d][%d,%d,%d,%d][%d,%d,%d,%d]\n", + uuid->uuid_asset[0], uuid->uuid_asset[1], uuid->uuid_asset[2], uuid->uuid_asset[3], + uuid->uuid_variant[0], uuid->uuid_variant[1], uuid->uuid_variant[2], uuid->uuid_variant[3], + uuid->uuid_revision[0], uuid->uuid_revision[1], uuid->uuid_revision[2], uuid->uuid_revision[3]); +} diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index 25491bcb998..3740fdca740 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -47,7 +47,7 @@ #include "IMB_imbuf.h" #include "IMB_moviecache.h" -#include "BKE_asset.h" +#include "BKE_asset_engine.h" #include "BKE_blender.h" /* own include */ #include "BKE_blender_version.h" /* own include */ #include "BKE_blendfile.h" diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index a708c59fa97..d079583f9a8 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -424,7 +424,7 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int { const char *absbase = (flag & BKE_BPATH_TRAVERSE_ABS) ? ID_BLEND_PATH(bmain, id) : NULL; - if ((flag & BKE_BPATH_TRAVERSE_SKIP_LIBRARY) && ID_IS_LINKED_DATABLOCK(id)) { + if ((flag & BKE_BPATH_TRAVERSE_SKIP_LIBRARY) && ID_IS_LINKED(id)) { return; } diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index 20621feac6c..da58ad332ba 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -197,10 +197,7 @@ Brush *BKE_brush_copy(Main *bmain, Brush *brush) /* enable fake user by default */ id_fake_user_set(&brush->id); - if (ID_IS_LINKED_DATABLOCK(brush)) { - BKE_id_expand_local(&brushn->id); - BKE_id_lib_local_paths(bmain, brush->id.lib, &brushn->id); - } + BKE_id_copy_ensure_local(bmain, &brush->id, &brushn->id); return brushn; } @@ -219,27 +216,27 @@ void BKE_brush_free(Brush *brush) BKE_previewimg_free(&(brush->preview)); } -void BKE_brush_make_local(Main *bmain, Brush *brush) +void BKE_brush_make_local(Main *bmain, Brush *brush, const bool lib_local) { bool is_local = false, is_lib = false; - /* - only lib users: do nothing + /* - only lib users: do nothing (unless force_local is set) * - only local users: set flag * - mixed: make copy */ - if (!ID_IS_LINKED_DATABLOCK(brush)) { + if (!ID_IS_LINKED(brush)) { return; } if (brush->clone.image) { /* Special case: ima always local immediately. Clone image should only have one user anyway. */ - id_make_local(bmain, &brush->clone.image->id, false); + id_make_local(bmain, &brush->clone.image->id, false, false); } BKE_library_ID_test_usages(bmain, brush, &is_local, &is_lib); - if (is_local) { + if (lib_local || is_local) { if (!is_lib) { id_clear_lib_data(bmain, &brush->id); BKE_id_expand_local(&brush->id); @@ -252,7 +249,9 @@ void BKE_brush_make_local(Main *bmain, Brush *brush) brush_new->id.us = 0; - BKE_libblock_remap(bmain, brush, brush_new, ID_REMAP_SKIP_INDIRECT_USAGE); + if (!lib_local) { + BKE_libblock_remap(bmain, brush, brush_new, ID_REMAP_SKIP_INDIRECT_USAGE); + } } } } diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index ae7aac8b54f..85ce399b770 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -78,8 +78,8 @@ void BKE_camera_init(Camera *cam) /* stereoscopy 3d */ cam->stereo.interocular_distance = 0.065f; cam->stereo.convergence_distance = 30.f * 0.065f; - cam->stereo.pole_merge_angle_from = DEG2RAD(60.0f); - cam->stereo.pole_merge_angle_to = DEG2RAD(75.0f); + cam->stereo.pole_merge_angle_from = DEG2RADF(60.0f); + cam->stereo.pole_merge_angle_to = DEG2RADF(75.0f); } void *BKE_camera_add(Main *bmain, const char *name) @@ -99,42 +99,14 @@ Camera *BKE_camera_copy(Main *bmain, Camera *cam) camn = BKE_libblock_copy(bmain, &cam->id); - if (ID_IS_LINKED_DATABLOCK(cam)) { - BKE_id_expand_local(&camn->id); - BKE_id_lib_local_paths(bmain, cam->id.lib, &camn->id); - } + BKE_id_copy_ensure_local(bmain, &cam->id, &camn->id); return camn; } -void BKE_camera_make_local(Main *bmain, Camera *cam) +void BKE_camera_make_local(Main *bmain, Camera *cam, const bool lib_local) { - bool is_local = false, is_lib = false; - - /* - only lib users: do nothing - * - only local users: set flag - * - mixed: make copy - */ - - if (!ID_IS_LINKED_DATABLOCK(cam)) { - return; - } - - BKE_library_ID_test_usages(bmain, cam, &is_local, &is_lib); - - if (is_local) { - if (!is_lib) { - id_clear_lib_data(bmain, &cam->id); - BKE_id_expand_local(&cam->id); - } - else { - Camera *cam_new = BKE_camera_copy(bmain, cam); - - cam_new->id.us = 0; - - BKE_libblock_remap(bmain, cam, cam_new, ID_REMAP_SKIP_INDIRECT_USAGE); - } - } + BKE_id_make_local_generic(bmain, &cam->id, true, lib_local); } /** Free (or release) any data used by this camera (does not free the camera itself). */ diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 2932939b208..53a74024c51 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -982,6 +982,7 @@ static void save_sample_line(Scopes *scopes, const int idx, const float fx, cons /* waveform */ switch (scopes->wavefrm_mode) { case SCOPES_WAVEFRM_RGB: + case SCOPES_WAVEFRM_RGB_PARADE: scopes->waveform_1[idx + 0] = fx; scopes->waveform_1[idx + 1] = rgb[0]; scopes->waveform_2[idx + 0] = fx; @@ -1265,6 +1266,8 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings * switch (scopes->wavefrm_mode) { case SCOPES_WAVEFRM_RGB: + /* fall-through */ + case SCOPES_WAVEFRM_RGB_PARADE: ycc_mode = -1; break; case SCOPES_WAVEFRM_LUMA: diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 4c9ddd495e3..1f2cc2e4ad8 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -4649,7 +4649,7 @@ void BKE_constraints_id_loop(ListBase *conlist, ConstraintIDFunc func, void *use /* helper for BKE_constraints_copy(), to be used for making sure that ID's are valid */ static void con_extern_cb(bConstraint *UNUSED(con), ID **idpoin, bool UNUSED(is_reference), void *UNUSED(userData)) { - if (*idpoin && ID_IS_LINKED_DATABLOCK(*idpoin)) + if (*idpoin && ID_IS_LINKED(*idpoin)) id_lib_extern(*idpoin); } diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 0e634e21ea3..90a514781d7 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -207,45 +207,14 @@ Curve *BKE_curve_copy(Main *bmain, Curve *cu) id_us_plus((ID *)cun->vfonti); id_us_plus((ID *)cun->vfontbi); - if (ID_IS_LINKED_DATABLOCK(cu)) { - BKE_id_expand_local(&cun->id); - BKE_id_lib_local_paths(bmain, cu->id.lib, &cun->id); - } + BKE_id_copy_ensure_local(bmain, &cu->id, &cun->id); return cun; } -void BKE_curve_make_local(Main *bmain, Curve *cu) +void BKE_curve_make_local(Main *bmain, Curve *cu, const bool lib_local) { - bool is_local = false, is_lib = false; - - /* - when there are only lib users: don't do - * - when there are only local users: set flag - * - mixed: do a copy - */ - - if (!ID_IS_LINKED_DATABLOCK(cu)) { - return; - } - - BKE_library_ID_test_usages(bmain, cu, &is_local, &is_lib); - - if (is_local) { - if (!is_lib) { - id_clear_lib_data(bmain, &cu->id); - if (cu->key) { - BKE_key_make_local(bmain, cu->key); - } - BKE_id_expand_local(&cu->id); - } - else { - Curve *cu_new = BKE_curve_copy(bmain, cu); - - cu_new->id.us = 0; - - BKE_libblock_remap(bmain, cu, cu_new, ID_REMAP_SKIP_INDIRECT_USAGE); - } - } + BKE_id_make_local_generic(bmain, &cu->id, true, lib_local); } /* Get list of nurbs from editnurbs structure */ diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c index 7292ed2b5c5..839673c192b 100644 --- a/source/blender/blenkernel/intern/data_transfer.c +++ b/source/blender/blenkernel/intern/data_transfer.c @@ -356,7 +356,7 @@ static MeshRemapIslandsCalc data_transfer_get_loop_islands_generator(const int c { switch (cddata_type) { case CD_FAKE_UV: - return BKE_mesh_calc_islands_loop_poly_uv; + return BKE_mesh_calc_islands_loop_poly_edgeseam; default: break; } diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 2b097f31c59..d35de6fc5d3 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -4483,7 +4483,7 @@ static void dynamicPaint_doSmudge(DynamicPaintSurface *surface, DynamicPaintBrus CLAMP_MIN(max_velocity, vel); } - steps = (int)ceil(max_velocity / bData->average_dist * timescale); + steps = (int)ceil((double)max_velocity / bData->average_dist * (double)timescale); CLAMP(steps, 0, 12); eff_scale = brush->smudge_strength / (float)steps * timescale; @@ -4634,7 +4634,7 @@ static int dynamicPaint_prepareEffectStep( /* calculate average values (single thread) */ for (int index = 0; index < sData->total_points; index++) { - average_force += (*force)[index * 4 + 3]; + average_force += (double)(*force)[index * 4 + 3]; } average_force /= sData->total_points; } @@ -4651,7 +4651,7 @@ static int dynamicPaint_prepareEffectStep( shrink_speed = surface->shrink_speed; fastest_effect = max_fff(spread_speed, shrink_speed, average_force); - avg_dist = bData->average_dist * CANVAS_REL_SIZE / getSurfaceDimension(sData); + avg_dist = bData->average_dist * (double)CANVAS_REL_SIZE / (double)getSurfaceDimension(sData); steps = (int)ceilf(1.5f * EFF_MOVEMENT_PER_FRAME * fastest_effect / avg_dist * timescale); CLAMP(steps, 1, 20); @@ -5009,7 +5009,8 @@ static void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescal const float wave_scale = CANVAS_REL_SIZE / canvas_size; /* allocate memory */ - PaintWavePoint *prevPoint = MEM_mallocN(sData->total_points * sizeof(PaintWavePoint), "Temp previous points for wave simulation"); + PaintWavePoint *prevPoint = MEM_mallocN( + sData->total_points * sizeof(PaintWavePoint), __func__); if (!prevPoint) return; @@ -5019,13 +5020,14 @@ static void dynamicPaint_doWaveStep(DynamicPaintSurface *surface, float timescal int numOfNeighs = sData->adj_data->n_num[index]; for (i = 0; i < numOfNeighs; i++) { - average_dist += bNeighs[sData->adj_data->n_index[index] + i].dist; + average_dist += (double)bNeighs[sData->adj_data->n_index[index] + i].dist; } } - average_dist *= wave_scale / sData->adj_data->total_targets; + average_dist *= (double)wave_scale / sData->adj_data->total_targets; /* determine number of required steps */ - steps = (int)ceil((WAVE_TIME_FAC * timescale * surface->wave_timescale) / (average_dist / wave_speed / 3)); + steps = (int)ceil((double)(WAVE_TIME_FAC * timescale * surface->wave_timescale) / + (average_dist / (double)wave_speed / 3)); CLAMP(steps, 1, 20); timescale /= steps; diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 5e1f8814ed6..580842fe176 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -309,6 +309,11 @@ VFont *BKE_vfont_load_exists(struct Main *bmain, const char *filepath) return BKE_vfont_load_exists_ex(bmain, filepath, NULL); } +void BKE_vfont_make_local(Main *bmain, VFont *vfont, const bool lib_local) +{ + BKE_id_make_local_generic(bmain, &vfont->id, true, lib_local); +} + static VFont *which_vfont(Curve *cu, CharInfo *info) { switch (info->flag & (CU_CHINFO_BOLD | CU_CHINFO_ITALIC)) { diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index ac4f566dc62..8621da0d42e 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -390,6 +390,11 @@ bGPdata *gpencil_data_duplicate(Main *bmain, bGPdata *src, bool internal_copy) return dst; } +void BKE_gpencil_make_local(Main *bmain, bGPdata *gpd, const bool lib_local) +{ + BKE_id_make_local_generic(bmain, &gpd->id, true, lib_local); +} + /* -------- GP-Stroke API --------- */ /* ensure selection status of stroke is in sync with its points */ diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index 11bbd91e9c9..9b011dbb003 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -97,14 +97,16 @@ Group *BKE_group_copy(Main *bmain, Group *group) /* Do not copy group's preview (same behavior as for objects). */ groupn->preview = NULL; - if (ID_IS_LINKED_DATABLOCK(group)) { - BKE_id_expand_local(&groupn->id); - BKE_id_lib_local_paths(bmain, group->id.lib, &groupn->id); - } + BKE_id_copy_ensure_local(bmain, &group->id, &groupn->id); return groupn; } +void BKE_group_make_local(Main *bmain, Group *group, const bool lib_local) +{ + BKE_id_make_local_generic(bmain, &group->id, true, lib_local); +} + /* external */ static bool group_object_add_internal(Group *group, Object *ob) { diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index f3e86b44459..2d5b15c8f9d 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -221,6 +221,24 @@ PreviewImage *BKE_previewimg_copy(PreviewImage *prv) return prv_img; } +/** Duplicate preview image from \a id and clear icon_id, to be used by datablock copy functions. */ +void BKE_previewimg_id_copy(ID *new_id, ID *old_id) +{ + PreviewImage **old_prv_p = BKE_previewimg_id_get_p(old_id); + PreviewImage **new_prv_p = BKE_previewimg_id_get_p(new_id); + + if (old_prv_p && *old_prv_p) { + BLI_assert(new_prv_p != NULL && ELEM(*new_prv_p, NULL, *old_prv_p)); +// const int new_icon_id = get_next_free_id(); + +// if (new_icon_id == 0) { +// return; /* Failure. */ +// } + *new_prv_p = BKE_previewimg_copy(*old_prv_p); + new_id->icon_id = (*new_prv_p)->icon_id = 0; + } +} + PreviewImage **BKE_previewimg_id_get_p(ID *id) { switch (GS(id->name)) { @@ -423,10 +441,26 @@ void BKE_icon_changed(int id) } } -int BKE_icon_id_ensure(struct ID *id) +static int icon_id_ensure_create_icon(struct ID *id) { Icon *new_icon = NULL; + new_icon = MEM_mallocN(sizeof(Icon), __func__); + + new_icon->obj = id; + new_icon->type = GS(id->name); + + /* next two lines make sure image gets created */ + new_icon->drawinfo = NULL; + new_icon->drawinfo_free = NULL; + + BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(id->icon_id), new_icon); + + return id->icon_id; +} + +int BKE_icon_id_ensure(struct ID *id) +{ if (!id || G.background) return 0; @@ -440,32 +474,39 @@ int BKE_icon_id_ensure(struct ID *id) return 0; } - new_icon = MEM_mallocN(sizeof(Icon), __func__); - - new_icon->obj = id; - new_icon->type = GS(id->name); - - /* next two lines make sure image gets created */ - new_icon->drawinfo = NULL; - new_icon->drawinfo_free = NULL; + /* Ensure we synchronize ID icon_id with its previewimage if it has one. */ + PreviewImage **p_prv = BKE_previewimg_id_get_p(id); + if (p_prv && *p_prv) { + BLI_assert(ELEM((*p_prv)->icon_id, 0, id->icon_id)); + (*p_prv)->icon_id = id->icon_id; + } - BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(id->icon_id), new_icon); - - return id->icon_id; + return icon_id_ensure_create_icon(id); } /** * Return icon id of given preview, or create new icon if not found. */ -int BKE_icon_preview_ensure(PreviewImage *preview) +int BKE_icon_preview_ensure(ID *id, PreviewImage *preview) { Icon *new_icon = NULL; if (!preview || G.background) return 0; - if (preview->icon_id) + if (id) { + BLI_assert(BKE_previewimg_id_ensure(id) == preview); + } + + if (preview->icon_id) { + BLI_assert(!id || !id->icon_id || id->icon_id == preview->icon_id); + return preview->icon_id; + } + + if (id && id->icon_id) { + preview->icon_id = id->icon_id; return preview->icon_id; + } preview->icon_id = get_next_free_id(); @@ -474,6 +515,12 @@ int BKE_icon_preview_ensure(PreviewImage *preview) return 0; } + /* Ensure we synchronize ID icon_id with its previewimage if available, and generate suitable 'ID' icon. */ + if (id) { + id->icon_id = preview->icon_id; + return icon_id_ensure_create_icon(id); + } + new_icon = MEM_mallocN(sizeof(Icon), __func__); new_icon->obj = preview; diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index f6f38977402..ea28dabb945 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -456,47 +456,20 @@ Image *BKE_image_copy(Main *bmain, Image *ima) copy_image_packedfiles(&nima->packedfiles, &ima->packedfiles); - nima->stereo3d_format = MEM_dupallocN(ima->stereo3d_format); + /* nima->stere3d_format is already allocated by image_alloc... */ + *nima->stereo3d_format = *ima->stereo3d_format; BLI_duplicatelist(&nima->views, &ima->views); - nima->preview = BKE_previewimg_copy(ima->preview); + BKE_previewimg_id_copy(&nima->id, &ima->id); - if (ID_IS_LINKED_DATABLOCK(ima)) { - BKE_id_expand_local(&nima->id); - BKE_id_lib_local_paths(bmain, ima->id.lib, &nima->id); - } + BKE_id_copy_ensure_local(bmain, &ima->id, &nima->id); return nima; } -void BKE_image_make_local(Main *bmain, Image *ima) +void BKE_image_make_local(Main *bmain, Image *ima, const bool lib_local) { - bool is_local = false, is_lib = false; - - /* - only lib users: do nothing - * - only local users: set flag - * - mixed: make copy - */ - - if (!ID_IS_LINKED_DATABLOCK(ima)) { - return; - } - - BKE_library_ID_test_usages(bmain, ima, &is_local, &is_lib); - - if (is_local) { - if (!is_lib) { - id_clear_lib_data(bmain, &ima->id); - BKE_id_expand_local(&ima->id); - } - else { - Image *ima_new = BKE_image_copy(bmain, ima); - - ima_new->id.us = 0; - - BKE_libblock_remap(bmain, ima, ima_new, ID_REMAP_SKIP_INDIRECT_USAGE); - } - } + BKE_id_make_local_generic(bmain, &ima->id, true, lib_local); } void BKE_image_merge(Image *dest, Image *source) @@ -1083,43 +1056,55 @@ int BKE_image_imtype_to_ftype(const char imtype, ImbFormatOptions *r_options) { memset(r_options, 0, sizeof(*r_options)); - if (imtype == R_IMF_IMTYPE_TARGA) + if (imtype == R_IMF_IMTYPE_TARGA) { return IMB_FTYPE_TGA; + } else if (imtype == R_IMF_IMTYPE_RAWTGA) { r_options->flag = RAWTGA; return IMB_FTYPE_TGA; } - else if (imtype == R_IMF_IMTYPE_IRIS) + else if (imtype == R_IMF_IMTYPE_IRIS) { return IMB_FTYPE_IMAGIC; + } #ifdef WITH_HDR - else if (imtype == R_IMF_IMTYPE_RADHDR) + else if (imtype == R_IMF_IMTYPE_RADHDR) { return IMB_FTYPE_RADHDR; + } #endif else if (imtype == R_IMF_IMTYPE_PNG) { r_options->quality = 15; return IMB_FTYPE_PNG; } #ifdef WITH_DDS - else if (imtype == R_IMF_IMTYPE_DDS) + else if (imtype == R_IMF_IMTYPE_DDS) { return IMB_FTYPE_DDS; + } #endif - else if (imtype == R_IMF_IMTYPE_BMP) + else if (imtype == R_IMF_IMTYPE_BMP) { return IMB_FTYPE_BMP; + } #ifdef WITH_TIFF - else if (imtype == R_IMF_IMTYPE_TIFF) + else if (imtype == R_IMF_IMTYPE_TIFF) { return IMB_FTYPE_TIF; + } #endif - else if (imtype == R_IMF_IMTYPE_OPENEXR || imtype == R_IMF_IMTYPE_MULTILAYER) + else if (imtype == R_IMF_IMTYPE_OPENEXR || imtype == R_IMF_IMTYPE_MULTILAYER) { return IMB_FTYPE_OPENEXR; + } #ifdef WITH_CINEON - else if (imtype == R_IMF_IMTYPE_CINEON) + else if (imtype == R_IMF_IMTYPE_CINEON) { return IMB_FTYPE_CINEON; - else if (imtype == R_IMF_IMTYPE_DPX) + } + else if (imtype == R_IMF_IMTYPE_DPX) { return IMB_FTYPE_DPX; + } #endif #ifdef WITH_OPENJPEG - else if (imtype == R_IMF_IMTYPE_JP2) + else if (imtype == R_IMF_IMTYPE_JP2) { + r_options->flag |= JP2_JP2; + r_options->quality = 90; return IMB_FTYPE_JP2; + } #endif else { r_options->quality = 90; @@ -1129,46 +1114,60 @@ int BKE_image_imtype_to_ftype(const char imtype, ImbFormatOptions *r_options) char BKE_image_ftype_to_imtype(const int ftype, const ImbFormatOptions *options) { - if (ftype == 0) + if (ftype == 0) { return R_IMF_IMTYPE_TARGA; - else if (ftype == IMB_FTYPE_IMAGIC) + } + else if (ftype == IMB_FTYPE_IMAGIC) { return R_IMF_IMTYPE_IRIS; + } #ifdef WITH_HDR - else if (ftype == IMB_FTYPE_RADHDR) + else if (ftype == IMB_FTYPE_RADHDR) { return R_IMF_IMTYPE_RADHDR; + } #endif - else if (ftype == IMB_FTYPE_PNG) + else if (ftype == IMB_FTYPE_PNG) { return R_IMF_IMTYPE_PNG; + } #ifdef WITH_DDS - else if (ftype == IMB_FTYPE_DDS) + else if (ftype == IMB_FTYPE_DDS) { return R_IMF_IMTYPE_DDS; + } #endif - else if (ftype == IMB_FTYPE_BMP) + else if (ftype == IMB_FTYPE_BMP) { return R_IMF_IMTYPE_BMP; + } #ifdef WITH_TIFF - else if (ftype == IMB_FTYPE_TIF) + else if (ftype == IMB_FTYPE_TIF) { return R_IMF_IMTYPE_TIFF; + } #endif - else if (ftype == IMB_FTYPE_OPENEXR) + else if (ftype == IMB_FTYPE_OPENEXR) { return R_IMF_IMTYPE_OPENEXR; + } #ifdef WITH_CINEON - else if (ftype == IMB_FTYPE_CINEON) + else if (ftype == IMB_FTYPE_CINEON) { return R_IMF_IMTYPE_CINEON; - else if (ftype == IMB_FTYPE_DPX) + } + else if (ftype == IMB_FTYPE_DPX) { return R_IMF_IMTYPE_DPX; + } #endif else if (ftype == IMB_FTYPE_TGA) { - if (options && (options->flag & RAWTGA)) + if (options && (options->flag & RAWTGA)) { return R_IMF_IMTYPE_RAWTGA; - else + } + else { return R_IMF_IMTYPE_TARGA; + } } #ifdef WITH_OPENJPEG - else if (ftype == IMB_FTYPE_JP2) + else if (ftype == IMB_FTYPE_JP2) { return R_IMF_IMTYPE_JP2; + } #endif - else + else { return R_IMF_IMTYPE_JPEG90; + } } diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index e59facd3c39..6cdeaf5e59b 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -170,10 +170,7 @@ Key *BKE_key_copy(Main *bmain, Key *key) kb = kb->next; } - if (ID_IS_LINKED_DATABLOCK(key)) { - BKE_id_expand_local(&keyn->id); - BKE_id_lib_local_paths(bmain, key->id.lib, &keyn->id); - } + BKE_id_copy_ensure_local(bmain, &key->id, &keyn->id); return keyn; } @@ -203,18 +200,6 @@ Key *BKE_key_copy_nolib(Key *key) return keyn; } -void BKE_key_make_local(Main *bmain, Key *key) -{ - /* Note that here for now we simply just make it local... - * Sounds fishy behavior, but since skeys are not *real* IDs... */ - - if (!ID_IS_LINKED_DATABLOCK(key)) { - return; - } - - id_clear_lib_data(bmain, &key->id); -} - /* Sort shape keys and Ipo curves after a change. This assumes that at most * one key was moved, which is a valid assumption for the places it's * currently being called. diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c index 003b154a70b..e9d039ad480 100644 --- a/source/blender/blenkernel/intern/lamp.c +++ b/source/blender/blenkernel/intern/lamp.c @@ -135,13 +135,10 @@ Lamp *BKE_lamp_copy(Main *bmain, Lamp *la) if (la->nodetree) lan->nodetree = ntreeCopyTree(bmain, la->nodetree); - - lan->preview = BKE_previewimg_copy(la->preview); - if (ID_IS_LINKED_DATABLOCK(la)) { - BKE_id_expand_local(&lan->id); - BKE_id_lib_local_paths(bmain, la->id.lib, &lan->id); - } + BKE_previewimg_id_copy(&lan->id, &la->id); + + BKE_id_copy_ensure_local(bmain, &la->id, &lan->id); return lan; } @@ -172,34 +169,9 @@ Lamp *localize_lamp(Lamp *la) return lan; } -void BKE_lamp_make_local(Main *bmain, Lamp *la) +void BKE_lamp_make_local(Main *bmain, Lamp *la, const bool lib_local) { - bool is_local = false, is_lib = false; - - /* - only lib users: do nothing - * - only local users: set flag - * - mixed: make copy - */ - - if (!ID_IS_LINKED_DATABLOCK(la)) { - return; - } - - BKE_library_ID_test_usages(bmain, la, &is_local, &is_lib); - - if (is_local) { - if (!is_lib) { - id_clear_lib_data(bmain, &la->id); - BKE_id_expand_local(&la->id); - } - else { - Lamp *la_new = BKE_lamp_copy(bmain, la); - - la_new->id.us = 0; - - BKE_libblock_remap(bmain, la, la_new, ID_REMAP_SKIP_INDIRECT_USAGE); - } - } + BKE_id_make_local_generic(bmain, &la->id, true, lib_local); } void BKE_lamp_free(Lamp *la) diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 67f49266efc..b0671f33094 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -297,10 +297,7 @@ Lattice *BKE_lattice_copy(Main *bmain, Lattice *lt) ltn->editlatt = NULL; - if (ID_IS_LINKED_DATABLOCK(lt)) { - BKE_id_expand_local(<n->id); - BKE_id_lib_local_paths(bmain, lt->id.lib, <n->id); - } + BKE_id_copy_ensure_local(bmain, <->id, <n->id); return ltn; } @@ -330,37 +327,9 @@ void BKE_lattice_free(Lattice *lt) } -void BKE_lattice_make_local(Main *bmain, Lattice *lt) +void BKE_lattice_make_local(Main *bmain, Lattice *lt, const bool lib_local) { - bool is_local = false, is_lib = false; - - /* - only lib users: do nothing - * - only local users: set flag - * - mixed: make copy - */ - - if (!ID_IS_LINKED_DATABLOCK(lt)) { - return; - } - - BKE_library_ID_test_usages(bmain, lt, &is_local, &is_lib); - - if (is_local) { - if (!is_lib) { - id_clear_lib_data(bmain, <->id); - if (lt->key) { - BKE_key_make_local(bmain, lt->key); - } - BKE_id_expand_local(<->id); - } - else { - Lattice *lt_new = BKE_lattice_copy(bmain, lt); - - lt_new->id.us = 0; - - BKE_libblock_remap(bmain, lt, lt_new, ID_REMAP_SKIP_INDIRECT_USAGE); - } - } + BKE_id_make_local_generic(bmain, <->id, true, lib_local); } typedef struct LatticeDeformData { diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 5fd929d6732..f19f1b45be6 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -76,12 +76,10 @@ #include "BLT_translation.h" #include "RNA_access.h" -#include "RNA_types.h" #include "BKE_action.h" #include "BKE_animsys.h" #include "BKE_armature.h" -#include "BKE_asset.h" #include "BKE_bpath.h" #include "BKE_brush.h" #include "BKE_camera.h" @@ -100,6 +98,7 @@ #include "BKE_lattice.h" #include "BKE_library.h" #include "BKE_library_query.h" +#include "BKE_library_remap.h" #include "BKE_linestyle.h" #include "BKE_mesh.h" #include "BKE_material.h" @@ -110,6 +109,7 @@ #include "BKE_object.h" #include "BKE_particle.h" #include "BKE_packedFile.h" +#include "BKE_sound.h" #include "BKE_speaker.h" #include "BKE_scene.h" #include "BKE_text.h" @@ -134,6 +134,10 @@ * also note that the id _must_ have a library - campbell */ void BKE_id_lib_local_paths(Main *bmain, Library *lib, ID *id) { + if (lib->flag & LIBRARY_FLAG_VIRTUAL) { + return; + } + const char *bpath_user_data[2] = {bmain->name, lib->filepath}; BKE_bpath_traverse_id(bmain, id, @@ -144,7 +148,7 @@ void BKE_id_lib_local_paths(Main *bmain, Library *lib, ID *id) void id_lib_extern(ID *id) { - if (id && ID_IS_LINKED_DATABLOCK(id)) { + if (id && ID_IS_LINKED(id)) { BLI_assert(BKE_idcode_is_linkable(GS(id->name))); if (id->tag & LIB_TAG_INDIRECT) { id->tag -= LIB_TAG_INDIRECT; @@ -271,90 +275,158 @@ void BKE_id_expand_local(ID *id) BKE_library_foreach_ID_link(id, id_expand_local_callback, NULL, 0); } -/* calls the appropriate make_local method for the block, unless test. Returns true - * if the block can be made local. */ -bool id_make_local(Main *bmain, ID *id, bool test) +/** + * Ensure new (copied) ID is fully made local. + */ +void BKE_id_copy_ensure_local(Main *bmain, ID *old_id, ID *new_id) +{ + if (ID_IS_LINKED(old_id)) { + BKE_id_expand_local(new_id); + BKE_id_lib_local_paths(bmain, old_id->lib, new_id); + } +} + +/** + * Generic 'make local' function, works for most of datablock types... + */ +void BKE_id_make_local_generic(Main *bmain, ID *id, const bool id_in_mainlist, const bool lib_local) +{ + bool is_local = false, is_lib = false; + + /* - only lib users: do nothing (unless force_local is set) + * - only local users: set flag + * - mixed: make copy + * In case we make a whole lib's content local, we always want to localize, and we skip remapping (done later). + */ + + if (!ID_IS_LINKED(id)) { + return; + } + + BKE_library_ID_test_usages(bmain, id, &is_local, &is_lib); + + if (lib_local || is_local) { + if (!is_lib) { + id_clear_lib_data_ex(bmain, id, id_in_mainlist); + BKE_id_expand_local(id); + } + else { + ID *id_new; + + /* Should not fail in expected usecases, but id_copy does not copy Scene e.g. */ + if (id_copy(bmain, id, &id_new, false)) { + id_new->us = 0; + + if (!lib_local) { + BKE_libblock_remap(bmain, id, id_new, ID_REMAP_SKIP_INDIRECT_USAGE); + } + } + } + } + +} + +/** + * Calls the appropriate make_local method for the block, unless test is set. + * + * \param lib_local Special flag used when making a whole library's content local, it needs specific handling. + * + * \return true if the block can be made local. + */ +bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local) { if (id->tag & LIB_TAG_INDIRECT) return false; switch (GS(id->name)) { case ID_SCE: - return false; /* not implemented */ + /* Partially implemented (has no copy...). */ + if (!test) BKE_scene_make_local(bmain, (Scene *)id, lib_local); + return true; case ID_LI: return false; /* can't be linked */ case ID_OB: - if (!test) BKE_object_make_local(bmain, (Object *)id); + if (!test) BKE_object_make_local(bmain, (Object *)id, lib_local); return true; case ID_ME: - if (!test) BKE_mesh_make_local(bmain, (Mesh *)id); + if (!test) BKE_mesh_make_local(bmain, (Mesh *)id, lib_local); return true; case ID_CU: - if (!test) BKE_curve_make_local(bmain, (Curve *)id); + if (!test) BKE_curve_make_local(bmain, (Curve *)id, lib_local); return true; case ID_MB: - if (!test) BKE_mball_make_local(bmain, (MetaBall *)id); + if (!test) BKE_mball_make_local(bmain, (MetaBall *)id, lib_local); return true; case ID_MA: - if (!test) BKE_material_make_local(bmain, (Material *)id); + if (!test) BKE_material_make_local(bmain, (Material *)id, lib_local); return true; case ID_TE: - if (!test) BKE_texture_make_local(bmain, (Tex *)id); + if (!test) BKE_texture_make_local(bmain, (Tex *)id, lib_local); return true; case ID_IM: - if (!test) BKE_image_make_local(bmain, (Image *)id); + if (!test) BKE_image_make_local(bmain, (Image *)id, lib_local); return true; case ID_LT: - if (!test) BKE_lattice_make_local(bmain, (Lattice *)id); + if (!test) BKE_lattice_make_local(bmain, (Lattice *)id, lib_local); return true; case ID_LA: - if (!test) BKE_lamp_make_local(bmain, (Lamp *)id); + if (!test) BKE_lamp_make_local(bmain, (Lamp *)id, lib_local); return true; case ID_CA: - if (!test) BKE_camera_make_local(bmain, (Camera *)id); + if (!test) BKE_camera_make_local(bmain, (Camera *)id, lib_local); return true; case ID_SPK: - if (!test) BKE_speaker_make_local(bmain, (Speaker *)id); + if (!test) BKE_speaker_make_local(bmain, (Speaker *)id, lib_local); return true; case ID_IP: return false; /* deprecated */ case ID_KE: - if (!test) BKE_key_make_local(bmain, (Key *)id); - return true; + return false; /* can't be linked */ case ID_WO: - if (!test) BKE_world_make_local(bmain, (World *)id); + if (!test) BKE_world_make_local(bmain, (World *)id, lib_local); return true; case ID_SCR: return false; /* can't be linked */ case ID_VF: - return false; /* not implemented */ + /* Partially implemented (has no copy...). */ + if (!test) BKE_vfont_make_local(bmain, (VFont *)id, lib_local); + return true; case ID_TXT: - return false; /* not implemented */ + if (!test) BKE_text_make_local(bmain, (Text *)id, lib_local); + return true; case ID_SO: - return false; /* not implemented */ + /* Partially implemented (has no copy...). */ + if (!test) BKE_sound_make_local(bmain, (bSound *)id, lib_local); + return true; case ID_GR: - return false; /* not implemented */ + if (!test) BKE_group_make_local(bmain, (Group *)id, lib_local); + return true; case ID_AR: - if (!test) BKE_armature_make_local(bmain, (bArmature *)id); + if (!test) BKE_armature_make_local(bmain, (bArmature *)id, lib_local); return true; case ID_AC: - if (!test) BKE_action_make_local(bmain, (bAction *)id); + if (!test) BKE_action_make_local(bmain, (bAction *)id, lib_local); return true; case ID_NT: - if (!test) ntreeMakeLocal(bmain, (bNodeTree *)id, true); + if (!test) ntreeMakeLocal(bmain, (bNodeTree *)id, true, lib_local); return true; case ID_BR: - if (!test) BKE_brush_make_local(bmain, (Brush *)id); + if (!test) BKE_brush_make_local(bmain, (Brush *)id, lib_local); return true; case ID_PA: - if (!test) BKE_particlesettings_make_local(bmain, (ParticleSettings *)id); + if (!test) BKE_particlesettings_make_local(bmain, (ParticleSettings *)id, lib_local); return true; case ID_WM: return false; /* can't be linked */ case ID_GD: - return false; /* not implemented */ + if (!test) BKE_gpencil_make_local(bmain, (bGPdata *)id, lib_local); + return true; + case ID_MSK: + if (!test) BKE_mask_make_local(bmain, (Mask *)id, lib_local); + return true; case ID_LS: - return false; /* not implemented */ + if (!test) BKE_linestyle_make_local(bmain, (FreestyleLineStyle *)id, lib_local); + return true; } return false; @@ -643,7 +715,7 @@ void BKE_main_lib_objects_recalc_all(Main *bmain) /* flag for full recalc */ for (ob = bmain->object.first; ob; ob = ob->id.next) { - if (ID_IS_LINKED_DATABLOCK(ob)) { + if (ID_IS_LINKED(ob)) { DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); } } @@ -1069,7 +1141,7 @@ static int id_relink_looper(void *UNUSED(user_data), ID *UNUSED(self_id), ID **i void BKE_libblock_relink(ID *id) { - if (ID_IS_LINKED_DATABLOCK(id)) + if (ID_IS_LINKED(id)) return; BKE_library_foreach_ID_link(id, id_relink_looper, NULL, 0); @@ -1285,7 +1357,7 @@ static ID *is_dupid(ListBase *lb, ID *id, const char *name) for (idtest = lb->first; idtest; idtest = idtest->next) { /* if idtest is not a lib */ - if (id != idtest && !ID_IS_LINKED_DATABLOCK(idtest)) { + if (id != idtest && !ID_IS_LINKED_DATABLOCK(idtest)) { /* Virtual lib IDs are considered as local ones here. */ /* do not test alphabetic! */ /* optimized */ if (idtest->name[2] == name[0]) { @@ -1426,7 +1498,7 @@ bool new_id(ListBase *lb, ID *id, const char *tname) bool result; char name[MAX_ID_NAME - 2]; - /* if library, don't rename */ + /* if real library, don't rename */ if (ID_IS_LINKED_DATABLOCK(id)) return false; @@ -1472,9 +1544,10 @@ bool new_id(ListBase *lb, ID *id, const char *tname) * Pull an ID out of a library (make it local). Only call this for IDs that * don't have other library users. */ -void id_clear_lib_data_ex(Main *bmain, ID *id, bool id_in_mainlist) +void id_clear_lib_data_ex(Main *bmain, ID *id, const bool id_in_mainlist) { bNodeTree *ntree = NULL; + Key *key = NULL; BKE_id_lib_local_paths(bmain, id->lib, id); @@ -1485,13 +1558,14 @@ void id_clear_lib_data_ex(Main *bmain, ID *id, bool id_in_mainlist) if (id_in_mainlist) new_id(which_libbase(bmain, GS(id->name)), id, NULL); - /* internal bNodeTree blocks inside ID types below - * also stores id->lib, make sure this stays in sync. - */ - ntree = ntreeFromID(id); + /* Internal bNodeTree blocks inside datablocks also stores id->lib, make sure this stays in sync. */ + if ((ntree = ntreeFromID(id))) { + id_clear_lib_data_ex(bmain, &ntree->id, false); /* Datablocks' nodetree is never in Main. */ + } - if (ntree) { - ntreeMakeLocal(bmain, ntree, false); + /* Same goes for shapekeys. */ + if ((key = BKE_key_from_id(id))) { + id_clear_lib_data_ex(bmain, &key->id, id_in_mainlist); /* sigh, why are keys in Main? */ } if (GS(id->name) == ID_OB) { @@ -1527,53 +1601,6 @@ void BKE_main_id_clear_newpoins(Main *bmain) } } -static void lib_indirect_test_id(ID *id, const Library *lib) -{ -#define LIBTAG(a) \ - if (a && a->id.lib) { a->id.tag &= ~LIB_TAG_INDIRECT; a->id.tag |= LIB_TAG_EXTERN; } (void)0 - - if (ID_IS_LINKED_DATABLOCK(id)) { - /* datablocks that were indirectly related are now direct links - * without this, appending data that has a link to other data will fail to write */ - if (lib && id->lib->parent == lib) { - id_lib_extern(id); - } - return; - } - - if (GS(id->name) == ID_OB) { - Object *ob = (Object *)id; - Mesh *me; - - int a; - -#if 0 /* XXX OLD ANIMSYS, NLASTRIPS ARE NO LONGER USED */ - /* XXX old animation system! -------------------------------------- */ - { - bActionStrip *strip; - for (strip = ob->nlastrips.first; strip; strip = strip->next) { - LIBTAG(strip->object); - LIBTAG(strip->act); - LIBTAG(strip->ipo); - } - } - /* XXX: new animation system needs something like this? */ -#endif - - for (a = 0; a < ob->totcol; a++) { - LIBTAG(ob->mat[a]); - } - - LIBTAG(ob->dup_group); - LIBTAG(ob->proxy); - - me = ob->data; - LIBTAG(me); - } - -#undef LIBTAG -} - /** Make linked datablocks local. * * \param bmain Almost certainly G.main. @@ -1581,19 +1608,30 @@ static void lib_indirect_test_id(ID *id, const Library *lib) * \param untagged_only If true, only make local datablocks not tagged with LIB_TAG_PRE_EXISTING. * \param set_fake If true, set fake user on all localized datablocks (except group and objects ones). */ +/* XXX TODO This function should probably be reworked. + * + * Old (2.77) version was simply making (tagging) datablocks as local, without actually making any check whether + * they were also indirectly used or not... + * + * Current version uses regular id_make_local callback, but this is not super-efficient since this ends up + * duplicating some IDs and then removing original ones (due to missing knowledge of which ID uses some other ID). + * + * We could first check all IDs and detect those to be made local that are only used by other local or future-local + * datablocks, and directly tag those as local (instead of going through id_make_local) maybe... + * + * We'll probably need at some point a true dependency graph between datablocks, but for now this should work + * good enough (performances is not a critical point here anyway). + */ void BKE_library_make_local(Main *bmain, const Library *lib, const bool untagged_only, const bool set_fake) { ListBase *lbarray[MAX_LIBARRAY]; - ID *id, *idn; + ID *id, *id_next; int a; - a = set_listbasepointers(bmain, lbarray); - while (a--) { - id = lbarray[a]->first; - - while (id) { + for (a = set_listbasepointers(bmain, lbarray); a--; ) { + for (id = lbarray[a]->first; id; id = id_next) { id->newid = NULL; - idn = id->next; /* id is possibly being inserted again */ + id_next = id->next; /* id is possibly being inserted again */ /* The check on the second line (LIB_TAG_PRE_EXISTING) is done so its * possible to tag data you don't want to be made local, used for @@ -1605,14 +1643,8 @@ void BKE_library_make_local(Main *bmain, const Library *lib, const bool untagged { if (lib == NULL || id->lib == lib) { if (id->lib) { - /* for Make Local > All we should be calling id_make_local, - * but doing that breaks append (see #36003 and #36006), we - * we should make it work with all datablocks and id.us==0 */ - id_clear_lib_data(bmain, id); /* sets 'id->tag' */ - - /* why sort alphabetically here but not in - * id_clear_lib_data() ? - campbell */ - id_sort_by_name(lbarray[a], id); + /* In this specific case, we do want to make ID local even if it has no local usage yet... */ + id_make_local(bmain, id, false, true); } else { id->tag &= ~(LIB_TAG_EXTERN | LIB_TAG_INDIRECT | LIB_TAG_NEW); @@ -1626,231 +1658,40 @@ void BKE_library_make_local(Main *bmain, const Library *lib, const bool untagged } } } - - id = idn; - } - } - - a = set_listbasepointers(bmain, lbarray); - while (a--) { - for (id = lbarray[a]->first; id; id = id->next) - lib_indirect_test_id(id, lib); - } -} - -/* Asset managing - TODO: we most likely want to turn this into a hashing at some point, could become a bit slow - * when having huge assets (or many of them)... */ -void BKE_library_asset_repository_init(Library *lib, const AssetEngineType *aet, const char *repo_root) -{ - BKE_library_asset_repository_free(lib); - lib->asset_repository = MEM_mallocN(sizeof(*lib->asset_repository), __func__); - - BLI_strncpy(lib->asset_repository->asset_engine, aet->idname, sizeof(lib->asset_repository->asset_engine)); - lib->asset_repository->asset_engine_version = aet->version; - BLI_strncpy(lib->asset_repository->root, repo_root, sizeof(lib->asset_repository->root)); - - BLI_listbase_clear(&lib->asset_repository->assets); -} - -void BKE_library_asset_repository_clear(Library *lib) -{ - if (lib->asset_repository) { - for (AssetRef *aref; (aref = BLI_pophead(&lib->asset_repository->assets)); ) { - BLI_freelistN(&aref->id_list); - MEM_freeN(aref); - } - } -} - -void BKE_library_asset_repository_free(Library *lib) -{ - if (lib->asset_repository) { - BKE_library_asset_repository_clear(lib); - MEM_freeN(lib->asset_repository); - lib->asset_repository = NULL; - } -} - -AssetRef *BKE_library_asset_repository_asset_add(Library *lib, const void *idv) -{ - const ID *id = idv; - BLI_assert(id->uuid != NULL); - - AssetRef *aref = BKE_library_asset_repository_asset_find(lib, idv); - if (!aref) { - aref = MEM_callocN(sizeof(*aref), __func__); - aref->uuid = *id->uuid; - BKE_library_asset_repository_subdata_add(aref, idv); - BLI_addtail(&lib->asset_repository->assets, aref); - } - - return aref; -} - -AssetRef *BKE_library_asset_repository_asset_find(Library *lib, const void *idv) -{ - const ID *id = idv; - BLI_assert(id->uuid != NULL); - - for (AssetRef *aref = lib->asset_repository->assets.first; aref; aref = aref->next) { - if (ASSETUUID_COMPARE(&aref->uuid, id->uuid)) { -#ifndef NDEBUG - LinkData *link = aref->id_list.first; - BLI_assert(link && (link->data == idv)); -#endif - return aref; - } - } - return NULL; -} - -void BKE_library_asset_repository_asset_remove(Library *lib, const void *idv) -{ - AssetRef *aref = BKE_library_asset_repository_asset_find(lib, idv); - BLI_remlink(&lib->asset_repository->assets, aref); - BLI_freelistN(&aref->id_list); - MEM_freeN(aref); -} - -void BKE_library_asset_repository_subdata_add(AssetRef *aref, const void *idv) -{ - if (BLI_findptr(&aref->id_list, idv, offsetof(LinkData, data)) == NULL) { - BLI_addtail(&aref->id_list, BLI_genericNodeN((void *)idv)); - } -} - -void BKE_library_asset_repository_subdata_remove(AssetRef *aref, const void *idv) -{ - LinkData *link = BLI_findptr(&aref->id_list, idv, offsetof(LinkData, data)); - if (link) { - BLI_freelinkN(&aref->id_list, link); - } -} - -void BKE_libraries_asset_subdata_remove(Main *bmain, const void *idv) -{ - const ID *id = idv; - - if (id->lib == NULL) { - return; - } - - ListBase *lb = which_libbase(bmain, ID_LI); - for (Library *lib = lb->first; lib; lib = lib->id.next) { - if (lib->asset_repository) { - for (AssetRef *aref = lib->asset_repository->assets.first; aref; aref = aref->next) { - BLI_freelinkN(&aref->id_list, BLI_findptr(&aref->id_list, idv, offsetof(LinkData, data))); - } } } -} - -void BKE_libraries_asset_repositories_clear(Main *bmain) -{ - ListBase *lb = which_libbase(bmain, ID_LI); - for (Library *lib = lb->first; lib; lib = lib->id.next) { - BKE_library_asset_repository_clear(lib); - } - BKE_main_id_tag_all(bmain, LIB_TAG_ASSET, false); -} - -static int library_asset_dependencies_rebuild_cb(void *userdata, ID *id_self, ID **idp, int UNUSED(cd_flag)) -{ - if (!idp || !*idp) { - return IDWALK_RET_NOP; - } - AssetRef *aref = userdata; - ID *id = *idp; - - if (id->uuid) { - return IDWALK_RET_STOP_RECURSION; - } - - printf("%s (from %s)\n", id->name, id_self->name); - - BKE_library_asset_repository_subdata_add(aref, (const void *)id); - id->tag |= LIB_TAG_ASSET; - return IDWALK_RET_NOP; -} - -static void library_asset_dependencies_rebuild(ID *asset) -{ - Library *lib = asset->lib; - BLI_assert(lib && lib->asset_repository); - - if (!(lib && lib->asset_repository)) { - printf("asset: %s\n", asset->name); - printf("lib: %p\n", lib); - printf("lib: %s\n", lib->id.name); - printf("lib: %s\n", lib->name); - printf("lib: %p\n\n\n", lib->asset_repository); - } - - asset->tag |= LIB_TAG_ASSET; - - AssetRef *aref = BKE_library_asset_repository_asset_add(lib, asset); - - BKE_library_foreach_ID_link(asset, library_asset_dependencies_rebuild_cb, aref, IDWALK_RECURSE); -} - -void BKE_libraries_asset_repositories_rebuild(Main *bmain) -{ - ListBase *lbarray[MAX_LIBARRAY]; - ID *id; - int a; - - BKE_libraries_asset_repositories_clear(bmain); - - a = set_listbasepointers(bmain, lbarray); - while (a--) { + /* We have to remap local usages of old (linked) ID to new (local) id in a second loop, as lbarray ordering is not + * enough to ensure us we did catch all dependencies (e.g. if making local a parent object before its child...). + * See T48907. */ + for (a = set_listbasepointers(bmain, lbarray); a--; ) { for (id = lbarray[a]->first; id; id = id->next) { - if (id->uuid) { - library_asset_dependencies_rebuild(id); + if (id->newid) { + BKE_libblock_remap(bmain, id, id->newid, ID_REMAP_SKIP_INDIRECT_USAGE); } } } -} -AssetRef *BKE_libraries_asset_repository_uuid_find(Main *bmain, const AssetUUID *uuid) -{ - ListBase *lb = which_libbase(bmain, ID_LI); - for (Library *lib = lb->first; lib; lib = lib->id.next) { - for (AssetRef *aref = lib->asset_repository->assets.first; aref; aref = aref->next) { - if (ASSETUUID_COMPARE(&aref->uuid, uuid)) { -#ifndef NDEBUG - LinkData *link = aref->id_list.first; - BLI_assert(link && ((ID *)link->data)->uuid && ASSETUUID_COMPARE(((ID *)link->data)->uuid, uuid)); -#endif - return aref; + /* Third step: remove datablocks that have been copied to be localized and are no more used in the end... + * Note that we may have to loop more than once here, to tackle dependencies between linked objects... */ + bool do_loop = true; + while (do_loop) { + do_loop = false; + for (a = set_listbasepointers(bmain, lbarray); a--; ) { + for (id = lbarray[a]->first; id; id = id_next) { + id_next = id->next; + if (id->newid) { + bool is_local = false, is_lib = false; + + BKE_library_ID_test_usages(bmain, id, &is_local, &is_lib); + if (!is_local && !is_lib) { + BKE_libblock_free(bmain, id); + do_loop = true; + } + } } } } - return NULL; -} - -/** Find or add the 'virtual' library datablock matching this asset engine, used for non-blend-data assets. */ -Library *BKE_library_asset_virtual_ensure(Main *bmain, const AssetEngineType *aet) -{ - Library *lib; - ListBase *lb = which_libbase(bmain, ID_LI); - - for (lib = lb->first; lib; lib = lib->id.next) { - if (!(lib->flag & LIBRARY_FLAG_VIRTUAL) || !lib->asset_repository) { - continue; - } - - if (STREQ(lib->asset_repository->asset_engine, aet->idname) && - lib->asset_repository->asset_engine_version == aet->version) - { - return lib; - } - } - - lib = BKE_libblock_alloc(bmain, ID_LI, "VirtualLib"); - BKE_library_asset_repository_init(lib, aet, ""); - lib->flag |= LIBRARY_FLAG_VIRTUAL; - return lib; } diff --git a/source/blender/blenkernel/intern/library_asset.c b/source/blender/blenkernel/intern/library_asset.c new file mode 100644 index 00000000000..9ee6a2e426e --- /dev/null +++ b/source/blender/blenkernel/intern/library_asset.c @@ -0,0 +1,269 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2015,2016 by Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Bastien Montagne. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/library_asset.c + * \ingroup bke + * + * Contains asset-related management of ID's and libraries. + */ + +#include <string.h> + +#include "MEM_guardedalloc.h" + +#include "BLI_blenlib.h" +#include "BLI_utildefines.h" + +#include "RNA_types.h" + +#include "BKE_asset_engine.h" +#include "BKE_library.h" +#include "BKE_library_query.h" +#include "BKE_main.h" + + +/* Asset managing - TODO: we most likely want to turn this into a hashing at some point, could become a bit slow + * when having huge assets (or many of them)... */ +void BKE_library_asset_repository_init(Library *lib, const AssetEngineType *aet, const char *repo_root) +{ + BKE_library_asset_repository_free(lib); + lib->asset_repository = MEM_mallocN(sizeof(*lib->asset_repository), __func__); + + BLI_strncpy(lib->asset_repository->asset_engine, aet->idname, sizeof(lib->asset_repository->asset_engine)); + lib->asset_repository->asset_engine_version = aet->version; + BLI_strncpy(lib->asset_repository->root, repo_root, sizeof(lib->asset_repository->root)); + + BLI_listbase_clear(&lib->asset_repository->assets); +} + +void BKE_library_asset_repository_clear(Library *lib) +{ + if (lib->asset_repository) { + for (AssetRef *aref; (aref = BLI_pophead(&lib->asset_repository->assets)); ) { + BLI_freelistN(&aref->id_list); + MEM_freeN(aref); + } + } +} + +void BKE_library_asset_repository_free(Library *lib) +{ + if (lib->asset_repository) { + BKE_library_asset_repository_clear(lib); + MEM_freeN(lib->asset_repository); + lib->asset_repository = NULL; + } +} + +AssetRef *BKE_library_asset_repository_asset_add(Library *lib, const void *idv) +{ + const ID *id = idv; + BLI_assert(id->uuid != NULL); + + AssetRef *aref = BKE_library_asset_repository_asset_find(lib, idv); + if (!aref) { + aref = MEM_callocN(sizeof(*aref), __func__); + aref->uuid = *id->uuid; + BKE_library_asset_repository_subdata_add(aref, idv); + BLI_addtail(&lib->asset_repository->assets, aref); + } + + return aref; +} + +AssetRef *BKE_library_asset_repository_asset_find(Library *lib, const void *idv) +{ + const ID *id = idv; + BLI_assert(id->uuid != NULL); + + for (AssetRef *aref = lib->asset_repository->assets.first; aref; aref = aref->next) { + if (ASSETUUID_COMPARE(&aref->uuid, id->uuid)) { +#ifndef NDEBUG + LinkData *link = aref->id_list.first; + BLI_assert(link && (link->data == idv)); +#endif + return aref; + } + } + return NULL; +} + +void BKE_library_asset_repository_asset_remove(Library *lib, const void *idv) +{ + AssetRef *aref = BKE_library_asset_repository_asset_find(lib, idv); + BLI_remlink(&lib->asset_repository->assets, aref); + BLI_freelistN(&aref->id_list); + MEM_freeN(aref); +} + +void BKE_library_asset_repository_subdata_add(AssetRef *aref, const void *idv) +{ + if (BLI_findptr(&aref->id_list, idv, offsetof(LinkData, data)) == NULL) { + BLI_addtail(&aref->id_list, BLI_genericNodeN((void *)idv)); + } +} + +void BKE_library_asset_repository_subdata_remove(AssetRef *aref, const void *idv) +{ + LinkData *link = BLI_findptr(&aref->id_list, idv, offsetof(LinkData, data)); + if (link) { + BLI_freelinkN(&aref->id_list, link); + } +} + +void BKE_libraries_asset_subdata_remove(Main *bmain, const void *idv) +{ + const ID *id = idv; + + if (id->lib == NULL) { + return; + } + + ListBase *lb = &bmain->library; + for (Library *lib = lb->first; lib; lib = lib->id.next) { + if (lib->asset_repository) { + for (AssetRef *aref = lib->asset_repository->assets.first; aref; aref = aref->next) { + LinkData *subdata = aref->id_list.first; + /* Skip first one, it's main asset, not subdata! */ + for (subdata = subdata->next; subdata; subdata = subdata->next) { + if (subdata->data == idv) { + BLI_freelinkN(&aref->id_list, subdata); + break; + } + } + } + } + } +} + +void BKE_libraries_asset_repositories_clear(Main *bmain) +{ + ListBase *lb = which_libbase(bmain, ID_LI); + for (Library *lib = lb->first; lib; lib = lib->id.next) { + BKE_library_asset_repository_clear(lib); + } + BKE_main_id_tag_all(bmain, LIB_TAG_ASSET, false); +} + +static int library_asset_dependencies_rebuild_cb(void *userdata, ID *id_self, ID **idp, int UNUSED(cd_flag)) +{ + if (!idp || !*idp) { + return IDWALK_RET_NOP; + } + + AssetRef *aref = userdata; + ID *id = *idp; + + if (id->uuid) { + return IDWALK_RET_STOP_RECURSION; + } + + printf("%s (from %s)\n", id->name, id_self->name); + + BKE_library_asset_repository_subdata_add(aref, (const void *)id); + id->tag |= LIB_TAG_ASSET; + return IDWALK_RET_NOP; +} + +static void library_asset_dependencies_rebuild(ID *asset) +{ + Library *lib = asset->lib; + BLI_assert(lib && lib->asset_repository); + + if (!(lib && lib->asset_repository)) { + printf("asset: %s\n", asset->name); + printf("lib: %p\n", lib); + printf("lib: %s\n", lib->id.name); + printf("lib: %s\n", lib->name); + printf("lib: %p\n\n\n", lib->asset_repository); + } + + asset->tag |= LIB_TAG_ASSET; + + AssetRef *aref = BKE_library_asset_repository_asset_add(lib, asset); + + BKE_library_foreach_ID_link(asset, library_asset_dependencies_rebuild_cb, aref, IDWALK_RECURSE); +} + +void BKE_libraries_asset_repositories_rebuild(Main *bmain) +{ + ListBase *lbarray[MAX_LIBARRAY]; + ID *id; + int a; + + BKE_libraries_asset_repositories_clear(bmain); + + a = set_listbasepointers(bmain, lbarray); + while (a--) { + for (id = lbarray[a]->first; id; id = id->next) { + if (id->uuid) { + library_asset_dependencies_rebuild(id); + } + } + } +} + +AssetRef *BKE_libraries_asset_repository_uuid_find(Main *bmain, const AssetUUID *uuid) +{ + ListBase *lb = which_libbase(bmain, ID_LI); + for (Library *lib = lb->first; lib; lib = lib->id.next) { + for (AssetRef *aref = lib->asset_repository->assets.first; aref; aref = aref->next) { + if (ASSETUUID_COMPARE(&aref->uuid, uuid)) { +#ifndef NDEBUG + LinkData *link = aref->id_list.first; + BLI_assert(link && ((ID *)link->data)->uuid && ASSETUUID_COMPARE(((ID *)link->data)->uuid, uuid)); +#endif + return aref; + } + } + } + return NULL; +} + +/** Find or add the 'virtual' library datablock matching this asset engine, used for non-blend-data assets. */ +Library *BKE_library_asset_virtual_ensure(Main *bmain, const AssetEngineType *aet) +{ + Library *lib; + ListBase *lb = which_libbase(bmain, ID_LI); + + for (lib = lb->first; lib; lib = lib->id.next) { + if (!(lib->flag & LIBRARY_FLAG_VIRTUAL) || !lib->asset_repository) { + continue; + } + + if (STREQ(lib->asset_repository->asset_engine, aet->idname) && + lib->asset_repository->asset_engine_version == aet->version) + { + return lib; + } + } + + lib = BKE_libblock_alloc(bmain, ID_LI, "VirtualLib"); + BKE_library_asset_repository_init(lib, aet, ""); + lib->flag |= LIBRARY_FLAG_VIRTUAL; + return lib; +} diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c index f86f5fa01ec..a33c63c07af 100644 --- a/source/blender/blenkernel/intern/library_query.c +++ b/source/blender/blenkernel/intern/library_query.c @@ -298,7 +298,7 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u do { data.self_id = id; - data.cd_flag = ID_IS_LINKED_DATABLOCK(id) ? IDWALK_INDIRECT_USAGE : 0; + data.cd_flag = ID_IS_LINKED(id) ? IDWALK_INDIRECT_USAGE : 0; AnimData *adt = BKE_animdata_from_id(id); if (adt) { @@ -442,7 +442,16 @@ void BKE_library_foreach_ID_link(ID *id, LibraryIDLinkCallback callback, void *u /* object->proxy is refcounted, but not object->proxy_group... *sigh* */ CALLBACK_INVOKE(object->proxy, IDWALK_USER); CALLBACK_INVOKE(object->proxy_group, IDWALK_NOP); + + /* Special case! + * Since this field is set/owned by 'user' of this ID (and not ID itself), it is only indirect usage + * if proxy object is linked... Twisted. */ + if (object->proxy_from) { + data.cd_flag = ID_IS_LINKED(object->proxy_from) ? IDWALK_INDIRECT_USAGE : 0; + } CALLBACK_INVOKE(object->proxy_from, IDWALK_NOP); + data.cd_flag = data_cd_flag; + CALLBACK_INVOKE(object->poselib, IDWALK_USER); data.cd_flag |= proxy_cd_flag; @@ -856,9 +865,10 @@ void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cd_flag) /** * Say whether given \a id_type_owner can use (in any way) a datablock of \a id_type_used. + * + * This is a 'simplified' abstract version of #BKE_library_foreach_ID_link() above, quite useful to reduce + * useless iterations in some cases. */ -/* This is a 'simplified' abstract version of BKE_library_foreach_ID_link() above, quite useful to reduce - * useless ietrations in some cases. */ bool BKE_library_idtype_can_use_idtype(const short id_type_owner, const short id_type_used) { if (id_type_used == ID_AC) { diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c index b158b3f968b..9ac795ddf44 100644 --- a/source/blender/blenkernel/intern/library_remap.c +++ b/source/blender/blenkernel/intern/library_remap.c @@ -296,6 +296,9 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data) if (ob->pose && (!old_id || ob->data == old_id)) { BLI_assert(ob->type == OB_ARMATURE); ob->pose->flag |= POSE_RECALC; + /* We need to clear pose bone pointers immediately, things like undo writefile may be called + * before pose is actually recomputed, can lead to segfault... */ + BKE_pose_clear_pointers(ob->pose); } } break; @@ -641,6 +644,7 @@ void BKE_libblock_relink_ex( libblock_remap_data_postprocess_group_scene_unlink(bmain, sce, NULL); } } + break; } case ID_OB: if (new_id) { /* Only affects us in case obdata was relinked (changed). */ @@ -682,6 +686,10 @@ void BKE_libblock_free_data(Main *bmain, ID *id) MEM_freeN(id->properties); } + if (id->uuid) { + MEM_freeN(id->uuid); + } + /* this ID may be a driver target! */ BKE_animdata_main_cb(bmain, animdata_dtar_clear_cb, (void *)id); } diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index c4a0d0074fb..430935a5fad 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -218,14 +218,16 @@ FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, FreestyleLineStyle *l for (m = (LineStyleModifier *)linestyle->geometry_modifiers.first; m; m = m->next) BKE_linestyle_geometry_modifier_copy(new_linestyle, m); - if (ID_IS_LINKED_DATABLOCK(linestyle)) { - BKE_id_expand_local(&new_linestyle->id); - BKE_id_lib_local_paths(bmain, linestyle->id.lib, &new_linestyle->id); - } + BKE_id_copy_ensure_local(bmain, &linestyle->id, &new_linestyle->id); return new_linestyle; } +void BKE_linestyle_make_local(struct Main *bmain, FreestyleLineStyle *linestyle, const bool lib_local) +{ + BKE_id_make_local_generic(bmain, &linestyle->id, true, lib_local); +} + FreestyleLineStyle *BKE_linestyle_active_from_scene(Scene *scene) { SceneRenderLayer *actsrl = BLI_findlink(&scene->r.layers, scene->r.actlay); diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 9e070bbef22..21023d9f53c 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -853,14 +853,16 @@ Mask *BKE_mask_copy(Main *bmain, Mask *mask) /* enable fake user by default */ id_fake_user_set(&mask->id); - if (ID_IS_LINKED_DATABLOCK(mask)) { - BKE_id_expand_local(&mask_new->id); - BKE_id_lib_local_paths(bmain, mask->id.lib, &mask_new->id); - } + BKE_id_copy_ensure_local(bmain, &mask->id, &mask_new->id); return mask_new; } +void BKE_mask_make_local(Main *bmain, Mask *mask, const bool lib_local) +{ + BKE_id_make_local_generic(bmain, &mask->id, true, lib_local); +} + void BKE_mask_point_free(MaskSplinePoint *point) { if (point->uw) diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 17811893c03..0be32c9b84c 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -243,14 +243,11 @@ Material *BKE_material_copy(Main *bmain, Material *ma) man->nodetree = ntreeCopyTree(bmain, ma->nodetree); } - man->preview = BKE_previewimg_copy(ma->preview); + BKE_previewimg_id_copy(&man->id, &ma->id); BLI_listbase_clear(&man->gpumaterial); - if (ID_IS_LINKED_DATABLOCK(ma)) { - BKE_id_expand_local(&man->id); - BKE_id_lib_local_paths(bmain, ma->id.lib, &man->id); - } + BKE_id_copy_ensure_local(bmain, &ma->id, &man->id); return man; } @@ -285,34 +282,9 @@ Material *localize_material(Material *ma) return man; } -void BKE_material_make_local(Main *bmain, Material *ma) +void BKE_material_make_local(Main *bmain, Material *ma, const bool lib_local) { - bool is_local = false, is_lib = false; - - /* - only lib users: do nothing - * - only local users: set flag - * - mixed: make copy - */ - - if (!ID_IS_LINKED_DATABLOCK(ma)) { - return; - } - - BKE_library_ID_test_usages(bmain, ma, &is_local, &is_lib); - - if (is_local) { - if (!is_lib) { - id_clear_lib_data(bmain, &ma->id); - BKE_id_expand_local(&ma->id); - } - else { - Material *ma_new = BKE_material_copy(bmain, ma); - - ma_new->id.us = 0; - - BKE_libblock_remap(bmain, ma, ma_new, ID_REMAP_SKIP_INDIRECT_USAGE); - } - } + BKE_id_make_local_generic(bmain, &ma->id, true, lib_local); } Material ***give_matarar(Object *ob) @@ -569,18 +541,6 @@ Material *give_current_material(Object *ob, short act) return ma; } -ID *material_from(Object *ob, short act) -{ - - if (ob == NULL) return NULL; - - if (ob->totcol == 0) return ob->data; - if (act == 0) act = 1; - - if (ob->matbits[act - 1]) return (ID *)ob; - else return ob->data; -} - Material *give_node_material(Material *ma) { if (ma && ma->use_nodes && ma->nodetree) { @@ -886,7 +846,11 @@ void assign_matarar(struct Object *ob, struct Material ***matar, short totcol) int actcol_orig = ob->actcol; short i; - while (object_remove_material_slot(ob)) {} + while ((ob->totcol > totcol) && + BKE_object_material_slot_remove(ob)) + { + /* pass */ + } /* now we have the right number of slots */ for (i = 0; i < totcol; i++) @@ -899,7 +863,7 @@ void assign_matarar(struct Object *ob, struct Material ***matar, short totcol) } -short find_material_index(Object *ob, Material *ma) +short BKE_object_material_slot_find_index(Object *ob, Material *ma) { Material ***matarar; short a, *totcolp; @@ -919,7 +883,7 @@ short find_material_index(Object *ob, Material *ma) return 0; } -bool object_add_material_slot(Object *ob) +bool BKE_object_material_slot_add(Object *ob) { if (ob == NULL) return false; if (ob->totcol >= MAXMAT) return false; @@ -1201,7 +1165,7 @@ void material_drivers_update(Scene *scene, Material *ma, float ctime) ma->id.tag &= ~LIB_TAG_DOIT; } -bool object_remove_material_slot(Object *ob) +bool BKE_object_material_slot_remove(Object *ob) { Material *mao, ***matarar; Object *obt; diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 9a0a6e3540c..8d024ea9aa5 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -119,42 +119,14 @@ MetaBall *BKE_mball_copy(Main *bmain, MetaBall *mb) mbn->editelems = NULL; mbn->lastelem = NULL; - if (ID_IS_LINKED_DATABLOCK(mb)) { - BKE_id_expand_local(&mbn->id); - BKE_id_lib_local_paths(bmain, mb->id.lib, &mbn->id); - } + BKE_id_copy_ensure_local(bmain, &mb->id, &mbn->id); return mbn; } -void BKE_mball_make_local(Main *bmain, MetaBall *mb) +void BKE_mball_make_local(Main *bmain, MetaBall *mb, const bool lib_local) { - bool is_local = false, is_lib = false; - - /* - only lib users: do nothing - * - only local users: set flag - * - mixed: make copy - */ - - if (!ID_IS_LINKED_DATABLOCK(mb)) { - return; - } - - BKE_library_ID_test_usages(bmain, mb, &is_local, &is_lib); - - if (is_local) { - if (!is_lib) { - id_clear_lib_data(bmain, &mb->id); - BKE_id_expand_local(&mb->id); - } - else { - MetaBall *mb_new = BKE_mball_copy(bmain, mb); - - mb_new->id.us = 0; - - BKE_libblock_remap(bmain, mb, mb_new, ID_REMAP_SKIP_INDIRECT_USAGE); - } - } + BKE_id_make_local_generic(bmain, &mb->id, true, lib_local); } /* most simple meta-element adding function diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 787b9905734..733e9030056 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -31,6 +31,7 @@ #include "DNA_scene_types.h" #include "DNA_material_types.h" +#include "DNA_meta_types.h" #include "DNA_object_types.h" #include "DNA_key_types.h" #include "DNA_mesh_types.h" @@ -530,10 +531,7 @@ Mesh *BKE_mesh_copy(Main *bmain, Mesh *me) men->key->from = (ID *)men; } - if (ID_IS_LINKED_DATABLOCK(me)) { - BKE_id_expand_local(&men->id); - BKE_id_lib_local_paths(bmain, me->id.lib, &men->id); - } + BKE_id_copy_ensure_local(bmain, &me->id, &men->id); return men; } @@ -555,37 +553,9 @@ BMesh *BKE_mesh_to_bmesh( return bm; } -void BKE_mesh_make_local(Main *bmain, Mesh *me) +void BKE_mesh_make_local(Main *bmain, Mesh *me, const bool lib_local) { - bool is_local = false, is_lib = false; - - /* - only lib users: do nothing - * - only local users: set flag - * - mixed: make copy - */ - - if (!ID_IS_LINKED_DATABLOCK(me)) { - return; - } - - BKE_library_ID_test_usages(bmain, me, &is_local, &is_lib); - - if (is_local) { - if (!is_lib) { - id_clear_lib_data(bmain, &me->id); - if (me->key) { - BKE_key_make_local(bmain, me->key); - } - BKE_id_expand_local(&me->id); - } - else { - Mesh *me_new = BKE_mesh_copy(bmain, me); - - me_new->id.us = 0; - - BKE_libblock_remap(bmain, me, me_new, ID_REMAP_SKIP_INDIRECT_USAGE); - } - } + BKE_id_make_local_generic(bmain, &me->id, true, lib_local); } bool BKE_mesh_uv_cdlayer_rename_index(Mesh *me, const int poly_index, const int loop_index, const int face_index, @@ -2227,7 +2197,6 @@ Mesh *BKE_mesh_new_from_object( { Mesh *tmpmesh; Curve *tmpcu = NULL, *copycu; - Object *tmpobj = NULL; int render = settings == eModifierMode_Render, i; int cage = !apply_modifiers; @@ -2242,7 +2211,7 @@ Mesh *BKE_mesh_new_from_object( int uv_from_orco; /* copies object and modifiers (but not the data) */ - tmpobj = BKE_object_copy_ex(bmain, ob, true); + Object *tmpobj = BKE_object_copy_ex(bmain, ob, true); tmpcu = (Curve *)tmpobj->data; id_us_min(&tmpcu->id); @@ -2398,23 +2367,25 @@ Mesh *BKE_mesh_new_from_object( } break; -#if 0 - /* Crashes when assigning the new material, not sure why */ case OB_MBALL: - tmpmb = (MetaBall *)ob->data; + { + MetaBall *tmpmb = (MetaBall *)ob->data; + tmpmesh->mat = MEM_dupallocN(tmpmb->mat); tmpmesh->totcol = tmpmb->totcol; /* free old material list (if it exists) and adjust user counts */ if (tmpmb->mat) { for (i = tmpmb->totcol; i-- > 0; ) { - tmpmesh->mat[i] = tmpmb->mat[i]; /* CRASH HERE ??? */ + /* are we an object material or data based? */ + tmpmesh->mat[i] = ob->matbits[i] ? ob->mat[i] : tmpmb->mat[i]; + if (tmpmesh->mat[i]) { - id_us_plus(&tmpmb->mat[i]->id); + id_us_plus(&tmpmesh->mat[i]->id); } } } break; -#endif + } case OB_MESH: if (!cage) { @@ -2442,9 +2413,6 @@ Mesh *BKE_mesh_new_from_object( BKE_mesh_tessface_ensure(tmpmesh); } - /* make sure materials get updated in object */ - test_object_materials(tmpobj ? tmpobj : ob, &tmpmesh->id); - return tmpmesh; } diff --git a/source/blender/blenkernel/intern/mesh_mapping.c b/source/blender/blenkernel/intern/mesh_mapping.c index a472b6e5bc1..8562988b5e1 100644 --- a/source/blender/blenkernel/intern/mesh_mapping.c +++ b/source/blender/blenkernel/intern/mesh_mapping.c @@ -393,6 +393,60 @@ void BKE_mesh_vert_edge_vert_map_create( } /** + * Generates a map where the key is the edge and the value is a list of loops that use that edge. + * Loops indices of a same poly are contiguous and in winding order. + * The lists are allocated from one memory pool. + */ +void BKE_mesh_edge_loop_map_create(MeshElemMap **r_map, int **r_mem, + const MEdge *UNUSED(medge), const int totedge, + const MPoly *mpoly, const int totpoly, + const MLoop *mloop, const int totloop) +{ + MeshElemMap *map = MEM_callocN(sizeof(MeshElemMap) * (size_t)totedge, "edge-poly map"); + int *indices = MEM_mallocN(sizeof(int) * (size_t)totloop * 2, "edge-poly map mem"); + int *index_step; + const MPoly *mp; + int i; + + /* count face users */ + for (i = 0, mp = mpoly; i < totpoly; mp++, i++) { + const MLoop *ml; + int j = mp->totloop; + for (ml = &mloop[mp->loopstart]; j--; ml++) { + map[ml->e].count += 2; + } + } + + /* create offsets */ + index_step = indices; + for (i = 0; i < totedge; i++) { + map[i].indices = index_step; + index_step += map[i].count; + + /* re-count, using this as an index below */ + map[i].count = 0; + } + + /* assign loop-edge users */ + for (i = 0, mp = mpoly; i < totpoly; mp++, i++) { + const MLoop *ml; + MeshElemMap *map_ele; + const int max_loop = mp->loopstart + mp->totloop; + int j = mp->loopstart; + for (ml = &mloop[j]; j < max_loop; j++, ml++) { + map_ele = &map[ml->e]; + map_ele->indices[map_ele->count++] = j; + map_ele->indices[map_ele->count++] = j + 1; + } + /* last edge/loop of poly, must point back to first loop! */ + map_ele->indices[map_ele->count - 1] = mp->loopstart; + } + + *r_map = map; + *r_mem = indices; +} + +/** * Generates a map where the key is the edge and the value is a list of polygons that use that edge. * The lists are allocated from one memory pool. */ @@ -539,12 +593,12 @@ void BKE_mesh_origindex_map_create_looptri( */ typedef bool (*MeshRemap_CheckIslandBoundary)( const struct MPoly *mpoly, const struct MLoop *mloop, const struct MEdge *medge, - const int nbr_egde_users); + const int nbr_egde_users, void *user_data); static void poly_edge_loop_islands_calc( const MEdge *medge, const int totedge, const MPoly *mpoly, const int totpoly, const MLoop *mloop, const int totloop, MeshElemMap *edge_poly_map, - const bool use_bitflags, MeshRemap_CheckIslandBoundary edge_boundary_check, + const bool use_bitflags, MeshRemap_CheckIslandBoundary edge_boundary_check, void *edge_boundary_check_data, int **r_poly_groups, int *r_totgroup, BLI_bitmap **r_edge_borders, int *r_totedgeborder) { int *poly_groups; @@ -626,7 +680,7 @@ static void poly_edge_loop_islands_calc( const MeshElemMap *map_ele = &edge_poly_map[me_idx]; const int *p = map_ele->indices; int i = map_ele->count; - if (!edge_boundary_check(mp, ml, me, i)) { + if (!edge_boundary_check(mp, ml, me, i, edge_boundary_check_data)) { for (; i--; p++) { /* if we meet other non initialized its a bug */ BLI_assert(ELEM(poly_groups[*p], 0, poly_group_id)); @@ -718,7 +772,7 @@ static void poly_edge_loop_islands_calc( } static bool poly_is_island_boundary_smooth_cb( - const MPoly *mp, const MLoop *UNUSED(ml), const MEdge *me, const int nbr_egde_users) + const MPoly *mp, const MLoop *UNUSED(ml), const MEdge *me, const int nbr_egde_users, void *UNUSED(user_data)) { /* Edge is sharp if its poly is sharp, or edge itself is sharp, or edge is not used by exactly two polygons. */ return (!(mp->flag & ME_SMOOTH) || (me->flag & ME_SHARP) || (nbr_egde_users != 2)); @@ -741,7 +795,7 @@ int *BKE_mesh_calc_smoothgroups(const MEdge *medge, const int totedge, poly_edge_loop_islands_calc( medge, totedge, mpoly, totpoly, mloop, totloop, NULL, use_bitflags, - poly_is_island_boundary_smooth_cb, &poly_groups, r_totgroup, NULL, NULL); + poly_is_island_boundary_smooth_cb, NULL, &poly_groups, r_totgroup, NULL, NULL); return poly_groups; } @@ -848,28 +902,60 @@ void BKE_mesh_loop_islands_add( * Would make things much more complex though, and each UVMap would then need its own mesh mapping, * not sure we want that at all! */ +typedef struct MeshCheckIslandBoundaryUv { + const MLoop *loops; + const MLoopUV *luvs; + const MeshElemMap *edge_loop_map; +} MeshCheckIslandBoundaryUv; + static bool mesh_check_island_boundary_uv( - const MPoly *UNUSED(mp), const MLoop *UNUSED(ml), const MEdge *me, const int UNUSED(nbr_egde_users)) + const MPoly *UNUSED(mp), const MLoop *ml, const MEdge *me, + const int UNUSED(nbr_egde_users), void *user_data) { - /* Edge is UV boundary if tagged as seam. */ - return (me->flag & ME_SEAM) != 0; + if (user_data) { + const MeshCheckIslandBoundaryUv *data = user_data; + const MLoop *loops = data->loops; + const MLoopUV *luvs = data->luvs; + const MeshElemMap *edge_to_loops = &data->edge_loop_map[ml->e]; + + BLI_assert(edge_to_loops->count >= 2 && (edge_to_loops->count % 2) == 0); + + const unsigned int v1 = loops[edge_to_loops->indices[0]].v; + const unsigned int v2 = loops[edge_to_loops->indices[1]].v; + const float *uvco_v1 = luvs[edge_to_loops->indices[0]].uv; + const float *uvco_v2 = luvs[edge_to_loops->indices[1]].uv; + for (int i = 2; i < edge_to_loops->count; i += 2) { + if (loops[edge_to_loops->indices[i]].v == v1) { + if (!equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i]].uv) || + !equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i + 1]].uv)) + { + return true; + } + } + else { + BLI_assert(loops[edge_to_loops->indices[i]].v == v2); + UNUSED_VARS_NDEBUG(v2); + if (!equals_v2v2(uvco_v2, luvs[edge_to_loops->indices[i]].uv) || + !equals_v2v2(uvco_v1, luvs[edge_to_loops->indices[i + 1]].uv)) + { + return true; + } + } + } + return false; + } + else { + /* Edge is UV boundary if tagged as seam. */ + return (me->flag & ME_SEAM) != 0; + } } -/** - * Calculate UV islands. - * - * \note Currently we only consider edges tagges as seams as UV boundaries. This has the advantages of simplicity, - * and being valid/common to all UV maps. However, it means actual UV islands whithout matching UV seams - * will not be handled correctly... - * - * \note All this could be optimized... - * Not sure it would be worth the more complex code, though, those loops are supposed to be really quick to do... - */ -bool BKE_mesh_calc_islands_loop_poly_uv( +static bool mesh_calc_islands_loop_poly_uv( MVert *UNUSED(verts), const int UNUSED(totvert), MEdge *edges, const int totedge, MPoly *polys, const int totpoly, MLoop *loops, const int totloop, + const MLoopUV *luvs, MeshIslandStore *r_island_store) { int *poly_groups = NULL; @@ -879,6 +965,11 @@ bool BKE_mesh_calc_islands_loop_poly_uv( MeshElemMap *edge_poly_map; int *edge_poly_mem; + MeshElemMap *edge_loop_map; + int *edge_loop_mem; + + MeshCheckIslandBoundaryUv edge_boundary_check_data; + int *poly_indices; int *loop_indices; int num_pidx, num_lidx; @@ -899,9 +990,18 @@ bool BKE_mesh_calc_islands_loop_poly_uv( BKE_mesh_edge_poly_map_create(&edge_poly_map, &edge_poly_mem, edges, totedge, polys, totpoly, loops, totloop); + if (luvs) { + BKE_mesh_edge_loop_map_create(&edge_loop_map, &edge_loop_mem, + edges, totedge, polys, totpoly, loops, totloop); + edge_boundary_check_data.loops = loops; + edge_boundary_check_data.luvs = luvs; + edge_boundary_check_data.edge_loop_map = edge_loop_map; + } + poly_edge_loop_islands_calc( - edges, totedge, polys, totpoly, loops, totloop, edge_poly_map, false, - mesh_check_island_boundary_uv, &poly_groups, &num_poly_groups, &edge_borders, &num_edge_borders); + edges, totedge, polys, totpoly, loops, totloop, edge_poly_map, false, + mesh_check_island_boundary_uv, luvs ? &edge_boundary_check_data : NULL, + &poly_groups, &num_poly_groups, &edge_borders, &num_edge_borders); if (!num_poly_groups) { /* Should never happen... */ @@ -958,6 +1058,11 @@ bool BKE_mesh_calc_islands_loop_poly_uv( MEM_freeN(edge_poly_map); MEM_freeN(edge_poly_mem); + if (luvs) { + MEM_freeN(edge_loop_map); + MEM_freeN(edge_loop_mem); + } + MEM_freeN(poly_indices); MEM_freeN(loop_indices); MEM_freeN(poly_groups); @@ -973,4 +1078,42 @@ bool BKE_mesh_calc_islands_loop_poly_uv( return true; } +/** + * Calculate 'generic' UV islands, i.e. based only on actual geometry data (edge seams), not some UV layers coordinates. + */ +bool BKE_mesh_calc_islands_loop_poly_edgeseam( + MVert *verts, const int totvert, + MEdge *edges, const int totedge, + MPoly *polys, const int totpoly, + MLoop *loops, const int totloop, + MeshIslandStore *r_island_store) +{ + return mesh_calc_islands_loop_poly_uv( + verts, totvert, edges, totedge, polys, totpoly, loops, totloop, NULL, r_island_store); +} + +/** + * Calculate UV islands. + * + * \note If no MLoopUV layer is passed, we only consider edges tagged as seams as UV boundaries. + * This has the advantages of simplicity, and being valid/common to all UV maps. + * However, it means actual UV islands whithout matching UV seams will not be handled correctly... + * If a valid UV layer is passed as \a luvs parameter, UV coordinates are also used to detect islands boundaries. + * + * \note All this could be optimized... + * Not sure it would be worth the more complex code, though, those loops are supposed to be really quick to do... + */ +bool BKE_mesh_calc_islands_loop_poly_uvmap( + MVert *verts, const int totvert, + MEdge *edges, const int totedge, + MPoly *polys, const int totpoly, + MLoop *loops, const int totloop, + const MLoopUV *luvs, + MeshIslandStore *r_island_store) +{ + BLI_assert(luvs != NULL); + return mesh_calc_islands_loop_poly_uv( + verts, totvert, edges, totedge, polys, totpoly, loops, totloop, luvs, r_island_store); +} + /** \} */ diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index 41e4c21d814..349e99bab61 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -707,7 +707,7 @@ void test_object_modifiers(Object *ob) */ const char *modifier_path_relbase(Object *ob) { - if (G.relbase_valid || ID_IS_LINKED_DATABLOCK(ob)) { + if (G.relbase_valid || ID_IS_LINKED(ob)) { return ID_BLEND_PATH(G.main, &ob->id); } else { diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 296a00388c4..fad7b3b098e 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -1211,7 +1211,6 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool ski } else { newtree = BKE_libblock_copy_nolib(&ntree->id, true); - newtree->id.lib = NULL; /* same as owning datablock id.lib */ } id_us_plus((ID *)newtree->gpd); @@ -1291,10 +1290,7 @@ static bNodeTree *ntreeCopyTree_internal(bNodeTree *ntree, Main *bmain, bool ski /* node tree will generate its own interface type */ newtree->interface_type = NULL; - if (ID_IS_LINKED_DATABLOCK(ntree)) { - BKE_id_expand_local(&newtree->id); - BKE_id_lib_local_paths(bmain, ntree->id.lib, &newtree->id); - } + BKE_id_copy_ensure_local(bmain, &ntree->id, &newtree->id); return newtree; } @@ -1951,34 +1947,9 @@ bNodeTree *ntreeFromID(ID *id) } } -void ntreeMakeLocal(Main *bmain, bNodeTree *ntree, bool id_in_mainlist) +void ntreeMakeLocal(Main *bmain, bNodeTree *ntree, bool id_in_mainlist, const bool lib_local) { - bool is_lib = false, is_local = false; - - /* - only lib users: do nothing - * - only local users: set flag - * - mixed: make copy - */ - - if (!ID_IS_LINKED_DATABLOCK(ntree)) { - return; - } - - BKE_library_ID_test_usages(bmain, ntree, &is_local, &is_lib); - - if (is_local) { - if (!is_lib) { - id_clear_lib_data_ex(bmain, (ID *)ntree, id_in_mainlist); - BKE_id_expand_local(&ntree->id); - } - else { - bNodeTree *ntree_new = ntreeCopyTree(bmain, ntree); - - ntree_new->id.us = 0; - - BKE_libblock_remap(bmain, ntree, ntree_new, ID_REMAP_SKIP_INDIRECT_USAGE); - } - } + BKE_id_make_local_generic(bmain, &ntree->id, id_in_mainlist, lib_local); } int ntreeNodeExists(bNodeTree *ntree, bNode *testnode) @@ -2681,7 +2652,7 @@ void BKE_node_clipboard_add_node(bNode *node) node_info->id = node->id; if (node->id) { BLI_strncpy(node_info->id_name, node->id->name, sizeof(node_info->id_name)); - if (ID_IS_LINKED_DATABLOCK(node->id)) { + if (ID_IS_LINKED_DATABLOCK(node->id)) { /* Don't want virtual libraries here... */ BLI_strncpy(node_info->library_name, node->id->lib->filepath, sizeof(node_info->library_name)); } else { diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 30a193506a6..4bf92c30c6a 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1169,10 +1169,7 @@ Object *BKE_object_copy_ex(Main *bmain, Object *ob, bool copy_caches) /* Copy runtime surve data. */ obn->curve_cache = NULL; - if (ID_IS_LINKED_DATABLOCK(ob)) { - BKE_id_expand_local(&obn->id); - BKE_id_lib_local_paths(bmain, ob->id.lib, &obn->id); - } + BKE_id_copy_ensure_local(bmain, &ob->id, &obn->id); /* Do not copy object's preview (mostly due to the fact renderers create temp copy of objects). */ obn->preview = NULL; @@ -1186,22 +1183,23 @@ Object *BKE_object_copy(Main *bmain, Object *ob) return BKE_object_copy_ex(bmain, ob, false); } -void BKE_object_make_local(Main *bmain, Object *ob) +void BKE_object_make_local(Main *bmain, Object *ob, const bool lib_local) { bool is_local = false, is_lib = false; - /* - only lib users: do nothing + /* - only lib users: do nothing (unless force_local is set) * - only local users: set flag * - mixed: make copy + * In case we make a whole lib's content local, we always want to localize, and we skip remapping (done later). */ - if (!ID_IS_LINKED_DATABLOCK(ob)) { + if (!ID_IS_LINKED(ob)) { return; } BKE_library_ID_test_usages(bmain, ob, &is_local, &is_lib); - if (is_local) { + if (lib_local || is_local) { if (!is_lib) { id_clear_lib_data(bmain, &ob->id); BKE_id_expand_local(&ob->id); @@ -1212,7 +1210,9 @@ void BKE_object_make_local(Main *bmain, Object *ob) ob_new->id.us = 0; ob_new->proxy = ob_new->proxy_from = ob_new->proxy_group = NULL; - BKE_libblock_remap(bmain, ob, ob_new, ID_REMAP_SKIP_INDIRECT_USAGE); + if (!lib_local) { + BKE_libblock_remap(bmain, ob, ob_new, ID_REMAP_SKIP_INDIRECT_USAGE); + } } } } @@ -1220,15 +1220,15 @@ void BKE_object_make_local(Main *bmain, Object *ob) /* Returns true if the Object is from an external blend file (libdata) */ bool BKE_object_is_libdata(Object *ob) { - return (ob && ID_IS_LINKED_DATABLOCK(ob)); + return (ob && ID_IS_LINKED(ob)); } /* Returns true if the Object data is from an external blend file (libdata) */ bool BKE_object_obdata_is_libdata(Object *ob) { /* Linked objects with local obdata are forbidden! */ - BLI_assert(!ob || !ob->data || (ID_IS_LINKED_DATABLOCK(ob) ? ID_IS_LINKED_DATABLOCK(ob->data) : true)); - return (ob && ob->data && ID_IS_LINKED_DATABLOCK(ob->data)); + BLI_assert(!ob || !ob->data || (ID_IS_LINKED(ob) ? ID_IS_LINKED(ob->data) : true)); + return (ob && ob->data && ID_IS_LINKED(ob->data)); } /* *************** PROXY **************** */ @@ -1275,7 +1275,7 @@ void BKE_object_copy_proxy_drivers(Object *ob, Object *target) /* only on local objects because this causes indirect links * 'a -> b -> c', blend to point directly to a.blend * when a.blend has a proxy thats linked into c.blend */ - if (!ID_IS_LINKED_DATABLOCK(ob)) + if (!ID_IS_LINKED(ob)) id_lib_extern((ID *)dtar->id); } } @@ -1293,7 +1293,7 @@ void BKE_object_copy_proxy_drivers(Object *ob, Object *target) void BKE_object_make_proxy(Object *ob, Object *target, Object *gob) { /* paranoia checks */ - if (ID_IS_LINKED_DATABLOCK(ob) || !ID_IS_LINKED_DATABLOCK(target)) { + if (ID_IS_LINKED(ob) || !ID_IS_LINKED(target)) { printf("cannot make proxy\n"); return; } @@ -2670,7 +2670,7 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx, printf("recalcob %s\n", ob->id.name + 2); /* handle proxy copy for target */ - if (ID_IS_LINKED_DATABLOCK(ob) && ob->proxy_from) { + if (ID_IS_LINKED(ob) && ob->proxy_from) { // printf("ob proxy copy, lib ob %s proxy %s\n", ob->id.name, ob->proxy_from->id.name); if (ob->proxy_from->proxy_group) { /* transform proxy into group space */ Object *obg = ob->proxy_from->proxy_group; diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 457263f854b..ebd090bcc5b 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -203,7 +203,7 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx, break; } case OB_ARMATURE: - if (ID_IS_LINKED_DATABLOCK(ob) && ob->proxy_from) { + if (ID_IS_LINKED(ob) && ob->proxy_from) { if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) { printf("Proxy copy error, lib Object: %s proxy Object: %s\n", ob->id.name + 2, ob->proxy_from->id.name + 2); @@ -315,7 +315,7 @@ void BKE_object_eval_uber_transform(EvaluationContext *UNUSED(eval_ctx), // XXX: it's almost redundant now... /* Handle proxy copy for target, */ - if (ID_IS_LINKED_DATABLOCK(ob) && ob->proxy_from) { + if (ID_IS_LINKED(ob) && ob->proxy_from) { if (ob->proxy_from->proxy_group) { /* Transform proxy into group space. */ Object *obg = ob->proxy_from->proxy_group; @@ -347,10 +347,3 @@ void BKE_object_eval_uber_data(EvaluationContext *eval_ctx, ob->recalc &= ~(OB_RECALC_DATA | OB_RECALC_TIME); } - -void BKE_object_eval_proxy_backlink(EvaluationContext *UNUSED(eval_ctx), Object *ob) -{ - if (ob->proxy) { - ob->proxy->proxy_from = ob; - } -} diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c index 489fc2f3710..08aca2a44a3 100644 --- a/source/blender/blenkernel/intern/packedFile.c +++ b/source/blender/blenkernel/intern/packedFile.c @@ -232,7 +232,7 @@ void packAll(Main *bmain, ReportList *reports, bool verbose) int tot = 0; for (ima = bmain->image.first; ima; ima = ima->id.next) { - if (BKE_image_has_packedfile(ima) == false && !ID_IS_LINKED_DATABLOCK(ima)) { + if (BKE_image_has_packedfile(ima) == false && !ID_IS_LINKED(ima)) { if (ima->source == IMA_SRC_FILE) { BKE_image_packfiles(reports, ima, ID_BLEND_PATH(bmain, &ima->id)); tot ++; @@ -245,14 +245,14 @@ void packAll(Main *bmain, ReportList *reports, bool verbose) } for (vfont = bmain->vfont.first; vfont; vfont = vfont->id.next) { - if (vfont->packedfile == NULL && !ID_IS_LINKED_DATABLOCK(vfont) && BKE_vfont_is_builtin(vfont) == false) { + if (vfont->packedfile == NULL && !ID_IS_LINKED(vfont) && BKE_vfont_is_builtin(vfont) == false) { vfont->packedfile = newPackedFile(reports, vfont->name, bmain->name); tot ++; } } for (sound = bmain->sound.first; sound; sound = sound->id.next) { - if (sound->packedfile == NULL && !ID_IS_LINKED_DATABLOCK(sound)) { + if (sound->packedfile == NULL && !ID_IS_LINKED(sound)) { sound->packedfile = newPackedFile(reports, sound->name, bmain->name); tot++; } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 934c5b9ff06..42b818b35a5 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -3335,42 +3335,14 @@ ParticleSettings *BKE_particlesettings_copy(Main *bmain, ParticleSettings *part) BLI_duplicatelist(&partn->dupliweights, &part->dupliweights); - if (ID_IS_LINKED_DATABLOCK(part)) { - BKE_id_expand_local(&partn->id); - BKE_id_lib_local_paths(bmain, part->id.lib, &partn->id); - } + BKE_id_copy_ensure_local(bmain, &part->id, &partn->id); return partn; } -void BKE_particlesettings_make_local(Main *bmain, ParticleSettings *part) +void BKE_particlesettings_make_local(Main *bmain, ParticleSettings *part, const bool lib_local) { - bool is_local = false, is_lib = false; - - /* - only lib users: do nothing - * - only local users: set flag - * - mixed: make copy - */ - - if (!ID_IS_LINKED_DATABLOCK(part)) { - return; - } - - BKE_library_ID_test_usages(bmain, part, &is_local, &is_lib); - - if (is_local) { - if (!is_lib) { - id_clear_lib_data(bmain, &part->id); - BKE_id_expand_local(&part->id); - } - else { - ParticleSettings *part_new = BKE_particlesettings_copy(bmain, part); - - part_new->id.us = 0; - - BKE_libblock_remap(bmain, part, part_new, ID_REMAP_SKIP_INDIRECT_USAGE); - } - } + BKE_id_make_local_generic(bmain, &part->id, true, lib_local); } /************************************************/ diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 858b6bd927b..3e37ee83cea 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -344,7 +344,7 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) } } - scen->preview = BKE_previewimg_copy(sce->preview); + BKE_previewimg_id_copy(&scen->id, &sce->id); return scen; } @@ -355,6 +355,13 @@ void BKE_scene_groups_relink(Scene *sce) BKE_rigidbody_world_groups_relink(sce->rigidbody_world); } +void BKE_scene_make_local(Main *bmain, Scene *sce, const bool lib_local) +{ + /* For now should work, may need more work though to support all possible corner cases + * (also scene_copy probably needs some love). */ + BKE_id_make_local_generic(bmain, &sce->id, true, lib_local); +} + /** Free (or release) any data used by this scene (does not free the scene itself). */ void BKE_scene_free(Scene *sce) { @@ -1123,7 +1130,7 @@ char *BKE_scene_find_last_marker_name(Scene *scene, int frame) Base *BKE_scene_base_add(Scene *sce, Object *ob) { - Base *b = MEM_callocN(sizeof(*b), "BKE_scene_base_add"); + Base *b = MEM_callocN(sizeof(*b), __func__); BLI_addhead(&sce->base, b); b->object = ob; diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c index 3de4a426973..ce7c520438a 100644 --- a/source/blender/blenkernel/intern/seqeffects.c +++ b/source/blender/blenkernel/intern/seqeffects.c @@ -123,28 +123,34 @@ static ImBuf *prepare_effect_imbufs(const SeqRenderData *context, ImBuf *ibuf1, out = IMB_allocImBuf(x, y, 32, IB_rect); } - if (ibuf1 && !ibuf1->rect_float && out->rect_float) { - BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf1, true); - } - if (ibuf2 && !ibuf2->rect_float && out->rect_float) { - BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf2, true); - } - if (ibuf3 && !ibuf3->rect_float && out->rect_float) { - BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf3, true); - } + if (out->rect_float) { + if (ibuf1 && !ibuf1->rect_float) { + BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf1, true); + } + + if (ibuf2 && !ibuf2->rect_float) { + BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf2, true); + } + + if (ibuf3 && !ibuf3->rect_float) { + BKE_sequencer_imbuf_to_sequencer_space(scene, ibuf3, true); + } - if (ibuf1 && !ibuf1->rect && !out->rect_float) { - IMB_rect_from_float(ibuf1); - } - if (ibuf2 && !ibuf2->rect && !out->rect_float) { - IMB_rect_from_float(ibuf2); - } - if (ibuf3 && !ibuf3->rect && !out->rect_float) { - IMB_rect_from_float(ibuf3); + IMB_colormanagement_assign_float_colorspace(out, scene->sequencer_colorspace_settings.name); } + else { + if (ibuf1 && !ibuf1->rect) { + IMB_rect_from_float(ibuf1); + } - if (out->rect_float) - IMB_colormanagement_assign_float_colorspace(out, scene->sequencer_colorspace_settings.name); + if (ibuf2 && !ibuf2->rect) { + IMB_rect_from_float(ibuf2); + } + + if (ibuf3 && !ibuf3->rect) { + IMB_rect_from_float(ibuf3); + } + } /* If effect only affecting a single channel, forward input's metadata to the output. */ if (ibuf1 != NULL && ibuf1 == ibuf2 && ibuf2 == ibuf3) { diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 5ef502e0182..6067a8b2d9b 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -1308,41 +1308,40 @@ StripElem *BKE_sequencer_give_stripelem(Sequence *seq, int cfra) static int evaluate_seq_frame_gen(Sequence **seq_arr, ListBase *seqbase, int cfra, int chanshown) { - Sequence *seq; - Sequence *effect_inputs[MAXSEQ + 1]; - int i, totseq = 0, num_effect_inputs = 0; + /* Use arbitrary sized linked list, the size could be over MAXSEQ. */ + LinkNodePair effect_inputs = {NULL, NULL}; + int totseq = 0; memset(seq_arr, 0, sizeof(Sequence *) * (MAXSEQ + 1)); - seq = seqbase->first; - while (seq) { - if (seq->startdisp <= cfra && seq->enddisp > cfra) { + for (Sequence *seq = seqbase->first; seq; seq = seq->next) { + if ((seq->startdisp <= cfra) && (seq->enddisp > cfra)) { if ((seq->type & SEQ_TYPE_EFFECT) && !(seq->flag & SEQ_MUTE)) { + if (seq->seq1) { - effect_inputs[num_effect_inputs++] = seq->seq1; + BLI_linklist_append_alloca(&effect_inputs, seq->seq1); } if (seq->seq2) { - effect_inputs[num_effect_inputs++] = seq->seq2; + BLI_linklist_append_alloca(&effect_inputs, seq->seq2); } if (seq->seq3) { - effect_inputs[num_effect_inputs++] = seq->seq3; + BLI_linklist_append_alloca(&effect_inputs, seq->seq3); } } seq_arr[seq->machine] = seq; totseq++; } - seq = seq->next; } /* Drop strips which are used for effect inputs, we don't want * them to blend into render stack in any other way than effect * string rendering. */ - for (i = 0; i < num_effect_inputs; i++) { - seq = effect_inputs[i]; + for (LinkNode *seq_item = effect_inputs.list; seq_item; seq_item = seq_item->next) { + Sequence *seq = seq_item->link; /* It's possible that effetc strip would be placed to the same * 'machine' as it's inputs. We don't want to clear such strips * from the stack. @@ -1826,8 +1825,10 @@ static void seq_proxy_build_frame( IMB_freeImBuf(ibuf); } -/* returns whether the file this context would read from even exist, if not, don't create the context -*/ +/** + * Returns whether the file this context would read from even exist, + * if not, don't create the context + */ static bool seq_proxy_multiview_context_invalid(Sequence *seq, Scene *scene, const int view_id) { if ((scene->r.scemode & R_MULTIVIEW) == 0) @@ -1862,8 +1863,9 @@ static bool seq_proxy_multiview_context_invalid(Sequence *seq, Scene *scene, con return false; } -/** This returns the maximum possible number of required contexts -*/ +/** + * This returns the maximum possible number of required contexts + */ static int seq_proxy_context_count(Sequence *seq, Scene *scene) { int num_views = 1; @@ -3556,7 +3558,7 @@ static ImBuf *seq_render_strip( if (ibuf == NULL) { /* MOVIECLIPs have their own proxy management */ - if (ibuf == NULL && seq->type != SEQ_TYPE_MOVIECLIP) { + if (seq->type != SEQ_TYPE_MOVIECLIP) { ibuf = seq_proxy_fetch(context, seq, cfra); is_proxy_image = (ibuf != NULL); } diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 414be73e234..2f47966ec55 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -155,6 +155,11 @@ void BKE_sound_free(bSound *sound) #endif /* WITH_AUDASPACE */ } +void BKE_sound_make_local(Main *bmain, bSound *sound, const bool lib_local) +{ + BKE_id_make_local_generic(bmain, &sound->id, true, lib_local); +} + #ifdef WITH_AUDASPACE static const char *force_device = NULL; diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c index a91d8657179..ee6886e3fb2 100644 --- a/source/blender/blenkernel/intern/speaker.c +++ b/source/blender/blenkernel/intern/speaker.c @@ -77,42 +77,14 @@ Speaker *BKE_speaker_copy(Main *bmain, Speaker *spk) if (spkn->sound) id_us_plus(&spkn->sound->id); - if (ID_IS_LINKED_DATABLOCK(spk)) { - BKE_id_expand_local(&spkn->id); - BKE_id_lib_local_paths(G.main, spk->id.lib, &spkn->id); - } + BKE_id_copy_ensure_local(bmain, &spk->id, &spkn->id); return spkn; } -void BKE_speaker_make_local(Main *bmain, Speaker *spk) +void BKE_speaker_make_local(Main *bmain, Speaker *spk, const bool lib_local) { - bool is_local = false, is_lib = false; - - /* - only lib users: do nothing - * - only local users: set flag - * - mixed: make copy - */ - - if (!ID_IS_LINKED_DATABLOCK(spk)) { - return; - } - - BKE_library_ID_test_usages(bmain, spk, &is_local, &is_lib); - - if (is_local) { - if (!is_lib) { - id_clear_lib_data(bmain, &spk->id); - BKE_id_expand_local(&spk->id); - } - else { - Speaker *spk_new = BKE_speaker_copy(bmain, spk); - - spk_new->id.us = 0; - - BKE_libblock_remap(bmain, spk, spk_new, ID_REMAP_SKIP_INDIRECT_USAGE); - } - } + BKE_id_make_local_generic(bmain, &spk->id, true, lib_local); } void BKE_speaker_free(Speaker *spk) diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index b0d19320230..04bcd366c3f 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -794,14 +794,20 @@ static void ss_sync_osd_from_derivedmesh(CCGSubSurf *ss, static void ss_sync_from_derivedmesh(CCGSubSurf *ss, DerivedMesh *dm, float (*vertexCos)[3], - int use_flat_subdiv) + int use_flat_subdiv, + bool use_subdiv_uvs) { +#ifndef WITH_OPENSUBDIV + UNUSED_VARS(use_subdiv_uvs); +#endif + #ifdef WITH_OPENSUBDIV /* Reset all related descriptors if actual mesh topology changed or if * other evaluation-related settings changed. */ if (!ccgSubSurf_needGrids(ss)) { /* TODO(sergey): Use vertex coordinates and flat subdiv flag. */ + ccgSubSurf__sync_subdivUvs(ss, use_subdiv_uvs); ccgSubSurf_checkTopologyChanged(ss, dm); ss_sync_osd_from_derivedmesh(ss, dm); } @@ -1801,7 +1807,7 @@ static void ccgDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEd #ifdef WITH_OPENSUBDIV if (ccgdm->useGpuBackend) { /* TODO(sergey): We currently only support all edges drawing. */ - if (ccgSubSurf_prepareGLMesh(ccgdm->ss, true)) { + if (ccgSubSurf_prepareGLMesh(ccgdm->ss, true, -1)) { ccgSubSurf_drawGLMesh(ccgdm->ss, false, -1, -1); } return; @@ -2638,7 +2644,7 @@ static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes) int mat_nr = -1; bool draw_smooth = false; int start_draw_patch = -1, num_draw_patches = 0; - if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, setMaterial != NULL) == false)) { + if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, setMaterial != NULL, -1) == false)) { return; } if (setMaterial == NULL) { @@ -2750,7 +2756,7 @@ static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, bool draw_smooth = false; int start_draw_patch = -1, num_draw_patches = 0; GPU_draw_update_fvar_offset(dm); - if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, false) == false)) { + if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, false, -1) == false)) { return; } for (i = 0; i < num_base_faces; ++i) { @@ -3193,7 +3199,7 @@ static void ccgDM_drawMappedFacesMat(DerivedMesh *dm, int new_matnr; bool draw_smooth; GPU_draw_update_fvar_offset(dm); - if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, true) == false)) { + if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, true, -1) == false)) { return; } /* TODO(sergey): Single matierial currently. */ @@ -3386,19 +3392,6 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, int mat_index; int tot_element, start_element, tot_drawn; -#ifdef WITH_OPENSUBDIV - if (ccgdm->useGpuBackend) { - if (ccgSubSurf_prepareGLMesh(ss, true) == false) { - return; - } - ccgSubSurf_drawGLMesh(ss, true, -1, -1); - return; - } -#endif - - CCG_key_top_level(&key, ss); - ccgdm_pbvh_update(ccgdm); - if (use_colors) { colType = CD_TEXTURE_MLOOPCOL; mloopcol = dm->getLoopDataArray(dm, colType); @@ -3412,6 +3405,87 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, } } +#ifdef WITH_OPENSUBDIV + if (ccgdm->useGpuBackend) { + const int active_uv_layer = CustomData_get_active_layer_index(&dm->loopData, CD_MLOOPUV); + if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, true, active_uv_layer) == false)) { + return; + } + if (drawParams == NULL) { + ccgSubSurf_drawGLMesh(ss, true, -1, -1); + return; + } + const int level = ccgSubSurf_getSubdivisionLevels(ss); + const int face_side = 1 << level; + const int grid_side = 1 << (level - 1); + const int face_patches = face_side * face_side; + const int grid_patches = grid_side * grid_side; + const int num_base_faces = ccgSubSurf_getNumGLMeshBaseFaces(ss); + int current_patch = 0; + int mat_nr = -1; + int start_draw_patch = 0, num_draw_patches = 0; + bool draw_smooth = false; + for (i = 0; i < num_base_faces; ++i) { + const int num_face_verts = ccgSubSurf_getNumGLMeshBaseFaceVerts(ss, i); + const int num_patches = (num_face_verts == 4) ? face_patches + : num_face_verts * grid_patches; + if (faceFlags) { + mat_nr = faceFlags[i].mat_nr; + draw_smooth = (faceFlags[i].flag & ME_SMOOTH); + } + else { + mat_nr = 0; + draw_smooth = false; + } + + if (drawParams != NULL) { + MTexPoly *tp = (use_tface && mtexpoly) ? &mtexpoly[i] : NULL; + draw_option = drawParams(tp, (mloopcol != NULL), mat_nr); + } + else { + draw_option = (drawParamsMapped) + ? drawParamsMapped(userData, i, mat_nr) + : DM_DRAW_OPTION_NORMAL; + } + + flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == num_base_faces - 1); + + const int next_face = min_ii(i + 1, num_base_faces - 1); + if (!flush && compareDrawOptions) { + flush |= compareDrawOptions(userData, i, next_face) == 0; + } + if (!flush && faceFlags) { + bool new_draw_smooth = (faceFlags[next_face].flag & ME_SMOOTH); + flush |= (new_draw_smooth != draw_smooth); + } + + current_patch += num_patches; + + if (flush) { + if (draw_option != DM_DRAW_OPTION_SKIP) { + num_draw_patches += num_patches; + } + if (num_draw_patches != 0) { + glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT); + ccgSubSurf_drawGLMesh(ss, + true, + start_draw_patch, + num_draw_patches); + } + start_draw_patch = current_patch; + num_draw_patches = 0; + } + else { + num_draw_patches += num_patches; + } + } + return; + } +#endif + + CCG_key_top_level(&key, ss); + ccgdm_pbvh_update(ccgdm); + GPU_vertex_setup(dm); GPU_normal_setup(dm); GPU_triangle_setup(dm); @@ -3472,7 +3546,7 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, if (!flush && compareDrawOptions) { /* also compare draw options and flush buffer if they're different - * need for face selection highlight in edit mode */ + * need for face selection highlight in edit mode */ flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0; } @@ -3581,7 +3655,7 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, */ glColor3f(0.8f, 0.8f, 0.8f); } - if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, true) == false)) { + if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, true, -1) == false)) { return; } if (faceFlags) { @@ -3780,7 +3854,7 @@ static void ccgDM_drawMappedEdges(DerivedMesh *dm, #ifdef WITH_OPENSUBDIV if (ccgdm->useGpuBackend) { /* TODO(sergey): Only draw edges from base mesh. */ - if (ccgSubSurf_prepareGLMesh(ccgdm->ss, true)) { + if (ccgSubSurf_prepareGLMesh(ccgdm->ss, true, -1)) { if (!setDrawOptions || (setDrawOptions(userData, 0) != DM_DRAW_OPTION_SKIP)) { ccgSubSurf_drawGLMesh(ccgdm->ss, false, -1, -1); } @@ -4970,7 +5044,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( #ifdef WITH_OPENSUBDIV ccgSubSurf_setSkipGrids(smd->emCache, use_gpu_backend); #endif - ss_sync_from_derivedmesh(smd->emCache, dm, vertCos, useSimple); + ss_sync_from_derivedmesh(smd->emCache, dm, vertCos, useSimple, useSubsurfUv); result = getCCGDerivedMesh(smd->emCache, drawInteriorEdges, useSubsurfUv, dm, use_gpu_backend); @@ -4985,7 +5059,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( ss = _getSubSurf(NULL, levels, 3, useSimple | CCG_USE_ARENA | CCG_CALC_NORMALS); - ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple); + ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple, useSubsurfUv); result = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm, false); @@ -5016,7 +5090,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( if (useIncremental && (flags & SUBSURF_IS_FINAL_CALC)) { smd->mCache = ss = _getSubSurf(smd->mCache, levels, 3, useSimple | useAging | CCG_CALC_NORMALS); - ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple); + ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple, useSubsurfUv); result = getCCGDerivedMesh(smd->mCache, drawInteriorEdges, @@ -5056,7 +5130,7 @@ struct DerivedMesh *subsurf_make_derived_from_derived( #ifdef WITH_OPENSUBDIV ccgSubSurf_setSkipGrids(ss, use_gpu_backend); #endif - ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple); + ss_sync_from_derivedmesh(ss, dm, vertCos, useSimple, useSubsurfUv); result = getCCGDerivedMesh(ss, drawInteriorEdges, useSubsurfUv, dm, use_gpu_backend); @@ -5085,7 +5159,7 @@ void subsurf_calculate_limit_positions(Mesh *me, float (*r_positions)[3]) CCGVertIterator vi; DerivedMesh *dm = CDDM_from_mesh(me); - ss_sync_from_derivedmesh(ss, dm, NULL, 0); + ss_sync_from_derivedmesh(ss, dm, NULL, 0, 0); for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) { CCGVert *v = ccgVertIterator_getCurrent(&vi); diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 269d6d32b31..1636042f479 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -491,14 +491,16 @@ Text *BKE_text_copy(Main *bmain, Text *ta) init_undo_text(tan); - if (ID_IS_LINKED_DATABLOCK(ta)) { - BKE_id_expand_local(&tan->id); - BKE_id_lib_local_paths(bmain, ta->id.lib, &tan->id); - } + BKE_id_copy_ensure_local(bmain, &ta->id, &tan->id); return tan; } +void BKE_text_make_local(Main *bmain, Text *text, const bool lib_local) +{ + BKE_id_make_local_generic(bmain, &text->id, true, lib_local); +} + void BKE_text_clear(Text *text) /* called directly from rna */ { int oldstate; diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index e34d632f2ca..2d3ecad19ad 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -863,7 +863,6 @@ Tex *BKE_texture_copy(Main *bmain, Tex *tex) if (texn->pd) texn->pd = BKE_texture_pointdensity_copy(texn->pd); if (texn->vd) texn->vd = MEM_dupallocN(texn->vd); if (texn->ot) texn->ot = BKE_texture_ocean_copy(texn->ot); - if (tex->preview) texn->preview = BKE_previewimg_copy(tex->preview); if (tex->nodetree) { if (tex->nodetree->execdata) { @@ -871,13 +870,10 @@ Tex *BKE_texture_copy(Main *bmain, Tex *tex) } texn->nodetree = ntreeCopyTree(bmain, tex->nodetree); } - - texn->preview = BKE_previewimg_copy(tex->preview); - if (ID_IS_LINKED_DATABLOCK(tex)) { - BKE_id_expand_local(&texn->id); - BKE_id_lib_local_paths(bmain, tex->id.lib, &texn->id); - } + BKE_previewimg_id_copy(&texn->id, &tex->id); + + BKE_id_copy_ensure_local(bmain, &tex->id, &texn->id); return texn; } @@ -918,34 +914,9 @@ Tex *BKE_texture_localize(Tex *tex) /* ------------------------------------------------------------------------- */ -void BKE_texture_make_local(Main *bmain, Tex *tex) +void BKE_texture_make_local(Main *bmain, Tex *tex, const bool lib_local) { - bool is_local = false, is_lib = false; - - /* - only lib users: do nothing - * - only local users: set flag - * - mixed: make copy - */ - - if (!ID_IS_LINKED_DATABLOCK(tex)) { - return; - } - - BKE_library_ID_test_usages(bmain, tex, &is_local, &is_lib); - - if (is_local) { - if (!is_lib) { - id_clear_lib_data(bmain, &tex->id); - BKE_id_expand_local(&tex->id); - } - else { - Tex *tex_new = BKE_texture_copy(bmain, tex); - - tex_new->id.us = 0; - - BKE_libblock_remap(bmain, tex, tex_new, ID_REMAP_SKIP_INDIRECT_USAGE); - } - } + BKE_id_make_local_generic(bmain, &tex->id, true, lib_local); } Tex *give_current_object_texture(Object *ob) diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c index 9df30a8acc9..3b56ea271d0 100644 --- a/source/blender/blenkernel/intern/tracking_auto.c +++ b/source/blender/blenkernel/intern/tracking_auto.c @@ -376,6 +376,9 @@ bool BKE_autotrack_context_step(AutoTrackContext *context) #pragma omp parallel for if (context->num_tracks > 1) for (track = 0; track < context->num_tracks; ++track) { AutoTrackOptions *options = &context->options[track]; + if (options->is_failed) { + continue; + } libmv_Marker libmv_current_marker, libmv_reference_marker, libmv_tracked_marker; @@ -463,16 +466,25 @@ void BKE_autotrack_context_sync(AutoTrackContext *context) AutoTrackOptions *options = &context->options[track]; int track_frame = BKE_movieclip_remap_scene_to_clip_frame( context->clips[options->clip_index], frame); - if (options->is_failed && options->failed_frame == track_frame) { - MovieTrackingMarker *prev_marker = - BKE_tracking_marker_get_exact(options->track, frame); - if (prev_marker) { - marker = *prev_marker; - marker.framenr = context->backwards ? - track_frame - 1 : - track_frame + 1; - marker.flag |= MARKER_DISABLED; - BKE_tracking_marker_insert(options->track, &marker); + if (options->is_failed) { + if (options->failed_frame == track_frame) { + MovieTrackingMarker *prev_marker = + BKE_tracking_marker_get_exact( + options->track, + context->backwards + ? frame + 1 + : frame - 1); + if (prev_marker) { + marker = *prev_marker; + marker.framenr = track_frame; + marker.flag |= MARKER_DISABLED; + BKE_tracking_marker_insert(options->track, &marker); + continue; + } + } + if ((context->backwards && options->failed_frame > track_frame) || + (!context->backwards && options->failed_frame < track_frame)) + { continue; } } diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c index a40e4f72636..a90b1dee927 100644 --- a/source/blender/blenkernel/intern/tracking_util.c +++ b/source/blender/blenkernel/intern/tracking_util.c @@ -762,8 +762,8 @@ static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor, final_ibuf = IMB_dupImBuf(orig_ibuf); } IMB_scaleImBuf(final_ibuf, - ibuf->x / (1 << downscale), - ibuf->y / (1 << downscale)); + orig_ibuf->x / (1 << downscale), + orig_ibuf->y / (1 << downscale)); } if (transform != NULL) { @@ -780,7 +780,7 @@ static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor, } if (input_mode == LIBMV_IMAGE_MODE_RGBA) { - BLI_assert(ibuf->channels == 3 || ibuf->channels == 4); + BLI_assert(orig_ibuf->channels == 3 || orig_ibuf->channels == 4); /* pass */ } else /* if (input_mode == LIBMV_IMAGE_MODE_MONO) */ { diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 9795a8174f8..de1e3187a70 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -138,14 +138,11 @@ World *BKE_world_copy(Main *bmain, World *wrld) wrldn->nodetree = ntreeCopyTree(bmain, wrld->nodetree); } - wrldn->preview = BKE_previewimg_copy(wrld->preview); + BKE_previewimg_id_copy(&wrldn->id, &wrld->id); BLI_listbase_clear(&wrldn->gpumaterial); - if (ID_IS_LINKED_DATABLOCK(wrld)) { - BKE_id_expand_local(&wrldn->id); - BKE_id_lib_local_paths(bmain, wrld->id.lib, &wrldn->id); - } + BKE_id_copy_ensure_local(bmain, &wrld->id, &wrldn->id); return wrldn; } @@ -176,32 +173,7 @@ World *localize_world(World *wrld) return wrldn; } -void BKE_world_make_local(Main *bmain, World *wrld) +void BKE_world_make_local(Main *bmain, World *wrld, const bool lib_local) { - bool is_local = false, is_lib = false; - - /* - only lib users: do nothing - * - only local users: set flag - * - mixed: make copy - */ - - if (!ID_IS_LINKED_DATABLOCK(wrld)) { - return; - } - - BKE_library_ID_test_usages(bmain, wrld, &is_local, &is_lib); - - if (is_local) { - if (!is_lib) { - id_clear_lib_data(bmain, &wrld->id); - BKE_id_expand_local(&wrld->id); - } - else { - World *wrld_new = BKE_world_copy(bmain, wrld); - - wrld_new->id.us = 0; - - BKE_libblock_remap(bmain, wrld, wrld_new, ID_REMAP_SKIP_INDIRECT_USAGE); - } - } + BKE_id_make_local_generic(bmain, &wrld->id, true, lib_local); } diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index edeccf472c8..9dbc045f1b0 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -1672,9 +1672,6 @@ bool BKE_ffmpeg_alpha_channel_is_supported(RenderData *rd) if (codec == AV_CODEC_ID_PNG) return true; - if (codec == AV_CODEC_ID_PNG) - return true; - if (codec == AV_CODEC_ID_HUFFYUV) return true; diff --git a/source/blender/blenlib/BLI_threads.h b/source/blender/blenlib/BLI_threads.h index b4a465bbc74..0b1b4d8ee8c 100644 --- a/source/blender/blenlib/BLI_threads.h +++ b/source/blender/blenlib/BLI_threads.h @@ -42,7 +42,7 @@ extern "C" { #endif /* for tables, button in UI, etc */ -#define BLENDER_MAX_THREADS 64 +#define BLENDER_MAX_THREADS 1024 struct ListBase; struct TaskScheduler; diff --git a/source/blender/blenlib/intern/BLI_heap.c b/source/blender/blenlib/intern/BLI_heap.c index 4bd404e5d73..0a8dafc2dc1 100644 --- a/source/blender/blenlib/intern/BLI_heap.c +++ b/source/blender/blenlib/intern/BLI_heap.c @@ -32,7 +32,6 @@ #include "MEM_guardedalloc.h" #include "BLI_utildefines.h" -#include "BLI_memarena.h" #include "BLI_heap.h" #include "BLI_strict_flags.h" @@ -44,15 +43,37 @@ struct HeapNode { unsigned int index; }; +struct HeapNode_Chunk { + struct HeapNode_Chunk *prev; + unsigned int size; + unsigned int bufsize; + struct HeapNode buf[0]; +}; + +/** + * Number of nodes to include per #HeapNode_Chunk when no reserved size is passed, + * or we allocate past the reserved number. + * + * \note Optimize number for 64kb allocs. + */ +#define HEAP_CHUNK_DEFAULT_NUM \ + ((MEM_SIZE_OPTIMAL((1 << 16) - sizeof(struct HeapNode_Chunk))) / sizeof(HeapNode)) + struct Heap { unsigned int size; unsigned int bufsize; - MemArena *arena; - HeapNode *freenodes; HeapNode **tree; + + struct { + /* Always keep at least one chunk (never NULL) */ + struct HeapNode_Chunk *chunk; + /* when NULL, allocate a new chunk */ + HeapNode *free; + } nodes; }; -/* internal functions */ +/** \name Internal Functions + * \{ */ #define HEAP_PARENT(i) (((i) - 1) >> 1) #define HEAP_LEFT(i) (((i) << 1) + 1) @@ -92,11 +113,13 @@ static void heap_down(Heap *heap, unsigned int i) smallest = ((l < size) && HEAP_COMPARE(heap->tree[l], heap->tree[i])) ? l : i; - if ((r < size) && HEAP_COMPARE(heap->tree[r], heap->tree[smallest])) + if ((r < size) && HEAP_COMPARE(heap->tree[r], heap->tree[smallest])) { smallest = r; + } - if (smallest == i) + if (smallest == i) { break; + } heap_swap(heap, i, smallest); i = smallest; @@ -108,25 +131,73 @@ static void heap_up(Heap *heap, unsigned int i) while (i > 0) { const unsigned int p = HEAP_PARENT(i); - if (HEAP_COMPARE(heap->tree[p], heap->tree[i])) + if (HEAP_COMPARE(heap->tree[p], heap->tree[i])) { break; - + } heap_swap(heap, p, i); i = p; } } +/** \} */ -/***/ + +/** \name Internal Memory Management + * \{ */ + +static struct HeapNode_Chunk *heap_node_alloc_chunk( + unsigned int tot_nodes, struct HeapNode_Chunk *chunk_prev) +{ + struct HeapNode_Chunk *chunk = MEM_mallocN( + sizeof(struct HeapNode_Chunk) + (sizeof(HeapNode) * tot_nodes), __func__); + chunk->prev = chunk_prev; + chunk->bufsize = tot_nodes; + chunk->size = 0; + return chunk; +} + +static struct HeapNode *heap_node_alloc(Heap *heap) +{ + HeapNode *node; + + if (heap->nodes.free) { + node = heap->nodes.free; + heap->nodes.free = heap->nodes.free->ptr; + } + else { + struct HeapNode_Chunk *chunk = heap->nodes.chunk; + if (UNLIKELY(chunk->size == chunk->bufsize)) { + chunk = heap->nodes.chunk = heap_node_alloc_chunk(HEAP_CHUNK_DEFAULT_NUM, chunk); + } + node = &chunk->buf[chunk->size++]; + } + + return node; +} + +static void heap_node_free(Heap *heap, HeapNode *node) +{ + node->ptr = heap->nodes.free; + heap->nodes.free = node; +} + +/** \} */ + + +/** \name Public Heap API + * \{ */ /* use when the size of the heap is known in advance */ Heap *BLI_heap_new_ex(unsigned int tot_reserve) { - Heap *heap = (Heap *)MEM_callocN(sizeof(Heap), __func__); + Heap *heap = MEM_mallocN(sizeof(Heap), __func__); /* ensure we have at least one so we can keep doubling it */ + heap->size = 0; heap->bufsize = MAX2(1u, tot_reserve); - heap->tree = (HeapNode **)MEM_mallocN(heap->bufsize * sizeof(HeapNode *), "BLIHeapTree"); - heap->arena = BLI_memarena_new(MEM_SIZE_OPTIMAL(1 << 16), "heap arena"); + heap->tree = MEM_mallocN(heap->bufsize * sizeof(HeapNode *), "BLIHeapTree"); + + heap->nodes.chunk = heap_node_alloc_chunk((tot_reserve > 1) ? tot_reserve : HEAP_CHUNK_DEFAULT_NUM, NULL); + heap->nodes.free = NULL; return heap; } @@ -146,8 +217,15 @@ void BLI_heap_free(Heap *heap, HeapFreeFP ptrfreefp) } } + struct HeapNode_Chunk *chunk = heap->nodes.chunk; + do { + struct HeapNode_Chunk *chunk_prev; + chunk_prev = chunk->prev; + MEM_freeN(chunk); + chunk = chunk_prev; + } while (chunk); + MEM_freeN(heap->tree); - BLI_memarena_free(heap->arena); MEM_freeN(heap); } @@ -160,10 +238,16 @@ void BLI_heap_clear(Heap *heap, HeapFreeFP ptrfreefp) ptrfreefp(heap->tree[i]->ptr); } } - heap->size = 0; - BLI_memarena_clear(heap->arena); - heap->freenodes = NULL; + + /* Remove all except the last chunk */ + while (heap->nodes.chunk->prev) { + struct HeapNode_Chunk *chunk_prev = heap->nodes.chunk->prev; + MEM_freeN(heap->nodes.chunk); + heap->nodes.chunk = chunk_prev; + } + heap->nodes.chunk->size = 0; + heap->nodes.free = NULL; } HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr) @@ -175,13 +259,7 @@ HeapNode *BLI_heap_insert(Heap *heap, float value, void *ptr) heap->tree = MEM_reallocN(heap->tree, heap->bufsize * sizeof(*heap->tree)); } - if (heap->freenodes) { - node = heap->freenodes; - heap->freenodes = heap->freenodes->ptr; - } - else { - node = (HeapNode *)BLI_memarena_alloc(heap->arena, sizeof(*node)); - } + node = heap_node_alloc(heap); node->ptr = ptr; node->value = value; @@ -217,8 +295,7 @@ void *BLI_heap_popmin(Heap *heap) BLI_assert(heap->size != 0); - heap->tree[0]->ptr = heap->freenodes; - heap->freenodes = heap->tree[0]; + heap_node_free(heap, heap->tree[0]); if (--heap->size) { heap_swap(heap, 0, heap->size); @@ -254,3 +331,4 @@ void *BLI_heap_node_ptr(HeapNode *node) return node->ptr; } +/** \} */ diff --git a/source/blender/blenlib/intern/BLI_kdopbvh.c b/source/blender/blenlib/intern/BLI_kdopbvh.c index 92f4e998206..b14007a88cb 100644 --- a/source/blender/blenlib/intern/BLI_kdopbvh.c +++ b/source/blender/blenlib/intern/BLI_kdopbvh.c @@ -1917,7 +1917,7 @@ static void dist_squared_ray_to_aabb_scaled_v3_precalc( } /* un-normalize ray */ if (ray_is_normalized && scale && - (data->scale[0] != 1.0f || data->scale[1] != 1.0f || data->scale[2] != 1.0f)) + (data->scale[0] != 1.0f || data->scale[1] != 1.0f || data->scale[2] != 1.0f)) { data->ray.direction[0] = ray_direction[0] * data->scale[0]; data->ray.direction[1] = ray_direction[1] * data->scale[1]; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 2f7b1386a27..7fd08569984 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -115,7 +115,7 @@ #include "BKE_action.h" #include "BKE_armature.h" -#include "BKE_asset.h" +#include "BKE_asset_engine.h" #include "BKE_brush.h" #include "BKE_cloth.h" #include "BKE_constraint.h" @@ -1283,7 +1283,7 @@ void blo_freefiledata(FileData *fd) if (fd->filesdna) DNA_sdna_free(fd->filesdna); if (fd->compflags) - MEM_freeN(fd->compflags); + MEM_freeN((void *)fd->compflags); if (fd->datamap) oldnewmap_free(fd->datamap); @@ -2147,6 +2147,7 @@ static PreviewImage *direct_link_preview_image(FileData *fd, PreviewImage *old_p } prv->gputexture[i] = NULL; } + prv->icon_id = 0; } return prv; @@ -2718,7 +2719,7 @@ static void lib_link_node_socket(FileData *fd, ID *UNUSED(id), bNodeSocket *sock IDP_LibLinkProperty(sock->prop, (fd->flags & FD_FLAGS_SWITCH_ENDIAN), fd); } -/* singe node tree (also used for material/scene trees), ntree is not NULL */ +/* Single node tree (also used for material/scene trees), ntree is not NULL */ static void lib_link_ntree(FileData *fd, ID *id, bNodeTree *ntree) { bNode *node; @@ -2761,22 +2762,6 @@ static void lib_link_nodetree(FileData *fd, Main *main) } } -/* get node tree stored locally in other IDs */ -static bNodeTree *nodetree_from_id(ID *id) -{ - if (!id) - return NULL; - switch (GS(id->name)) { - case ID_SCE: return ((Scene *)id)->nodetree; - case ID_MA: return ((Material *)id)->nodetree; - case ID_WO: return ((World *)id)->nodetree; - case ID_LA: return ((Lamp *)id)->nodetree; - case ID_TE: return ((Tex *)id)->nodetree; - case ID_LS: return ((FreestyleLineStyle *)id)->nodetree; - } - return NULL; -} - /* updates group node socket identifier so that * external links to/from the group node are preserved. */ @@ -6355,11 +6340,9 @@ static void lib_link_screen(FileData *fd, Main *main) snode->id = newlibadr(fd, sc->id.lib, snode->id); snode->from = newlibadr(fd, sc->id.lib, snode->from); - ntree = nodetree_from_id(snode->id); - if (ntree) - snode->nodetree = ntree; - else { - snode->nodetree = newlibadr_us(fd, sc->id.lib, snode->nodetree); + if (snode->id) { + ntree = ntreeFromID(snode->id); + snode->nodetree = ntree ? ntree : newlibadr_us(fd, sc->id.lib, snode->nodetree); } for (path = snode->treepath.first; path; path = path->next) { @@ -6739,11 +6722,11 @@ void blo_lib_link_screen_restore(Main *newmain, bScreen *curscreen, Scene *cursc snode->id = restore_pointer_by_name(id_map, snode->id, USER_REAL); snode->from = restore_pointer_by_name(id_map, snode->from, USER_IGNORE); - ntree = nodetree_from_id(snode->id); - if (ntree) - snode->nodetree = ntree; - else - snode->nodetree = restore_pointer_by_name(id_map, (ID*)snode->nodetree, USER_REAL); + if (snode->id) { + ntree = ntreeFromID(snode->id); + snode->nodetree = ntree ? ntree : + restore_pointer_by_name(id_map, (ID *)snode->nodetree, USER_REAL); + } for (path = snode->treepath.first; path; path = path->next) { if (path == snode->treepath.first) { diff --git a/source/blender/blenloader/intern/readfile.h b/source/blender/blenloader/intern/readfile.h index b054cd0031d..7719aaa2b0d 100644 --- a/source/blender/blenloader/intern/readfile.h +++ b/source/blender/blenloader/intern/readfile.h @@ -75,7 +75,7 @@ typedef struct FileData { // general reading variables struct SDNA *filesdna; const struct SDNA *memsdna; - char *compflags; /* array of eSDNA_StructCompare */ + const char *compflags; /* array of eSDNA_StructCompare */ int fileversion; int id_name_offs; /* used to retrieve ID names from (bhead+1) */ diff --git a/source/blender/blenloader/intern/versioning_270.c b/source/blender/blenloader/intern/versioning_270.c index b7b6ace3c1a..a254a854c66 100644 --- a/source/blender/blenloader/intern/versioning_270.c +++ b/source/blender/blenloader/intern/versioning_270.c @@ -1194,8 +1194,8 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) if (camera->stereo.pole_merge_angle_from == 0.0f && camera->stereo.pole_merge_angle_to == 0.0f) { - camera->stereo.pole_merge_angle_from = DEG2RAD(60.0f); - camera->stereo.pole_merge_angle_to = DEG2RAD(75.0f); + camera->stereo.pole_merge_angle_from = DEG2RADF(60.0f); + camera->stereo.pole_merge_angle_to = DEG2RADF(75.0f); } } @@ -1212,5 +1212,24 @@ void blo_do_versions_270(FileData *fd, Library *UNUSED(lib), Main *main) } } } + + if (!DNA_struct_elem_find(fd->filesdna, "BooleanModifierData", "float", "double_threshold")) { + Object *ob; + for (ob = main->object.first; ob; ob = ob->id.next) { + ModifierData *md; + for (md = ob->modifiers.first; md; md = md->next) { + if (md->type == eModifierType_Boolean) { + BooleanModifierData *bmd = (BooleanModifierData *)md; + bmd->double_threshold = 1e-6f; + } + } + } + } + + for (Brush *br = main->brush.first; br; br = br->id.next) { + if (br->sculpt_tool == SCULPT_TOOL_FLATTEN) { + br->flag |= BRUSH_ACCUMULATE; + } + } } } diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c index ad7a3c5b9c4..0ed7a397e0b 100644 --- a/source/blender/blenloader/intern/versioning_defaults.c +++ b/source/blender/blenloader/intern/versioning_defaults.c @@ -256,6 +256,11 @@ void BLO_update_defaults_startup_blend(Main *bmain) if (br) { br->alpha = 1.0f; } + + br = (Brush *)BKE_libblock_find_name_ex(bmain, ID_BR, "Flatten/Contrast"); + if (br) { + br->flag |= BRUSH_ACCUMULATE; + } } } diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index d949dcf48c7..903cae48858 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2275,7 +2275,7 @@ static void write_meshes(WriteData *wd, ListBase *idbase) mesh->edit_btmesh = NULL; /* now fill in polys to mfaces */ - /* XXX This breaks writing desing, by using temp allocated memory, which will likely generate + /* XXX This breaks writing design, by using temp allocated memory, which will likely generate * duplicates in stored 'old' addresses. * This is very bad, but do not see easy way to avoid this, aside from generating those data * outside of save process itself. diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index 13b6a3c13c5..c500d7b9ec2 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -48,31 +48,6 @@ #include "intern/bmesh_private.h" /** - * \brief TEST EDGE SIDE and POINT IN TRIANGLE - * - * Point in triangle tests stolen from scanfill.c. - * Used for tessellator - */ - -static bool testedgesidef(const float v1[2], const float v2[2], const float v3[2]) -{ - /* is v3 to the right of v1 - v2 ? With exception: v3 == v1 || v3 == v2 */ - double inp; - - //inp = (v2[cox] - v1[cox]) * (v1[coy] - v3[coy]) + (v1[coy] - v2[coy]) * (v1[cox] - v3[cox]); - inp = (v2[0] - v1[0]) * (v1[1] - v3[1]) + (v1[1] - v2[1]) * (v1[0] - v3[0]); - - if (inp < 0.0) { - return false; - } - else if (inp == 0) { - if (v1[0] == v3[0] && v1[1] == v3[1]) return false; - if (v2[0] == v3[0] && v2[1] == v3[1]) return false; - } - return true; -} - -/** * \brief COMPUTE POLY NORMAL (BMFace) * * Same as #normal_poly_v3 but operates directly on a bmesh face. @@ -603,29 +578,6 @@ void BM_face_calc_center_mean_weighted(const BMFace *f, float r_cent[3]) } /** - * \brief BM LEGAL EDGES - * - * takes in a face and a list of edges, and sets to NULL any edge in - * the list that bridges a concave region of the face or intersects - * any of the faces's edges. - */ -static void scale_edge_v2f(float v1[2], float v2[2], const float fac) -{ - float mid[2]; - - mid_v2_v2v2(mid, v1, v2); - - sub_v2_v2v2(v1, v1, mid); - sub_v2_v2v2(v2, v2, mid); - - mul_v2_fl(v1, fac); - mul_v2_fl(v2, fac); - - add_v2_v2v2(v1, v1, mid); - add_v2_v2v2(v2, v2, mid); -} - -/** * \brief POLY ROTATE PLANE * * Rotates a polygon so that it's @@ -910,67 +862,6 @@ void BM_face_normal_flip(BMesh *bm, BMFace *f) BM_face_normal_flip_ex(bm, f, cd_loop_mdisp_offset, true); } -/* detects if two line segments cross each other (intersects). - * note, there could be more winding cases then there needs to be. */ -static bool line_crosses_v2f(const float v1[2], const float v2[2], const float v3[2], const float v4[2]) -{ - -#define GETMIN2_AXIS(a, b, ma, mb, axis) \ - { \ - ma[axis] = min_ff(a[axis], b[axis]); \ - mb[axis] = max_ff(a[axis], b[axis]); \ - } (void)0 - -#define GETMIN2(a, b, ma, mb) \ - { \ - GETMIN2_AXIS(a, b, ma, mb, 0); \ - GETMIN2_AXIS(a, b, ma, mb, 1); \ - } (void)0 - -#define EPS (FLT_EPSILON * 15) - - int w1, w2, w3, w4, w5 /*, re */; - float mv1[2], mv2[2], mv3[2], mv4[2]; - - /* now test winding */ - w1 = testedgesidef(v1, v3, v2); - w2 = testedgesidef(v2, v4, v1); - w3 = !testedgesidef(v1, v2, v3); - w4 = testedgesidef(v3, v2, v4); - w5 = !testedgesidef(v3, v1, v4); - - if (w1 == w2 && w2 == w3 && w3 == w4 && w4 == w5) { - return true; - } - - GETMIN2(v1, v2, mv1, mv2); - GETMIN2(v3, v4, mv3, mv4); - - /* do an interval test on the x and y axes */ - /* first do x axis */ - if (fabsf(v1[1] - v2[1]) < EPS && - fabsf(v3[1] - v4[1]) < EPS && - fabsf(v1[1] - v3[1]) < EPS) - { - return (mv4[0] >= mv1[0] && mv3[0] <= mv2[0]); - } - - /* now do y axis */ - if (fabsf(v1[0] - v2[0]) < EPS && - fabsf(v3[0] - v4[0]) < EPS && - fabsf(v1[0] - v3[0]) < EPS) - { - return (mv4[1] >= mv1[1] && mv3[1] <= mv2[1]); - } - - return false; - -#undef GETMIN2_AXIS -#undef GETMIN2 -#undef EPS - -} - /** * BM POINT IN FACE * @@ -1268,121 +1159,103 @@ void BM_face_triangulate( */ void BM_face_splits_check_legal(BMesh *bm, BMFace *f, BMLoop *(*loops)[2], int len) { - const int len2 = len * 2; - BMLoop *l; - float v1[2], v2[2], v3[2], mid[2], *p1, *p2, *p3, *p4; float out[2] = {-FLT_MAX, -FLT_MAX}; + float center[2] = {0.0f, 0.0f}; float axis_mat[3][3]; float (*projverts)[2] = BLI_array_alloca(projverts, f->len); - float (*edgeverts)[2] = BLI_array_alloca(edgeverts, len2); - float fac1 = 1.0000001f, fac2 = 0.9f; //9999f; //0.999f; - int i, j, a = 0, clen; + const float *(*edgeverts)[2] = BLI_array_alloca(edgeverts, len); + BMLoop *l; + int i, i_prev, j; BLI_assert(BM_face_is_normal_valid(f)); axis_dominant_v3_to_m3(axis_mat, f->no); for (i = 0, l = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l = l->next) { - BM_elem_index_set(l, i); /* set_dirty */ mul_v2_m3v3(projverts[i], axis_mat, l->v->co); + add_v2_v2(center, projverts[i]); } - bm->elem_index_dirty |= BM_LOOP; /* first test for completely convex face */ if (is_poly_convex_v2((const float (*)[2])projverts, f->len)) { return; } + mul_v2_fl(center, 1.0f / f->len); + for (i = 0, l = BM_FACE_FIRST_LOOP(f); i < f->len; i++, l = l->next) { + BM_elem_index_set(l, i); /* set_dirty */ + + /* center the projection for maximum accuracy */ + sub_v2_v2(projverts[i], center); + out[0] = max_ff(out[0], projverts[i][0]); out[1] = max_ff(out[1], projverts[i][1]); } + bm->elem_index_dirty |= BM_LOOP; /* ensure we are well outside the face bounds (value is arbitrary) */ add_v2_fl(out, 1.0f); for (i = 0; i < len; i++) { - copy_v2_v2(edgeverts[a + 0], projverts[BM_elem_index_get(loops[i][0])]); - copy_v2_v2(edgeverts[a + 1], projverts[BM_elem_index_get(loops[i][1])]); - scale_edge_v2f(edgeverts[a + 0], edgeverts[a + 1], fac2); - a += 2; + edgeverts[i][0] = projverts[BM_elem_index_get(loops[i][0])]; + edgeverts[i][1] = projverts[BM_elem_index_get(loops[i][1])]; } /* do convexity test */ for (i = 0; i < len; i++) { - copy_v2_v2(v2, edgeverts[i * 2 + 0]); - copy_v2_v2(v3, edgeverts[i * 2 + 1]); - - mid_v2_v2v2(mid, v2, v3); + float mid[2]; + mid_v2_v2v2(mid, edgeverts[i][0], edgeverts[i][1]); - clen = 0; - for (j = 0; j < f->len; j++) { - p1 = projverts[j]; - p2 = projverts[(j + 1) % f->len]; - -#if 0 - copy_v2_v2(v1, p1); - copy_v2_v2(v2, p2); - - scale_edge_v2f(v1, v2, fac1); - if (line_crosses_v2f(v1, v2, mid, out)) { - clen++; + int isect = 0; + int j_prev; + for (j = 0, j_prev = f->len - 1; j < f->len; j_prev = j++) { + const float *f_edge[2] = {projverts[j_prev], projverts[j]}; + if (isect_seg_seg_v2(UNPACK2(f_edge), mid, out) == ISECT_LINE_LINE_CROSS) { + isect++; } -#else - if (line_crosses_v2f(p1, p2, mid, out)) { - clen++; - } -#endif } - if (clen % 2 == 0) { + if (isect % 2 == 0) { loops[i][0] = NULL; } } - /* do line crossing tests */ - for (i = 0; i < f->len; i++) { - p1 = projverts[i]; - p2 = projverts[(i + 1) % f->len]; - - copy_v2_v2(v1, p1); - copy_v2_v2(v2, p2); - - scale_edge_v2f(v1, v2, fac1); +#define EDGE_SHARE_VERT(e1, e2) \ + ((ELEM((e1)[0], (e2)[0], (e2)[1])) || \ + (ELEM((e1)[1], (e2)[0], (e2)[1]))) + /* do line crossing tests */ + for (i = 0, i_prev = f->len - 1; i < f->len; i_prev = i++) { + const float *f_edge[2] = {projverts[i_prev], projverts[i]}; for (j = 0; j < len; j++) { - if (!loops[j][0]) { - continue; - } - - p3 = edgeverts[j * 2]; - p4 = edgeverts[j * 2 + 1]; - - if (line_crosses_v2f(v1, v2, p3, p4)) { - loops[j][0] = NULL; + if ((loops[j][0] != NULL) && + !EDGE_SHARE_VERT(f_edge, edgeverts[j])) + { + if (isect_seg_seg_v2(UNPACK2(f_edge), UNPACK2(edgeverts[j])) == ISECT_LINE_LINE_CROSS) { + loops[j][0] = NULL; + } } } } + /* self intersect tests */ for (i = 0; i < len; i++) { - for (j = 0; j < len; j++) { - if (j != i && loops[i][0] && loops[j][0]) { - p1 = edgeverts[i * 2]; - p2 = edgeverts[i * 2 + 1]; - p3 = edgeverts[j * 2]; - p4 = edgeverts[j * 2 + 1]; - - copy_v2_v2(v1, p1); - copy_v2_v2(v2, p2); - - scale_edge_v2f(v1, v2, fac1); - - if (line_crosses_v2f(v1, v2, p3, p4)) { - loops[i][0] = NULL; + if (loops[i][0]) { + for (j = i + 1; j < len; j++) { + if ((loops[j][0] != NULL) && + !EDGE_SHARE_VERT(edgeverts[i], edgeverts[j])) + { + if (isect_seg_seg_v2(UNPACK2(edgeverts[i]), UNPACK2(edgeverts[j])) == ISECT_LINE_LINE_CROSS) { + loops[i][0] = NULL; + break; + } } } } } + +#undef EDGE_SHARE_VERT } /** diff --git a/source/blender/bmesh/operators/bmo_connect_nonplanar.c b/source/blender/bmesh/operators/bmo_connect_nonplanar.c index 9b3e1d38feb..b8acc9d09b8 100644 --- a/source/blender/bmesh/operators/bmo_connect_nonplanar.c +++ b/source/blender/bmesh/operators/bmo_connect_nonplanar.c @@ -63,7 +63,7 @@ static float bm_face_subset_calc_planar(BMLoop *l_first, BMLoop *l_last, const f return delta_z; } -static bool bm_face_split_find(BMesh *bm, BMFace *f, BMLoop *l_pair[2], float *r_angle) +static bool bm_face_split_find(BMesh *bm, BMFace *f, BMLoop *l_pair[2], float *r_angle_cos) { BMLoop *l_iter, *l_first; BMLoop **l_arr = BLI_array_alloca(l_arr, f->len); @@ -73,7 +73,7 @@ static bool bm_face_split_find(BMesh *bm, BMFace *f, BMLoop *l_pair[2], float *r /* angle finding */ float err_best = FLT_MAX; - float angle_best = FLT_MAX; + float angle_best_cos = -FLT_MAX; l_iter = l_first = BM_FACE_FIRST_LOOP(f); i_a = 0; @@ -108,7 +108,7 @@ static bool bm_face_split_find(BMesh *bm, BMFace *f, BMLoop *l_pair[2], float *r l_pair[0] = l_a; l_pair[1] = l_b; - angle_best = angle_normalized_v3v3(no_a, no_b); + angle_best_cos = dot_v3v3(no_a, no_b); found = true; } } @@ -117,17 +117,17 @@ static bool bm_face_split_find(BMesh *bm, BMFace *f, BMLoop *l_pair[2], float *r } } - *r_angle = angle_best; + *r_angle_cos = angle_best_cos; return found; } -static bool bm_face_split_by_angle(BMesh *bm, BMFace *f, BMFace *r_f_pair[2], const float angle_limit) +static bool bm_face_split_by_angle(BMesh *bm, BMFace *f, BMFace *r_f_pair[2], const float angle_limit_cos) { BMLoop *l_pair[2]; - float angle; + float angle_cos; - if (bm_face_split_find(bm, f, l_pair, &angle) && (angle > angle_limit)) { + if (bm_face_split_find(bm, f, l_pair, &angle_cos) && (angle_cos < angle_limit_cos)) { BMFace *f_new; BMLoop *l_new; @@ -154,7 +154,7 @@ void bmo_connect_verts_nonplanar_exec(BMesh *bm, BMOperator *op) bool changed = false; BLI_LINKSTACK_DECLARE(fstack, BMFace *); - const float angle_limit = BMO_slot_float_get(op->slots_in, "angle_limit"); + const float angle_limit_cos = cosf(BMO_slot_float_get(op->slots_in, "angle_limit")); BLI_LINKSTACK_INIT(fstack); @@ -166,7 +166,7 @@ void bmo_connect_verts_nonplanar_exec(BMesh *bm, BMOperator *op) while ((f = BLI_LINKSTACK_POP(fstack))) { BMFace *f_pair[2]; - if (bm_face_split_by_angle(bm, f, f_pair, angle_limit)) { + if (bm_face_split_by_angle(bm, f, f_pair, angle_limit_cos)) { int j; for (j = 0; j < 2; j++) { BM_face_normal_update(f_pair[j]); diff --git a/source/blender/bmesh/operators/bmo_connect_pair.c b/source/blender/bmesh/operators/bmo_connect_pair.c index 3eb6fe0cb97..05322a570a7 100644 --- a/source/blender/bmesh/operators/bmo_connect_pair.c +++ b/source/blender/bmesh/operators/bmo_connect_pair.c @@ -124,8 +124,8 @@ typedef struct PathLinkState { } PathLinkState; /** - \name Min Dist Dir Util - + * \name Min Dist Dir Util + * * Simply getting the closest intersecting vert/edge is _not_ good enough. see T43792 * we need to get the closest in both directions since the absolute closest may be a dead-end. * diff --git a/source/blender/bmesh/operators/bmo_normals.c b/source/blender/bmesh/operators/bmo_normals.c index f0738303d5c..73dbee25be3 100644 --- a/source/blender/bmesh/operators/bmo_normals.c +++ b/source/blender/bmesh/operators/bmo_normals.c @@ -86,7 +86,7 @@ static int recalc_face_normals_find_index(BMesh *bm, BMFace **faces, const int f int f_start_index; int i; - /* Search for the best loop. Members are comapred in-order defined here. */ + /* Search for the best loop. Members are compared in-order defined here. */ struct { /* Squared distance from the center to the loops vertex 'l->v'. * The normalized direction between the center and this vertex is also used for the dot-products below. */ diff --git a/source/blender/bmesh/operators/bmo_subdivide_edgering.c b/source/blender/bmesh/operators/bmo_subdivide_edgering.c index b4a77bf1a38..ce031e1c230 100644 --- a/source/blender/bmesh/operators/bmo_subdivide_edgering.c +++ b/source/blender/bmesh/operators/bmo_subdivide_edgering.c @@ -1099,7 +1099,8 @@ void bmo_subdivide_edgering_exec(BMesh *bm, BMOperator *op) BMFace *f; BM_ITER_ELEM (f, &fiter, e, BM_FACES_OF_EDGE) { - if (!BMO_face_flag_test(bm, f, FACE_OUT)) { + /* could support ngons, other areas would need updating too, see T48926. */ + if ((f->len <= 4) && !BMO_face_flag_test(bm, f, FACE_OUT)) { BMIter liter; BMLoop *l; bool ok = false; diff --git a/source/blender/bmesh/tools/bmesh_bevel.c b/source/blender/bmesh/tools/bmesh_bevel.c index 4dc1c8a9f00..b647f5a667d 100644 --- a/source/blender/bmesh/tools/bmesh_bevel.c +++ b/source/blender/bmesh/tools/bmesh_bevel.c @@ -1648,9 +1648,11 @@ static void build_boundary_vertex_only(BevelParams *bp, BevVert *bv, bool constr } } -/* Special case of build_boundary when a single edge is beveled. - * The 'width adjust' part of build_boundary has been done already, and - * efirst is the first beveled edge at vertex bv. */ +/** + * Special case of build_boundary when a single edge is beveled. + * The 'width adjust' part of build_boundary has been done already, + * and \a efirst is the first beveled edge at vertex \a bv. +*/ static void build_boundary_terminal_edge(BevelParams *bp, BevVert *bv, EdgeHalf *efirst, bool construct) { MemArena *mem_arena = bp->mem_arena; diff --git a/source/blender/collada/DocumentImporter.cpp b/source/blender/collada/DocumentImporter.cpp index f06f299d381..226f319cefd 100644 --- a/source/blender/collada/DocumentImporter.cpp +++ b/source/blender/collada/DocumentImporter.cpp @@ -904,6 +904,7 @@ void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Materia i++; } } + // EMISSION // color if (ef->getEmission().isColor()) { @@ -919,8 +920,22 @@ void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Materia i++; } } - - if (ef->getOpacity().isTexture()) { + + // TRANSPARENT + // color + if (ef->getOpacity().isColor()) { + col = ef->getTransparent().getColor(); + float alpha = ef->getTransparency().getFloatValue(); + if (col.isValid()) { + alpha *= col.getAlpha(); // Assuming A_ONE opaque mode + } + if (col.isValid() || alpha < 1.0) { + ma->alpha = alpha; + ma->mode |= MA_ZTRANSP | MA_TRANSP; + } + } + // texture + else if (ef->getOpacity().isTexture()) { COLLADAFW::Texture ctex = ef->getOpacity().getTexture(); mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map); if (mtex != NULL) { @@ -930,22 +945,7 @@ void DocumentImporter::write_profile_COMMON(COLLADAFW::EffectCommon *ef, Materia ma->mode |= MA_ZTRANSP | MA_TRANSP; } } - // TRANSPARENT - // color -#if 0 - if (ef->getOpacity().isColor()) { - // XXX don't know what to do here - } - // texture - else if (ef->getOpacity().isTexture()) { - ctex = ef->getOpacity().getTexture(); - if (mtex != NULL) mtex->mapto &= MAP_ALPHA; - else { - mtex = create_texture(ef, ctex, ma, i, texindex_texarray_map); - if (mtex != NULL) mtex->mapto = MAP_ALPHA; - } - } -#endif + material_texture_mapping_map[ma] = texindex_texarray_map; } diff --git a/source/blender/collada/EffectExporter.cpp b/source/blender/collada/EffectExporter.cpp index 13dc1eda580..76b51148509 100644 --- a/source/blender/collada/EffectExporter.cpp +++ b/source/blender/collada/EffectExporter.cpp @@ -30,6 +30,7 @@ #include <set> #include "COLLADASWEffectProfile.h" +#include "COLLADAFWColorOrTexture.h" #include "EffectExporter.h" #include "DocumentExporter.h" @@ -217,9 +218,9 @@ void EffectsExporter::operator()(Material *ma, Object *ob) // transparency if (ma->mode & MA_TRANSP) { // Tod: because we are in A_ONE mode transparency is calculated like this: - ep.setTransparency(ma->alpha, false, "transparency"); - // cot = getcol(1.0f, 1.0f, 1.0f, 1.0f); - // ep.setTransparent(cot); + cot = getcol(1.0f, 1.0f, 1.0f, ma->alpha); + ep.setTransparent(cot); + ep.setOpaque(COLLADASW::EffectProfile::A_ONE); } // emission diff --git a/source/blender/collada/ErrorHandler.cpp b/source/blender/collada/ErrorHandler.cpp index b271604f839..98aa85f8a9b 100644 --- a/source/blender/collada/ErrorHandler.cpp +++ b/source/blender/collada/ErrorHandler.cpp @@ -79,7 +79,7 @@ bool ErrorHandler::handleError(const COLLADASaxFWL::IError *error) COLLADASaxFWL::SaxFWLError *saxFWLError = (COLLADASaxFWL::SaxFWLError *) error; /* * Accept non critical errors as warnings (i.e. texture not found) - * This makes the importer more gracefull, so it now imports what makes sense. + * This makes the importer more graceful, so it now imports what makes sense. */ if (saxFWLError->getSeverity() == COLLADASaxFWL::IError::SEVERITY_ERROR_NONCRITICAL) { isError = false; diff --git a/source/blender/collada/collada_utils.cpp b/source/blender/collada/collada_utils.cpp index 649c86edd25..abe5130b9c1 100644 --- a/source/blender/collada/collada_utils.cpp +++ b/source/blender/collada/collada_utils.cpp @@ -539,8 +539,8 @@ void BoneExtended::set_bone_layers(std::string layerString, std::vector<std::str } /* If numeric layers and labeled layers are used in parallel (unlikely), - we get a potential mixup. Just leave as is for now. - */ + * we get a potential mixup. Just leave as is for now. + */ this->bone_layers = bc_set_layer(this->bone_layers, pos); } diff --git a/source/blender/compositor/operations/COM_MaskOperation.cpp b/source/blender/compositor/operations/COM_MaskOperation.cpp index d6e5fdf86bb..caafdfe8f0c 100644 --- a/source/blender/compositor/operations/COM_MaskOperation.cpp +++ b/source/blender/compositor/operations/COM_MaskOperation.cpp @@ -1,5 +1,4 @@ /* - * Copyright 2012, Blender Foundation. * * This program is free software; you can redistribute it and/or diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 2d67ef1d584..a397b48e19c 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -296,15 +296,16 @@ void DepsgraphNodeBuilder::build_scene(Main *bmain, Scene *scene) for (Base *base = (Base *)scene->base.first; base; base = base->next) { Object *ob = base->object; + /* object itself */ + build_object(scene, base, ob); + /* object that this is a proxy for */ // XXX: the way that proxies work needs to be completely reviewed! if (ob->proxy) { ob->proxy->proxy_from = ob; + build_object(scene, base, ob->proxy); } - /* object itself */ - build_object(scene, base, ob); - /* Object dupligroup. */ if (ob->dup_group) { build_group(scene, base, ob->dup_group); @@ -397,12 +398,12 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob) { if (ob->id.tag & LIB_TAG_DOIT) { IDDepsNode *id_node = m_graph->find_id_node(&ob->id); - id_node->layers = base->lay; + id_node->layers |= base->lay; return; } IDDepsNode *id_node = add_id_node(&ob->id); - id_node->layers = base->lay; + id_node->layers |= base->lay; ob->customdata_mask = 0; /* standard components */ @@ -441,7 +442,7 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob) } case OB_ARMATURE: /* Pose */ - if (ob->id.lib != NULL && ob->proxy_from != NULL) { + if (ID_IS_LINKED_DATABLOCK(ob) && ob->proxy_from != NULL) { build_proxy_rig(ob); } else { @@ -485,12 +486,6 @@ void DepsgraphNodeBuilder::build_object(Scene *scene, Base *base, Object *ob) if (ob->gpd) { build_gpencil(ob->gpd); } - - if (ob->proxy != NULL) { - add_operation_node(&ob->id, DEPSNODE_TYPE_PROXY, DEPSOP_TYPE_POST, - function_bind(BKE_object_eval_proxy_backlink, _1, ob), - DEG_OPCODE_PLACEHOLDER, "Parameters Eval"); - } } void DepsgraphNodeBuilder::build_object_transform(Scene *scene, Object *ob) diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index 34c661b21f3..42b8260c05a 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -266,18 +266,12 @@ void DepsgraphRelationBuilder::build_scene(Main *bmain, Scene *scene) for (Base *base = (Base *)scene->base.first; base; base = base->next) { Object *ob = base->object; - /* Object that this is a proxy for. - * Just makes sure backlink is correct. - */ - if (ob->proxy) { - ob->proxy->proxy_from = ob; - } - /* object itself */ build_object(bmain, scene, ob); /* object that this is a proxy for */ if (ob->proxy) { + ob->proxy->proxy_from = ob; build_object(bmain, scene, ob->proxy); /* TODO(sergey): This is an inverted relation, matches old depsgraph * behavior and need to be investigated if it still need to be inverted. @@ -441,7 +435,7 @@ void DepsgraphRelationBuilder::build_object(Main *bmain, Scene *scene, Object *o } case OB_ARMATURE: /* Pose */ - if (ob->id.lib != NULL && ob->proxy_from != NULL) { + if (ID_IS_LINKED_DATABLOCK(ob) && ob->proxy_from != NULL) { build_proxy_rig(ob); } else { @@ -926,6 +920,12 @@ void DepsgraphRelationBuilder::build_driver(ID *id, FCurve *fcu) } } else { + if (dtar->id == id) { + /* Ignore input dependency if we're driving properties of the same ID, + * otherwise we'll be ending up in a cyclic dependency here. + */ + continue; + } /* resolve path to get node */ RNAPathKey target_key(dtar->id, dtar->rna_path ? dtar->rna_path : ""); add_relation(target_key, driver_key, DEPSREL_TYPE_DRIVER_TARGET, "[RNA Target -> Driver]"); diff --git a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc index 9ba0b61a4f1..f9e1504b3ce 100644 --- a/source/blender/depsgraph/intern/eval/deg_eval_flush.cc +++ b/source/blender/depsgraph/intern/eval/deg_eval_flush.cc @@ -85,9 +85,6 @@ static void flush_init_func(void *data_v, int i) id_node->done = 0; comp_node->done = 0; node->scheduled = false; - if (comp_node->type == DEPSNODE_TYPE_PROXY) { - node->flag |= DEPSOP_FLAG_NEEDS_UPDATE; - } } /* Flush updates from tagged nodes outwards until all affected nodes diff --git a/source/blender/depsgraph/intern/nodes/deg_node.cc b/source/blender/depsgraph/intern/nodes/deg_node.cc index 12d5ee00a63..db807d22b89 100644 --- a/source/blender/depsgraph/intern/nodes/deg_node.cc +++ b/source/blender/depsgraph/intern/nodes/deg_node.cc @@ -181,6 +181,11 @@ void IDDepsNode::init(const ID *id, const string &UNUSED(subdata)) this->layers = (1 << 20) - 1; this->eval_flags = 0; + /* For object we initialize layers to layer from base. */ + if (GS(id) == ID_OB) { + this->layers = 0; + } + components = BLI_ghash_new(id_deps_node_hash_key, id_deps_node_hash_key_cmp, "Depsgraph id components hash"); diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c index 6306926e0b2..6979a324b69 100644 --- a/source/blender/editors/armature/armature_utils.c +++ b/source/blender/editors/armature/armature_utils.c @@ -424,7 +424,9 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone for (curBone = bones->first; curBone; curBone = curBone->next) { eBone = MEM_callocN(sizeof(EditBone), "make_editbone"); - /* Copy relevant data from bone to eBone */ + /* Copy relevant data from bone to eBone + * Keep selection logic in sync with ED_armature_sync_selection. + */ eBone->parent = parent; BLI_strncpy(eBone->name, curBone->name, sizeof(eBone->name)); eBone->flag = curBone->flag; @@ -435,11 +437,11 @@ EditBone *make_boneList(ListBase *edbo, ListBase *bones, EditBone *parent, Bone eBone->flag |= BONE_TIPSEL; if (eBone->parent && (eBone->flag & BONE_CONNECTED)) { eBone->parent->flag |= BONE_TIPSEL; - eBone->flag &= ~BONE_ROOTSEL; /* this is ignored when there is a connected parent, so unset it */ - } - else { - eBone->flag |= BONE_ROOTSEL; } + + /* For connected bones, take care when changing the selection when we have a connected parent, + * this flag is a copy of '(eBone->parent->flag & BONE_TIPSEL)'. */ + eBone->flag |= BONE_ROOTSEL; } else { /* if the bone is not selected, but connected to its parent diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 72b48a32477..e40dde24ce2 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -5843,7 +5843,7 @@ static int curve_dissolve_exec(bContext *C, wmOperator *UNUSED(op)) normalize_v3(tan_r); curve_fit_cubic_to_points_single_fl( - points, points_len, dims, FLT_EPSILON, + points, points_len, NULL, dims, FLT_EPSILON, tan_l, tan_r, bezt_prev->vec[2], bezt_next->vec[0], &error_sq_dummy); diff --git a/source/blender/editors/curve/editcurve_paint.c b/source/blender/editors/curve/editcurve_paint.c index 38018541929..4d0a2fa53cd 100644 --- a/source/blender/editors/curve/editcurve_paint.c +++ b/source/blender/editors/curve/editcurve_paint.c @@ -55,6 +55,8 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "RNA_enum_types.h" + #define USE_SPLINE_FIT #ifdef USE_SPLINE_FIT @@ -65,6 +67,9 @@ #define STROKE_SAMPLE_DIST_MIN_PX 3 #define STROKE_SAMPLE_DIST_MAX_PX 6 +/* Distance between start/end points to consider cyclic */ +#define STROKE_CYCLIC_DIST_PX 8 + /* -------------------------------------------------------------------- */ @@ -730,6 +735,11 @@ static void curve_draw_exec_precalc(wmOperator *op) const CurvePaintSettings *cps = &cdd->vc.scene->toolsettings->curve_paint_settings; PropertyRNA *prop; + prop = RNA_struct_find_property(op->ptr, "fit_method"); + if (!RNA_property_is_set(op->ptr, prop)) { + RNA_property_enum_set(op->ptr, prop, cps->fit_method); + } + prop = RNA_struct_find_property(op->ptr, "corner_angle"); if (!RNA_property_is_set(op->ptr, prop)) { const float corner_angle = (cps->flag & CURVE_PAINT_FLAG_CORNERS_DETECT) ? cps->corner_angle : (float)M_PI; @@ -759,6 +769,32 @@ static void curve_draw_exec_precalc(wmOperator *op) RNA_property_float_set(op->ptr, prop, error_threshold); } + prop = RNA_struct_find_property(op->ptr, "use_cyclic"); + if (!RNA_property_is_set(op->ptr, prop)) { + bool use_cyclic = false; + + if (BLI_mempool_count(cdd->stroke_elem_pool) > 2) { + BLI_mempool_iter iter; + const struct StrokeElem *selem, *selem_first, *selem_last; + + BLI_mempool_iternew(cdd->stroke_elem_pool, &iter); + selem_first = BLI_mempool_iterstep(&iter); + for (selem = BLI_mempool_iterstep(&iter); selem; selem = BLI_mempool_iterstep(&iter)) { + selem_last = selem; + } + + if (len_squared_v2v2( + selem_first->mval, + selem_last->mval) <= SQUARE(STROKE_CYCLIC_DIST_PX * U.pixelsize)) + { + use_cyclic = true; + } + } + + RNA_property_boolean_set(op->ptr, prop, use_cyclic); + } + + if ((cps->radius_taper_start != 0.0f) || (cps->radius_taper_end != 0.0f)) { @@ -868,8 +904,10 @@ static int curve_draw_exec(bContext *C, wmOperator *op) unsigned int cubic_spline_len = 0; /* error in object local space */ + const int fit_method = RNA_enum_get(op->ptr, "fit_method"); const float error_threshold = RNA_float_get(op->ptr, "error_threshold"); const float corner_angle = RNA_float_get(op->ptr, "corner_angle"); + const bool use_cyclic = RNA_boolean_get(op->ptr, "use_cyclic"); { BLI_mempool_iter iter; @@ -894,14 +932,14 @@ static int curve_draw_exec(bContext *C, wmOperator *op) unsigned int *corners = NULL; unsigned int corners_len = 0; - if (corner_angle < (float)M_PI) { + if ((fit_method == CURVE_PAINT_FIT_METHOD_SPLIT) && (corner_angle < (float)M_PI)) { /* this could be configurable... */ const float corner_radius_min = error_threshold / 8; const float corner_radius_max = error_threshold * 2; const unsigned int samples_max = 16; curve_fit_corners_detect_fl( - (const float *)coords, stroke_len, dims, + coords, stroke_len, dims, corner_radius_min, corner_radius_max, samples_max, corner_angle, &corners, &corners_len); @@ -909,13 +947,29 @@ static int curve_draw_exec(bContext *C, wmOperator *op) unsigned int *corners_index = NULL; unsigned int corners_index_len = 0; + unsigned int calc_flag = CURVE_FIT_CALC_HIGH_QUALIY; - const int result = curve_fit_cubic_to_points_fl( - coords, stroke_len, dims, error_threshold, CURVE_FIT_CALC_HIGH_QUALIY, - corners, corners_len, - &cubic_spline, &cubic_spline_len, - NULL, - &corners_index, &corners_index_len); + if ((stroke_len > 2) && use_cyclic) { + calc_flag |= CURVE_FIT_CALC_CYCLIC; + } + + int result; + if (fit_method == CURVE_PAINT_FIT_METHOD_REFIT) { + result = curve_fit_cubic_to_points_refit_fl( + coords, stroke_len, dims, error_threshold, calc_flag, + NULL, 0, corner_angle, + &cubic_spline, &cubic_spline_len, + NULL, + &corners_index, &corners_index_len); + } + else { + result = curve_fit_cubic_to_points_fl( + coords, stroke_len, dims, error_threshold, calc_flag, + corners, corners_len, + &cubic_spline, &cubic_spline_len, + NULL, + &corners_index, &corners_index_len); + } MEM_freeN(coords); if (corners) { @@ -950,11 +1004,24 @@ static int curve_draw_exec(bContext *C, wmOperator *op) if (corners_index) { /* ignore the first and last */ - for (unsigned int i = 1; i < corners_index_len - 1; i++) { + unsigned int i_start = 0, i_end = corners_index_len; + + if ((corners_index_len >= 2) && + (calc_flag & CURVE_FIT_CALC_CYCLIC) == 0) + { + i_start += 1; + i_end -= 1; + } + + for (unsigned int i = i_start; i < i_end; i++) { bezt = &nu->bezt[corners_index[i]]; bezt->h1 = bezt->h2 = HD_FREE; } } + + if (calc_flag & CURVE_FIT_CALC_CYCLIC) { + nu->flagu |= CU_NURB_CYCLIC; + } } if (corners_index) { @@ -1220,13 +1287,19 @@ void CURVE_OT_draw(wmOperatorType *ot) 0.0001f, 10.0f); RNA_def_property_ui_range(prop, 0.0, 10, 1, 4); + RNA_def_enum(ot->srna, "fit_method", rna_enum_curve_fit_method_items, CURVE_PAINT_FIT_METHOD_REFIT, + "Fit Method", ""); + prop = RNA_def_float_distance( ot->srna, "corner_angle", DEG2RADF(70.0f), 0.0f, M_PI, "Corner Angle", "", 0.0f, M_PI); RNA_def_property_subtype(prop, PROP_ANGLE); - prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", ""); + prop = RNA_def_boolean(ot->srna, "use_cyclic", true, "Cyclic", ""); RNA_def_property_flag(prop, PROP_SKIP_SAVE); + prop = RNA_def_collection_runtime(ot->srna, "stroke", &RNA_OperatorStrokeElement, "Stroke", ""); + RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); + prop = RNA_def_boolean(ot->srna, "wait_for_input", true, "Wait for Input", ""); RNA_def_property_flag(prop, PROP_HIDDEN | PROP_SKIP_SAVE); } diff --git a/source/blender/editors/curve/editcurve_select.c b/source/blender/editors/curve/editcurve_select.c index a29266294b4..cad70443657 100644 --- a/source/blender/editors/curve/editcurve_select.c +++ b/source/blender/editors/curve/editcurve_select.c @@ -294,11 +294,11 @@ static void select_adjacent_cp( if (next < 0) bezt = &nu->bezt[a - 1]; while (a--) { if (a - abs(next) < 0) break; - if ((lastsel == 0) && (bezt->hide == 0) && ((bezt->f2 & SELECT) || (selstatus == DESELECT))) { + if ((lastsel == false) && (bezt->hide == 0) && ((bezt->f2 & SELECT) || (selstatus == DESELECT))) { bezt += next; if (!(bezt->f2 & SELECT) || (selstatus == DESELECT)) { - short sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE); - if ((sel == 1) && (cont == 0)) lastsel = true; + bool sel = select_beztriple(bezt, selstatus, SELECT, VISIBLE); + if (sel && !cont) lastsel = true; } } else { @@ -315,11 +315,11 @@ static void select_adjacent_cp( if (next < 0) bp = &nu->bp[a - 1]; while (a--) { if (a - abs(next) < 0) break; - if ((lastsel == 0) && (bp->hide == 0) && ((bp->f1 & SELECT) || (selstatus == DESELECT))) { + if ((lastsel == false) && (bp->hide == 0) && ((bp->f1 & SELECT) || (selstatus == DESELECT))) { bp += next; if (!(bp->f1 & SELECT) || (selstatus == DESELECT)) { - short sel = select_bpoint(bp, selstatus, SELECT, VISIBLE); - if ((sel == 1) && (cont == 0)) lastsel = true; + bool sel = select_bpoint(bp, selstatus, SELECT, VISIBLE); + if (sel && !cont) lastsel = true; } } else { @@ -820,7 +820,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op)) BezTriple *bezt; int a; int sel = 0; - short lastsel = false; + bool lastsel = false; if (obedit->type == OB_SURF) { for (nu = editnurb->first; nu; nu = nu->next) { @@ -935,9 +935,8 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op)) a = nu->pntsu * nu->pntsv; bp = nu->bp; while (a--) { - if ((lastsel == 0) && (bp->hide == 0) && (bp->f1 & SELECT)) { - if (lastsel != 0) sel = 1; - else sel = 0; + if ((lastsel == false) && (bp->hide == 0) && (bp->f1 & SELECT)) { + sel = 0; /* first and last are exceptions */ if (a == nu->pntsu * nu->pntsv - 1) { diff --git a/source/blender/editors/curve/editfont.c b/source/blender/editors/curve/editfont.c index 053a7ee5023..b40b51e337f 100644 --- a/source/blender/editors/curve/editfont.c +++ b/source/blender/editors/curve/editfont.c @@ -1695,7 +1695,7 @@ static int font_open_exec(bContext *C, wmOperator *op) if (pprop->prop) { /* when creating new ID blocks, use is already 1, but RNA - * pointer se also increases user, so this compensates it */ + * pointer use also increases user, so this compensates it */ id_us_min(&font->id); RNA_id_pointer_create(&font->id, &idptr); diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h index 81e2558e765..602e203a381 100644 --- a/source/blender/editors/include/ED_keyframing.h +++ b/source/blender/editors/include/ED_keyframing.h @@ -325,18 +325,18 @@ bool ANIM_driver_vars_paste(struct ReportList *reports, struct FCurve *fcu, bool /* Notes: * - All the defines for this (User-Pref settings and Per-Scene settings) * are defined in DNA_userdef_types.h - * - Scene settings take presidence over those for userprefs, with old files + * - Scene settings take precedence over those for userprefs, with old files * inheriting userpref settings for the scene settings * - "On/Off + Mode" are stored per Scene, but "settings" are currently stored * as userprefs */ /* Auto-Keying macros for use by various tools */ -/* check if auto-keyframing is enabled (per scene takes presidence) */ +/* check if auto-keyframing is enabled (per scene takes precedence) */ #define IS_AUTOKEY_ON(scene) ((scene) ? (scene->toolsettings->autokey_mode & AUTOKEY_ON) : (U.autokey_mode & AUTOKEY_ON)) -/* check the mode for auto-keyframing (per scene takes presidence) */ +/* check the mode for auto-keyframing (per scene takes precedence) */ #define IS_AUTOKEY_MODE(scene, mode) ((scene) ? (scene->toolsettings->autokey_mode == AUTOKEY_MODE_##mode) : (U.autokey_mode == AUTOKEY_MODE_##mode)) -/* check if a flag is set for auto-keyframing (per scene takes presidence) */ +/* check if a flag is set for auto-keyframing (per scene takes precedence) */ #define IS_AUTOKEY_FLAG(scene, flag) \ ((scene) ? \ ((scene->toolsettings->autokey_flag & AUTOKEY_FLAG_##flag) || (U.autokey_flag & AUTOKEY_FLAG_##flag)) \ diff --git a/source/blender/editors/include/ED_view3d.h b/source/blender/editors/include/ED_view3d.h index b09284aa759..48c1e2d1996 100644 --- a/source/blender/editors/include/ED_view3d.h +++ b/source/blender/editors/include/ED_view3d.h @@ -208,6 +208,7 @@ eV3DProjStatus ED_view3d_project_float_global(const struct ARegion *ar, const fl eV3DProjStatus ED_view3d_project_float_object(const struct ARegion *ar, const float co[3], float r_co[2], const eV3DProjTest flag); float ED_view3d_calc_zfac(const struct RegionView3D *rv3d, const float co[3], bool *r_flip); +bool ED_view3d_clip_segment(const struct RegionView3D *rv3d, float ray_start[3], float ray_end[3]); bool ED_view3d_win_to_ray( const struct ARegion *ar, const struct View3D *v3d, const float mval[2], float ray_start[3], float ray_normal[3], const bool do_clip); @@ -218,6 +219,7 @@ void ED_view3d_global_to_vector(const struct RegionView3D *rv3d, const float coo void ED_view3d_win_to_3d(const struct ARegion *ar, const float depth_pt[3], const float mval[2], float out[3]); void ED_view3d_win_to_3d_int(const struct ARegion *ar, const float depth_pt[3], const int mval[2], float out[3]); void ED_view3d_win_to_delta(const struct ARegion *ar, const float mval[2], float out[3], const float zfac); +void ED_view3d_win_to_origin(const struct ARegion *ar, const float mval[2], float out[3]); void ED_view3d_win_to_vector(const struct ARegion *ar, const float mval[2], float out[3]); bool ED_view3d_win_to_segment(const struct ARegion *ar, struct View3D *v3d, const float mval[2], float r_ray_start[3], float r_ray_end[3], const bool do_clip); diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index ba7240be5d8..cbe8654ceb6 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -1138,7 +1138,7 @@ static bool ui_but_event_property_operator_string(const bContext *C, uiBut *but, * as new items are added to the menu later on. It also optimises efficiency - * a radial menu is best kept symmetrical, with as large an angle between * items as possible, so that the gestural mouse movements can be fast and inexact. - + * * It starts off with two opposite sides for the first two items * then joined by the one below for the third (this way, even with three items, * the menu seems to still be 'in order' reading left to right). Then the fourth is diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index 72a6a04feec..9ce863dc8f7 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -734,24 +734,50 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), CLAMP(max, rect.ymin, rect.ymax); fdrawline(rect.xmax - 3, min, rect.xmax - 3, max); } + /* RGB (3 channel) */ + else if (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB) { + glBlendFunc(GL_ONE, GL_ONE); + + glEnableClientState(GL_VERTEX_ARRAY); + + glPushMatrix(); + + glTranslatef(rect.xmin, yofs, 0.f); + glScalef(w, h, 0.f); + + glColor3fv( colors_alpha[0] ); + glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1); + glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); + + glColor3fv( colors_alpha[1] ); + glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_2); + glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); - /* RGB / YCC (3 channels) */ + glColor3fv( colors_alpha[2] ); + glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_3); + glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); + + glDisableClientState(GL_VERTEX_ARRAY); + glPopMatrix(); + } + /* PARADE / YCC (3 channels) */ else if (ELEM(scopes->wavefrm_mode, - SCOPES_WAVEFRM_RGB, + SCOPES_WAVEFRM_RGB_PARADE, SCOPES_WAVEFRM_YCC_601, SCOPES_WAVEFRM_YCC_709, - SCOPES_WAVEFRM_YCC_JPEG)) + SCOPES_WAVEFRM_YCC_JPEG + )) { - int rgb = (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB); - + int rgb = (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB_PARADE); + glBlendFunc(GL_ONE, GL_ONE); - + glPushMatrix(); glEnableClientState(GL_VERTEX_ARRAY); - + glTranslatef(rect.xmin, yofs, 0.f); glScalef(w3, h, 0.f); - + glColor3fv((rgb) ? colors_alpha[0] : colorsycc_alpha[0]); glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_1); glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); @@ -760,19 +786,19 @@ void ui_draw_but_WAVEFORM(ARegion *ar, uiBut *but, uiWidgetColors *UNUSED(wcol), glColor3fv((rgb) ? colors_alpha[1] : colorsycc_alpha[1]); glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_2); glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); - + glTranslatef(1.f, 0.f, 0.f); glColor3fv((rgb) ? colors_alpha[2] : colorsycc_alpha[2]); glVertexPointer(2, GL_FLOAT, 0, scopes->waveform_3); glDrawArrays(GL_POINTS, 0, scopes->waveform_tot); - + glDisableClientState(GL_VERTEX_ARRAY); glPopMatrix(); - - - /* min max */ + } + /* min max */ + if (scopes->wavefrm_mode != SCOPES_WAVEFRM_LUMA ) { for (int c = 0; c < 3; c++) { - if (scopes->wavefrm_mode == SCOPES_WAVEFRM_RGB) + if (ELEM(scopes->wavefrm_mode, SCOPES_WAVEFRM_RGB_PARADE, SCOPES_WAVEFRM_RGB)) glColor3f(colors[c][0] * 0.75f, colors[c][1] * 0.75f, colors[c][2] * 0.75f); else glColor3f(colorsycc[c][0] * 0.75f, colorsycc[c][1] * 0.75f, colorsycc[c][2] * 0.75f); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 0a0ecf93d17..11703208b2a 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -1057,7 +1057,9 @@ static void ui_multibut_free(uiHandleButtonData *data, uiBlock *block) } } -static bool ui_multibut_states_tag(uiBut *but_active, uiHandleButtonData *data, const wmEvent *event) +static bool ui_multibut_states_tag( + uiBut *but_active, + uiHandleButtonData *data, const wmEvent *event) { uiBut *but; float seg[2][2]; @@ -1668,7 +1670,9 @@ static bool ui_but_contains_point_px_icon(uiBut *but, ARegion *ar, const wmEvent return BLI_rcti_isect_pt(&rect, x, y); } -static bool ui_but_drag_init(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static bool ui_but_drag_init( + bContext *C, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { /* prevent other WM gestures to start while we try to drag */ WM_gestures_remove(C); @@ -1740,11 +1744,16 @@ static bool ui_but_drag_init(bContext *C, uiBut *but, uiHandleButtonData *data, } } else { - wmDrag *drag; + wmDrag *drag = WM_event_start_drag( + C, but->icon, but->dragtype, but->dragpoin, + ui_but_value_get(but), WM_DRAG_NOP); - drag = WM_event_start_drag(C, but->icon, but->dragtype, but->dragpoin, ui_but_value_get(but), WM_DRAG_NOP); - if (but->imb) - WM_event_drag_image(drag, but->imb, but->imb_scale, BLI_rctf_size_x(&but->rect), BLI_rctf_size_y(&but->rect)); + if (but->imb) { + WM_event_drag_image( + drag, but->imb, but->imb_scale, + BLI_rctf_size_x(&but->rect), + BLI_rctf_size_y(&but->rect)); + } } return true; } @@ -1872,11 +1881,15 @@ static void ui_but_smart_controller_add(bContext *C, uiBut *from, uiBut *to) /* (3) add a new controller */ if (WM_operator_name_call(C, "LOGIC_OT_controller_add", WM_OP_EXEC_DEFAULT, &props_ptr) & OPERATOR_FINISHED) { cont = (bController *)ob->controllers.last; - cont->type = CONT_LOGIC_AND; /* Quick fix to make sure we always have an AND controller. It might be nicer to make sure the operator gives us the right one though... */ + /* Quick fix to make sure we always have an AND controller. + * It might be nicer to make sure the operator gives us the right one though... */ + cont->type = CONT_LOGIC_AND; /* (4) link the sensor->controller->actuator */ tmp_but = MEM_callocN(sizeof(uiBut), "uiBut"); - UI_but_link_set(tmp_but, (void **)&cont, (void ***)&(cont->links), &(cont->totlinks), from->link->tocode, (int)to->hardmin); + UI_but_link_set( + tmp_but, (void **)&cont, (void ***)&(cont->links), + &cont->totlinks, from->link->tocode, (int)to->hardmin); tmp_but->hardmin = from->link->tocode; tmp_but->poin = (char *)cont; @@ -3180,7 +3193,9 @@ static void ui_textedit_prev_but(uiBlock *block, uiBut *actbut, uiHandleButtonDa } -static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static void ui_do_but_textedit( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int retval = WM_UI_HANDLER_CONTINUE; bool changed = false, inbox = false, update = false; @@ -3233,7 +3248,8 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle if (data->searchbox) inbox = ui_searchbox_inside(data->searchbox, event->x, event->y); - /* for double click: we do a press again for when you first click on button (selects all text, no cursor pos) */ + /* for double click: we do a press again for when you first click on button + * (selects all text, no cursor pos) */ if (event->val == KM_PRESS || event->val == KM_DBL_CLICK) { float mx, my; @@ -3477,7 +3493,9 @@ static void ui_do_but_textedit(bContext *C, uiBlock *block, uiBut *but, uiHandle ED_region_tag_redraw(data->region); } -static void ui_do_but_textedit_select(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static void ui_do_but_textedit_select( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int mx, my, retval = WM_UI_HANDLER_CONTINUE; @@ -3682,7 +3700,9 @@ static uiBut *ui_but_list_row_text_activate( /* ***************** events for different button types *************** */ -static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_BUT( + bContext *C, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { if (data->state == BUTTON_STATE_HIGHLIGHT) { if (event->type == LEFTMOUSE && event->val == KM_PRESS) { @@ -3713,7 +3733,9 @@ static int ui_do_but_BUT(bContext *C, uiBut *but, uiHandleButtonData *data, cons return WM_UI_HANDLER_CONTINUE; } -static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_HOTKEYEVT( + bContext *C, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { if (data->state == BUTTON_STATE_HIGHLIGHT) { if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) { @@ -3776,7 +3798,9 @@ static int ui_do_but_HOTKEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data return WM_UI_HANDLER_CONTINUE; } -static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_KEYEVT( + bContext *C, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { if (data->state == BUTTON_STATE_HIGHLIGHT) { if (ELEM(event->type, LEFTMOUSE, PADENTER, RETKEY) && event->val == KM_PRESS) { @@ -3802,7 +3826,9 @@ static int ui_do_but_KEYEVT(bContext *C, uiBut *but, uiHandleButtonData *data, c return WM_UI_HANDLER_CONTINUE; } -static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_TEX( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { if (data->state == BUTTON_STATE_HIGHLIGHT) { if (ELEM(event->type, LEFTMOUSE, EVT_BUT_OPEN, PADENTER, RETKEY) && event->val == KM_PRESS) { @@ -3830,7 +3856,9 @@ static int ui_do_but_TEX(bContext *C, uiBlock *block, uiBut *but, uiHandleButton return WM_UI_HANDLER_CONTINUE; } -static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_SEARCH_UNLINK( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { uiButExtraIconType extra_icon_type; @@ -3877,7 +3905,9 @@ static int ui_do_but_SEARCH_UNLINK(bContext *C, uiBlock *block, uiBut *but, uiHa return ui_do_but_TEX(C, block, but, data, event); } -static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_TOG( + bContext *C, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { #ifdef USE_DRAG_TOGGLE if (data->state == BUTTON_STATE_HIGHLIGHT) { @@ -3944,7 +3974,9 @@ static int ui_do_but_TOG(bContext *C, uiBut *but, uiHandleButtonData *data, cons return WM_UI_HANDLER_CONTINUE; } -static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_EXIT( + bContext *C, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { if (data->state == BUTTON_STATE_HIGHLIGHT) { @@ -4092,7 +4124,7 @@ static float ui_numedit_apply_snap( static bool ui_numedit_but_NUM( uiBut *but, uiHandleButtonData *data, - int mx, + int mx, const bool is_motion, const enum eSnapType snap, float fac) { float deler, tempf, softmin, softmax, softrange; @@ -4100,8 +4132,10 @@ static bool ui_numedit_but_NUM( bool changed = false; const bool is_float = ui_but_is_float(but); - /* prevent unwanted drag adjustments */ - if (ui_but_dragedit_update_mval(data, mx) == false) { + /* prevent unwanted drag adjustments, test motion so modifier keys refresh. */ + if ((is_motion || data->draglock) && + (ui_but_dragedit_update_mval(data, mx) == false)) + { return changed; } @@ -4242,7 +4276,9 @@ static bool ui_numedit_but_NUM( return changed; } -static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_NUM( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int mx, my; /* mouse location scaled to fit the UI */ int screen_mx, screen_my; /* mouse location kept at screen pixel coords */ @@ -4324,6 +4360,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton } } else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) { + const bool is_motion = (event->type == MOUSEMOVE); const enum eSnapType snap = ui_event_to_snap(event); float fac; @@ -4335,8 +4372,9 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton fac = 1.0f; if (event->shift) fac /= 10.0f; - if (ui_numedit_but_NUM(but, data, (ui_but_is_cursor_warp(but) ? screen_mx : mx), snap, fac)) + if (ui_numedit_but_NUM(but, data, (ui_but_is_cursor_warp(but) ? screen_mx : mx), is_motion, snap, fac)) { ui_numedit_apply(C, block, but, data); + } #ifdef USE_DRAG_MULTINUM else if (data->multi_data.has_mbuts) { if (data->multi_data.init == BUTTON_MULTI_INIT_ENABLE) { @@ -4430,7 +4468,7 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton static bool ui_numedit_but_SLI( uiBut *but, uiHandleButtonData *data, - int mx, const bool is_horizontal, + int mx, const bool is_horizontal, const bool is_motion, const bool snap, const bool shift) { float deler, f, tempf, softmin, softmax, softrange; @@ -4440,8 +4478,9 @@ static bool ui_numedit_but_SLI( /* note, 'offs' is really from the widget drawing rounded corners see 'widget_numslider' */ float offs; - /* prevent unwanted drag adjustments */ + /* prevent unwanted drag adjustments, test motion so modifier keys refresh. */ if ((but->type != UI_BTYPE_SCROLL) && + (is_motion || data->draglock) && (ui_but_dragedit_update_mval(data, mx) == false)) { return changed; @@ -4541,7 +4580,9 @@ static bool ui_numedit_but_SLI( return changed; } -static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_SLI( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int mx, my, click = 0; int retval = WM_UI_HANDLER_CONTINUE; @@ -4634,12 +4675,14 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton } } else if ((event->type == MOUSEMOVE) || ui_event_is_snap(event)) { + const bool is_motion = (event->type == MOUSEMOVE); #ifdef USE_DRAG_MULTINUM data->multi_data.drag_dir[0] += abs(data->draglastx - mx); data->multi_data.drag_dir[1] += abs(data->draglasty - my); #endif - if (ui_numedit_but_SLI(but, data, mx, true, event->ctrl != 0, event->shift != 0)) + if (ui_numedit_but_SLI(but, data, mx, true, is_motion, event->ctrl != 0, event->shift != 0)) { ui_numedit_apply(C, block, but, data); + } #ifdef USE_DRAG_MULTINUM else if (data->multi_data.has_mbuts) { @@ -4722,7 +4765,9 @@ static int ui_do_but_SLI(bContext *C, uiBlock *block, uiBut *but, uiHandleButton return retval; } -static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_SCROLL( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int mx, my /*, click = 0 */; int retval = WM_UI_HANDLER_CONTINUE; @@ -4765,8 +4810,10 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut button_activate_state(C, but, BUTTON_STATE_EXIT); } else if (event->type == MOUSEMOVE) { - if (ui_numedit_but_SLI(but, data, (horizontal) ? mx : my, horizontal, false, false)) + const bool is_motion = (event->type == MOUSEMOVE); + if (ui_numedit_but_SLI(but, data, (horizontal) ? mx : my, horizontal, is_motion, false, false)) { ui_numedit_apply(C, block, but, data); + } } retval = WM_UI_HANDLER_BREAK; @@ -4775,7 +4822,9 @@ static int ui_do_but_SCROLL(bContext *C, uiBlock *block, uiBut *but, uiHandleBut return retval; } -static int ui_do_but_GRIP(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_GRIP( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int mx, my; int retval = WM_UI_HANDLER_CONTINUE; @@ -4826,7 +4875,9 @@ static int ui_do_but_GRIP(bContext *C, uiBlock *block, uiBut *but, uiHandleButto return retval; } -static int ui_do_but_LISTROW(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_LISTROW( + bContext *C, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { if (data->state == BUTTON_STATE_HIGHLIGHT) { /* hack to pass on ctrl+click and double click to overlapping text @@ -4846,7 +4897,9 @@ static int ui_do_but_LISTROW(bContext *C, uiBut *but, uiHandleButtonData *data, return ui_do_but_EXIT(C, but, data, event); } -static int ui_do_but_BLOCK(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_BLOCK( + bContext *C, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { if (data->state == BUTTON_STATE_HIGHLIGHT) { @@ -5021,7 +5074,9 @@ static void ui_palette_set_active(uiBut *but) } } -static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_COLOR( + bContext *C, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { if (data->state == BUTTON_STATE_HIGHLIGHT) { /* first handle click on icondrag type button */ @@ -5154,7 +5209,9 @@ static int ui_do_but_COLOR(bContext *C, uiBut *but, uiHandleButtonData *data, co return WM_UI_HANDLER_CONTINUE; } -static int ui_do_but_UNITVEC(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_UNITVEC( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int mx, my; @@ -5431,7 +5488,9 @@ static void ui_ndofedit_but_HSVCUBE( ui_but_v3_set(but, data->vec); } -static int ui_do_but_HSVCUBE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_HSVCUBE( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int mx, my; @@ -5693,7 +5752,9 @@ static void ui_ndofedit_but_HSVCIRCLE( } -static int ui_do_but_HSVCIRCLE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_HSVCIRCLE( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { ColorPicker *cpicker = but->custom_data; float *hsv = cpicker->color_data; @@ -5821,7 +5882,9 @@ static bool ui_numedit_but_COLORBAND(uiBut *but, uiHandleButtonData *data, int m return changed; } -static int ui_do_but_COLORBAND(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_COLORBAND( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { ColorBand *coba; CBData *cbd; @@ -5997,7 +6060,9 @@ static bool ui_numedit_but_CURVE( return changed; } -static int ui_do_but_CURVE(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_CURVE( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int mx, my, a; bool changed = false; @@ -6165,7 +6230,9 @@ static bool ui_numedit_but_HISTOGRAM(uiBut *but, uiHandleButtonData *data, int m return changed; } -static int ui_do_but_HISTOGRAM(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_HISTOGRAM( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int mx, my; @@ -6238,7 +6305,9 @@ static bool ui_numedit_but_WAVEFORM(uiBut *but, uiHandleButtonData *data, int mx return changed; } -static int ui_do_but_WAVEFORM(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_WAVEFORM( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int mx, my; @@ -6292,7 +6361,9 @@ static int ui_do_but_WAVEFORM(bContext *C, uiBlock *block, uiBut *but, uiHandleB return WM_UI_HANDLER_CONTINUE; } -static int ui_do_but_LINK(bContext *C, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_LINK( + bContext *C, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { VECCOPY2D(but->linkto, event->mval); @@ -6355,7 +6426,9 @@ static bool ui_numedit_but_TRACKPREVIEW( return changed; } -static int ui_do_but_TRACKPREVIEW(bContext *C, uiBlock *block, uiBut *but, uiHandleButtonData *data, const wmEvent *event) +static int ui_do_but_TRACKPREVIEW( + bContext *C, uiBlock *block, uiBut *but, + uiHandleButtonData *data, const wmEvent *event) { int mx, my; @@ -6851,7 +6924,8 @@ static bool ui_but_menu(bContext *C, uiBut *but) WM_operator_properties_create(&ptr_props, "WM_OT_doc_view"); RNA_string_set(&ptr_props, "doc_id", buf); - uiItemFullO(layout, "WM_OT_doc_view", CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"), + uiItemFullO(layout, "WM_OT_doc_view", + CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Online Python Reference"), ICON_NONE, ptr_props.data, WM_OP_EXEC_DEFAULT, 0); /* XXX inactive option, not for public! */ @@ -6860,7 +6934,8 @@ static bool ui_but_menu(bContext *C, uiBut *but) RNA_string_set(&ptr_props, "doc_id", buf); RNA_string_set(&ptr_props, "doc_new", RNA_property_description(but->rnaprop)); - uiItemFullO(layout, "WM_OT_doc_edit", "Submit Description", ICON_NONE, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0); + uiItemFullO(layout, "WM_OT_doc_edit", + "Submit Description", ICON_NONE, ptr_props.data, WM_OP_INVOKE_DEFAULT, 0); #endif } } @@ -7440,7 +7515,8 @@ static bool ui_but_contains_point_px(ARegion *ar, uiBut *but, int x, int y) /** * Can we mouse over the button or is it hidden/disabled/layout. - * Note: ctrl is kind of a hack currently, so that non-embossed UI_BTYPE_TEXT button behaves as a label when ctrl is not pressed. + * \note ctrl is kind of a hack currently, + * so that non-embossed UI_BTYPE_TEXT button behaves as a label when ctrl is not pressed. */ static bool ui_but_is_interactive(const uiBut *but, const bool labeledit) { @@ -7634,7 +7710,9 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s if (but->block->auto_open == true) { /* test for toolbox */ time = 1; } - else if ((but->block->flag & UI_BLOCK_LOOP && but->type != UI_BTYPE_BLOCK) || but->block->auto_open == true) { + else if ((but->block->flag & UI_BLOCK_LOOP && but->type != UI_BTYPE_BLOCK) || + (but->block->auto_open == true)) + { time = 5 * U.menuthreshold2; } else if (U.uiflag & USER_MENUOPENAUTO) { diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index e00d8cf7c07..4107414a240 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -1061,6 +1061,9 @@ static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size) } } +static void ui_id_preview_image_render_size( + const bContext *C, Scene *scene, ID *id, PreviewImage *pi, int size, const bool use_job); + void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool big) { Icon *icon = BKE_icon_get(icon_id); @@ -1076,22 +1079,20 @@ void ui_icon_ensure_deferred(const bContext *C, const int icon_id, const bool bi } if (di) { - if (di->type == ICON_TYPE_PREVIEW) { - PreviewImage *prv = (icon->type != 0) ? BKE_previewimg_id_ensure((ID *)icon->obj) : icon->obj; - - if (prv) { - const int size = big ? ICON_SIZE_PREVIEW : ICON_SIZE_ICON; - - if (!prv->use_deferred || prv->rect[size] || (prv->flag[size] & PRV_USER_EDITED)) { - return; + switch (di->type) { + case ICON_TYPE_PREVIEW: + { + ID *id = (icon->type != 0) ? icon->obj : NULL; + PreviewImage *prv = id ? BKE_previewimg_id_ensure(id) : icon->obj; + + if (prv) { + const int size = big ? ICON_SIZE_PREVIEW : ICON_SIZE_ICON; + + if (id || prv->use_deferred) { + ui_id_preview_image_render_size(C, NULL, id, prv, size, true); + } } - - icon_create_rect(prv, size); - - /* Always using job (background) version. */ - ED_preview_icon_job(C, prv, NULL, prv->rect[size], prv->w[size], prv->h[size]); - - prv->flag[size] &= ~PRV_CHANGED; + break; } } } diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 01b10b7b032..1af6d902b18 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -416,7 +416,7 @@ bool UI_context_copy_to_selected_list( if ((id_data == NULL) || (id_data->tag & LIB_TAG_DOIT) == 0 || - ID_IS_LINKED_DATABLOCK(id_data->lib) || + ID_IS_LINKED_DATABLOCK(id_data) || (GS(id_data->name) != id_code)) { BLI_remlink(&lb, link); diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 575b32e81e8..694794193da 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -110,7 +110,7 @@ bool ui_but_menu_step_poll(const uiBut *but) { BLI_assert(but->type == UI_BTYPE_MENU); - /* currenly only RNA buttons */ + /* currently only RNA buttons */ return ((but->menu_step_func != NULL) || (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_ENUM)); } @@ -459,6 +459,11 @@ static uiTooltipData *ui_tooltip_data_from_button(bContext *C, uiBut *but) data->format[data->totline].color_id = UI_TIP_LC_NORMAL; data->totline++; } + else if (ID_IS_LINKED_DATAPATH(id)) { + BLI_snprintf(data->lines[data->totline], sizeof(data->lines[0]), TIP_("Using file path as asset")); + data->format[data->totline].color_id = UI_TIP_LC_NORMAL; + data->totline++; + } } } else if (but->optype) { @@ -3331,6 +3336,11 @@ void UI_popup_block_close(bContext *C, wmWindow *win, uiBlock *block) if (win) { UI_popup_handlers_remove(&win->modalhandlers, block->handle); ui_popup_block_free(C, block->handle); + + /* In the case we have nested popups, closing one may need to redraw anorher, see: T48874 */ + for (ARegion *ar = win->screen->regionbase.first; ar; ar = ar->next) { + ED_region_tag_refresh_ui(ar); + } } } } diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index d91bd498225..aec4065adaf 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -302,7 +302,7 @@ static void template_id_cb(bContext *C, void *arg_litem, void *arg_event) break; case UI_ID_LOCAL: if (id) { - if (id_make_local(CTX_data_main(C), id, false)) { + if (id_make_local(CTX_data_main(C), id, false, false)) { /* reassign to get get proper updates/notifiers */ idptr = RNA_property_pointer_get(&template->ptr, template->prop); RNA_property_pointer_set(&template->ptr, template->prop, idptr); @@ -455,7 +455,7 @@ static void template_ID( else { but = uiDefIconBut(block, UI_BTYPE_BUT, 0, ICON_LIBRARY_DATA_DIRECT, 0, 0, UI_UNIT_X, UI_UNIT_Y, NULL, 0, 0, 0, 0, TIP_("Direct linked library datablock, click to make local")); - if (!id_make_local(CTX_data_main(C), id, true /* test */) || (idfrom && idfrom->lib)) + if (!id_make_local(CTX_data_main(C), id, true /* test */, false) || (idfrom && idfrom->lib)) UI_but_flag_enable(but, UI_BUT_DISABLED); } diff --git a/source/blender/editors/io/io_collada.c b/source/blender/editors/io/io_collada.c index b74c4b5f526..d62651cef81 100644 --- a/source/blender/editors/io/io_collada.c +++ b/source/blender/editors/io/io_collada.c @@ -175,7 +175,7 @@ static int wm_collada_export_exec(bContext *C, wmOperator *op) open_sim); if (export_count == 0) { - BKE_report(op->reports, RPT_WARNING, "Export file is empty"); + BKE_report(op->reports, RPT_WARNING, "No objects selected -- Created empty export file"); return OPERATOR_CANCELLED; } else if (export_count < 0) { diff --git a/source/blender/editors/mesh/editmesh_intersect.c b/source/blender/editors/mesh/editmesh_intersect.c index 69588928253..281a8b2a02d 100644 --- a/source/blender/editors/mesh/editmesh_intersect.c +++ b/source/blender/editors/mesh/editmesh_intersect.c @@ -563,7 +563,7 @@ static BMEdge *bm_face_split_edge_find( if (UNLIKELY(BM_edge_exists(v_pivot, l_iter->e->v1) || BM_edge_exists(v_pivot, l_iter->e->v2))) { - /* very unlikley but will cause complications splicing the verts together, + /* very unlikely but will cause complications splicing the verts together, * so just skip this case */ ok = false; } diff --git a/source/blender/editors/mesh/editmesh_rip.c b/source/blender/editors/mesh/editmesh_rip.c index e3e5863dc0e..e31e4096ded 100644 --- a/source/blender/editors/mesh/editmesh_rip.c +++ b/source/blender/editors/mesh/editmesh_rip.c @@ -395,7 +395,7 @@ static void edbm_ripsel_deselect_helper(BMesh *bm, EdgeLoopPair *eloop_pairs, * return an un-ordered array of loop pairs * use for rebuilding face-fill * - * \note the method currenly used fails for edges with 3+ face users and gives + * \note the method currently used fails for edges with 3+ face users and gives * nasty holes in the mesh, there isnt a good way of knowing ahead of time * which loops will be split apart (its possible to figure out but quite involved). * So for now this is a known limitation of current rip-fill option. @@ -748,10 +748,8 @@ static int edbm_rip_invoke__vert(bContext *C, wmOperator *op, const wmEvent *eve } if (do_fill) { - if (do_fill) { - /* match extrude vert-order */ - BM_edge_create(bm, vout[1], vout[0], NULL, BM_CREATE_NOP); - } + /* match extrude vert-order */ + BM_edge_create(bm, vout[1], vout[0], NULL, BM_CREATE_NOP); } MEM_freeN(vout); diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 3a7a8fb883b..1a14fad8650 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -4032,7 +4032,7 @@ static int edbm_decimate_exec(bContext *C, wmOperator *op) const MDeformVert *dv = BM_ELEM_CD_GET_VOID_P(v, cd_dvert_offset); weight = defvert_find_weight(dv, defbase_act); if (invert_vertex_group) { - weight = 1.0 - weight; + weight = 1.0f - weight; } } else { diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c index bcdd170c53c..0fe43c44d7d 100644 --- a/source/blender/editors/object/object_group.c +++ b/source/blender/editors/object/object_group.c @@ -440,7 +440,7 @@ static int group_link_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; /* Early return check, if the object is already in group - * we could sckip all the dependency check and just consider + * we could skip all the dependency check and just consider * operator is finished. */ if (BKE_group_object_exists(group, ob)) { diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 6b16e19f790..b3edf1f5e0d 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -2104,11 +2104,11 @@ static void make_local_makelocalmaterial(Material *ma) AnimData *adt; int b; - id_make_local(G.main, &ma->id, false); + id_make_local(G.main, &ma->id, false, false); for (b = 0; b < MAX_MTEX; b++) if (ma->mtex[b] && ma->mtex[b]->tex) - id_make_local(G.main, &ma->mtex[b]->tex->id, false); + id_make_local(G.main, &ma->mtex[b]->tex->id, false, false); adt = BKE_animdata_from_id(&ma->id); if (adt) BKE_animdata_make_local(adt); @@ -2237,7 +2237,7 @@ static int make_local_exec(bContext *C, wmOperator *op) } if (ob->id.lib) - id_make_local(bmain, &ob->id, false); + id_make_local(bmain, &ob->id, false, false); } CTX_DATA_END; @@ -2259,7 +2259,7 @@ static int make_local_exec(bContext *C, wmOperator *op) id = ob->data; if (id && (ELEM(mode, MAKE_LOCAL_SELECT_OBDATA, MAKE_LOCAL_SELECT_OBDATA_MATERIAL))) { - id_make_local(bmain, id, false); + id_make_local(bmain, id, false, false); adt = BKE_animdata_from_id(id); if (adt) BKE_animdata_make_local(adt); @@ -2275,7 +2275,7 @@ static int make_local_exec(bContext *C, wmOperator *op) } for (psys = ob->particlesystem.first; psys; psys = psys->next) - id_make_local(bmain, &psys->part->id, false); + id_make_local(bmain, &psys->part->id, false, false); adt = BKE_animdata_from_id(&ob->id); if (adt) BKE_animdata_make_local(adt); @@ -2294,7 +2294,7 @@ static int make_local_exec(bContext *C, wmOperator *op) for (b = 0; b < MAX_MTEX; b++) if (la->mtex[b] && la->mtex[b]->tex) - id_make_local(bmain, &la->mtex[b]->tex->id, false); + id_make_local(bmain, &la->mtex[b]->tex->id, false, false); } else { for (a = 0; a < ob->totcol; a++) { diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index 0cbbe46f461..f1b7186f8a1 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -577,7 +577,6 @@ static bool select_grouped_parent(bContext *C) /* Makes parent active and de-sel /* can be NULL if parent in other scene */ if (baspar && BASE_SELECTABLE(v3d, baspar)) { - ED_base_object_select(basact, BA_DESELECT); ED_base_object_select(baspar, BA_SELECT); ED_base_object_activate(C, baspar); changed = true; diff --git a/source/blender/editors/object/object_vgroup.c b/source/blender/editors/object/object_vgroup.c index 6e8aaebcccc..ad41fb23a69 100644 --- a/source/blender/editors/object/object_vgroup.c +++ b/source/blender/editors/object/object_vgroup.c @@ -3538,8 +3538,10 @@ static int vgroup_sort_name(const void *def_a_ptr, const void *def_b_ptr) return BLI_natstrcmp(def_a->name, def_b->name); } -/* Sorts the weight groups according to the bone hierarchy of the - associated armature (similar to how bones are ordered in the Outliner) */ +/** + * Sorts the weight groups according to the bone hierarchy of the + * associated armature (similar to how bones are ordered in the Outliner) + */ static void vgroup_sort_bone_hierarchy(Object *ob, ListBase *bonebase) { if (bonebase == NULL) { diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 1203889cf0e..8c5d25ad44d 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -1482,7 +1482,7 @@ static void render_view3d_do(RenderEngine *engine, const bContext *C) void render_view3d_update(RenderEngine *engine, const bContext *C) { /* this shouldn't be needed and causes too many database rebuilds, but we - * aren't actually tracking updates for all relevent datablocks so this is + * aren't actually tracking updates for all relevant datablocks so this is * a catch-all for updates */ engine->update_flag |= RE_ENGINE_UPDATE_DATABASE; diff --git a/source/blender/editors/render/render_shading.c b/source/blender/editors/render/render_shading.c index c3f83138707..5a0c250c777 100644 --- a/source/blender/editors/render/render_shading.c +++ b/source/blender/editors/render/render_shading.c @@ -102,7 +102,7 @@ static int material_slot_add_exec(bContext *C, wmOperator *UNUSED(op)) if (!ob) return OPERATOR_CANCELLED; - object_add_material_slot(ob); + BKE_object_material_slot_add(ob); if (ob->mode & OB_MODE_TEXTURE_PAINT) { Scene *scene = CTX_data_scene(C); @@ -145,7 +145,7 @@ static int material_slot_remove_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - object_remove_material_slot(ob); + BKE_object_material_slot_remove(ob); if (ob->mode & OB_MODE_TEXTURE_PAINT) { Scene *scene = CTX_data_scene(C); @@ -529,7 +529,7 @@ static int new_texture_exec(bContext *C, wmOperator *UNUSED(op)) if (prop) { /* when creating new ID blocks, use is already 1, but RNA - * pointer se also increases user, so this compensates it */ + * pointer use also increases user, so this compensates it */ id_us_min(&tex->id); if (ptr.id.data && GS(((ID *)ptr.id.data)->name) == ID_MA && @@ -592,7 +592,7 @@ static int new_world_exec(bContext *C, wmOperator *UNUSED(op)) if (prop) { /* when creating new ID blocks, use is already 1, but RNA - * pointer se also increases user, so this compensates it */ + * pointer use also increases user, so this compensates it */ id_us_min(&wo->id); RNA_id_pointer_create(&wo->id, &idptr); diff --git a/source/blender/editors/screen/area.c b/source/blender/editors/screen/area.c index ab8b7d4e138..8d058ed2081 100644 --- a/source/blender/editors/screen/area.c +++ b/source/blender/editors/screen/area.c @@ -580,15 +580,20 @@ void ED_region_tag_refresh_ui(ARegion *ar) void ED_region_tag_redraw_partial(ARegion *ar, const rcti *rct) { if (ar && !(ar->do_draw & RGN_DRAWING)) { - if (!(ar->do_draw & RGN_DRAW)) { + if (!(ar->do_draw & (RGN_DRAW | RGN_DRAW_PARTIAL))) { /* no redraw set yet, set partial region */ ar->do_draw |= RGN_DRAW_PARTIAL; ar->drawrct = *rct; } else if (ar->drawrct.xmin != ar->drawrct.xmax) { + BLI_assert((ar->do_draw & RGN_DRAW_PARTIAL) != 0); /* partial redraw already set, expand region */ BLI_rcti_union(&ar->drawrct, rct); } + else { + BLI_assert((ar->do_draw & RGN_DRAW) != 0); + /* Else, full redraw is already requested, nothing to do here. */ + } } } diff --git a/source/blender/editors/sculpt_paint/paint_image_proj.c b/source/blender/editors/sculpt_paint/paint_image_proj.c index 6ed969cb270..d60c8e8dbd9 100644 --- a/source/blender/editors/sculpt_paint/paint_image_proj.c +++ b/source/blender/editors/sculpt_paint/paint_image_proj.c @@ -183,8 +183,8 @@ BLI_INLINE unsigned char f_to_char(const float val) /* to avoid locking in tile initialization */ #define TILE_PENDING SET_INT_IN_POINTER(-1) -/* This is mainly a convenience struct used so we can keep an array of images we use - * Thir imbufs, etc, in 1 array, When using threads this array is copied for each thread +/* This is mainly a convenience struct used so we can keep an array of images we use - + * their imbufs, etc, in 1 array, When using threads this array is copied for each thread * because 'partRedrawRect' and 'touch' values would not be thread safe */ typedef struct ProjPaintImage { Image *ima; @@ -202,7 +202,7 @@ typedef struct ProjPaintImage { */ typedef struct ProjStrokeHandle { /* Support for painting from multiple views at once, - * currently used to impliment symmetry painting, + * currently used to implement symmetry painting, * we can assume at least the first is set while painting. */ struct ProjPaintState *ps_views[8]; int ps_views_tot; @@ -2174,7 +2174,7 @@ static void project_bucket_clip_face( if ((*tot) < 3) { /* no intersections to speak of, but more probable is that all face is just outside the - * rectangle and culled due to float precision issues. Since above teste have failed, + * rectangle and culled due to float precision issues. Since above tests have failed, * just dump triangle as is for painting */ *tot = 0; copy_v2_v2(bucket_bounds_uv[*tot], uv1co); (*tot)++; diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index aa17cb02fe5..1431958501d 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -491,31 +491,30 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, const float } /* Returns zero if no sculpt changes should be made, non-zero otherwise */ -static int paint_smooth_stroke(PaintStroke *stroke, float output[2], float *outpressure, - const PaintSample *sample, PaintMode mode) +static bool paint_smooth_stroke( + PaintStroke *stroke, const PaintSample *sample, PaintMode mode, + float r_mouse[2], float *r_pressure) { if (paint_supports_smooth_stroke(stroke->brush, mode)) { float radius = stroke->brush->smooth_stroke_radius * stroke->zoom_2d; - float u = stroke->brush->smooth_stroke_factor, v = 1.0f - u; - float dx = stroke->last_mouse_position[0] - sample->mouse[0]; - float dy = stroke->last_mouse_position[1] - sample->mouse[1]; + float u = stroke->brush->smooth_stroke_factor; /* If the mouse is moving within the radius of the last move, * don't update the mouse position. This allows sharp turns. */ - if (dx * dx + dy * dy < radius * radius) - return 0; + if (len_squared_v2v2(stroke->last_mouse_position, sample->mouse) < SQUARE(radius)) { + return false; + } - output[0] = sample->mouse[0] * v + stroke->last_mouse_position[0] * u; - output[1] = sample->mouse[1] * v + stroke->last_mouse_position[1] * u; - *outpressure = sample->pressure * v + stroke->last_pressure * u; + interp_v2_v2v2(r_mouse, sample->mouse, stroke->last_mouse_position, u); + *r_pressure = interpf(sample->pressure, stroke->last_pressure, u); } else { - output[0] = sample->mouse[0]; - output[1] = sample->mouse[1]; - *outpressure = sample->pressure; + r_mouse[0] = sample->mouse[0]; + r_mouse[1] = sample->mouse[1]; + *r_pressure = sample->pressure; } - return 1; + return true; } static float paint_space_stroke_spacing(const Scene *scene, PaintStroke *stroke, float size_pressure, float spacing_pressure) @@ -1190,7 +1189,7 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event) /* airbrush */ ((br->flag & BRUSH_AIRBRUSH) && event->type == TIMER && event->customdata == stroke->timer)) { - if (paint_smooth_stroke(stroke, mouse, &pressure, &sample_average, mode)) { + if (paint_smooth_stroke(stroke, &sample_average, mode, mouse, &pressure)) { if (stroke->stroke_started) { if (paint_space_stroke_enabled(br, mode)) { if (paint_space_stroke(C, op, mouse, pressure)) diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 3bcd610150c..991025a4d5d 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -257,9 +257,7 @@ static bool make_vertexcol(Object *ob) /* single ob */ /* copies from shadedisplist to mcol */ if (!me->mloopcol && me->totloop) { - if (!me->mloopcol) { - CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop); - } + CustomData_add_layer(&me->ldata, CD_MLOOPCOL, CD_DEFAULT, NULL, me->totloop); BKE_mesh_update_customdata_pointers(me, true); } @@ -2380,9 +2378,8 @@ static void wpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P swap_m4m4(vc->rv3d->persmat, mat); /* calculate pivot for rotation around seletion if needed */ - if (U.uiflag & USER_ORBIT_SELECTION) { - paint_last_stroke_update(scene, vc->ar, mval); - } + /* also needed for "View Selected" on last stroke */ + paint_last_stroke_update(scene, vc->ar, mval); DAG_id_tag_update(ob->data, 0); ED_region_tag_redraw(vc->ar); @@ -2858,9 +2855,8 @@ static void vpaint_stroke_update_step(bContext *C, struct PaintStroke *stroke, P } /* calculate pivot for rotation around seletion if needed */ - if (U.uiflag & USER_ORBIT_SELECTION) { - paint_last_stroke_update(scene, vc->ar, mval); - } + /* also needed for "View Selected" on last stroke */ + paint_last_stroke_update(scene, vc->ar, mval); ED_region_tag_redraw(vc->ar); diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c index cc7531b9783..1305b76b5ad 100644 --- a/source/blender/editors/sculpt_paint/sculpt.c +++ b/source/blender/editors/sculpt_paint/sculpt.c @@ -1145,7 +1145,9 @@ static void calc_area_normal_and_center( /* Return modified brush strength. Includes the direction of the brush, positive * values pull vertices, negative values push. Uses tablet pressure and a * special multiplier found experimentally to scale the strength factor. */ -static float brush_strength(const Sculpt *sd, const StrokeCache *cache, const float feather, const UnifiedPaintSettings *ups) +static float brush_strength( + const Sculpt *sd, const StrokeCache *cache, + const float feather, const UnifiedPaintSettings *ups) { const Scene *scene = cache->vc->scene; const Brush *brush = BKE_paint_brush((Paint *)&sd->paint); @@ -3985,7 +3987,9 @@ static void sculpt_init_mirror_clipping(Object *ob, SculptSession *ss) } /* Initialize the stroke cache invariants from operator properties */ -static void sculpt_update_cache_invariants(bContext *C, Sculpt *sd, SculptSession *ss, wmOperator *op, const float mouse[2]) +static void sculpt_update_cache_invariants( + bContext *C, Sculpt *sd, SculptSession *ss, + wmOperator *op, const float mouse[2]) { StrokeCache *cache = MEM_callocN(sizeof(StrokeCache), "stroke cache"); Scene *scene = CTX_data_scene(C); @@ -4448,7 +4452,9 @@ static void sculpt_raycast_detail_cb(PBVHNode *node, void *data_v, float *tmin) } } -static float sculpt_raycast_init(ViewContext *vc, const float mouse[2], float ray_start[3], float ray_end[3], float ray_normal[3], bool original) +static float sculpt_raycast_init( + ViewContext *vc, const float mouse[2], + float ray_start[3], float ray_end[3], float ray_normal[3], bool original) { float obimat[4][4]; float dist; @@ -4956,8 +4962,9 @@ void sculpt_dyntopo_node_layers_add(SculptSession *ss) cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->vdata, CD_PROP_INT, layer_id); } - ss->cd_vert_node_offset = CustomData_get_n_offset(&ss->bm->vdata, CD_PROP_INT, - cd_node_layer_index - CustomData_get_layer_index(&ss->bm->vdata, CD_PROP_INT)); + ss->cd_vert_node_offset = CustomData_get_n_offset( + &ss->bm->vdata, CD_PROP_INT, + cd_node_layer_index - CustomData_get_layer_index(&ss->bm->vdata, CD_PROP_INT)); ss->bm->vdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY; @@ -4967,8 +4974,9 @@ void sculpt_dyntopo_node_layers_add(SculptSession *ss) cd_node_layer_index = CustomData_get_named_layer_index(&ss->bm->pdata, CD_PROP_INT, layer_id); } - ss->cd_face_node_offset = CustomData_get_n_offset(&ss->bm->pdata, CD_PROP_INT, - cd_node_layer_index - CustomData_get_layer_index(&ss->bm->pdata, CD_PROP_INT)); + ss->cd_face_node_offset = CustomData_get_n_offset( + &ss->bm->pdata, CD_PROP_INT, + cd_node_layer_index - CustomData_get_layer_index(&ss->bm->pdata, CD_PROP_INT)); ss->bm->pdata.layers[cd_node_layer_index].flag |= CD_FLAG_TEMPORARY; } @@ -5667,7 +5675,8 @@ static void SCULPT_OT_sample_detail_size(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_int_array(ot->srna, "location", 2, NULL, 0, SHRT_MAX, "Location", "Screen Coordinates of sampling", 0, SHRT_MAX); + RNA_def_int_array(ot->srna, "location", 2, NULL, 0, SHRT_MAX, + "Location", "Screen Coordinates of sampling", 0, SHRT_MAX); } diff --git a/source/blender/editors/sound/sound_ops.c b/source/blender/editors/sound/sound_ops.c index 4931426d62e..03f2e146b7d 100644 --- a/source/blender/editors/sound/sound_ops.c +++ b/source/blender/editors/sound/sound_ops.c @@ -136,7 +136,7 @@ static int sound_open_exec(bContext *C, wmOperator *op) if (pprop->prop) { /* when creating new ID blocks, use is already 1, but RNA - * pointer se also increases user, so this compensates it */ + * pointer use also increases user, so this compensates it */ id_us_min(&sound->id); RNA_id_pointer_create(&sound->id, &idptr); diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index 1ff656243d6..14d0f909d23 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -634,7 +634,7 @@ typedef struct PrefetchQueue { short render_size, render_flag; /* If true prefecthing goes forward in time, - * othwewise it goes backwards in time (starting from current frame). + * otherwise it goes backwards in time (starting from current frame). */ bool forward; diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 085fdd57309..83876ae2669 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -234,7 +234,7 @@ static int open_exec(bContext *C, wmOperator *op) if (pprop->prop) { /* when creating new ID blocks, use is already 1, but RNA - * pointer se also increases user, so this compensates it */ + * pointer use also increases user, so this compensates it */ id_us_min(&clip->id); RNA_id_pointer_create(&clip->id, &idptr); diff --git a/source/blender/editors/space_file/file_ops.c b/source/blender/editors/space_file/file_ops.c index 6d1916cfae7..6fb55729802 100644 --- a/source/blender/editors/space_file/file_ops.c +++ b/source/blender/editors/space_file/file_ops.c @@ -40,7 +40,7 @@ #include "BLO_readfile.h" #include "BKE_appdir.h" -#include "BKE_asset.h" +#include "BKE_asset_engine.h" #include "BKE_context.h" #include "BKE_screen.h" #include "BKE_global.h" diff --git a/source/blender/editors/space_file/filelist.c b/source/blender/editors/space_file/filelist.c index 8e2eed89de2..814eb846d37 100644 --- a/source/blender/editors/space_file/filelist.c +++ b/source/blender/editors/space_file/filelist.c @@ -65,7 +65,7 @@ #include "RNA_types.h" -#include "BKE_asset.h" +#include "BKE_asset_engine.h" #include "BKE_context.h" #include "BKE_global.h" #include "BKE_library.h" diff --git a/source/blender/editors/space_file/filelist.h b/source/blender/editors/space_file/filelist.h index cd008d4a54b..ee768ba6087 100644 --- a/source/blender/editors/space_file/filelist.h +++ b/source/blender/editors/space_file/filelist.h @@ -37,7 +37,7 @@ extern "C" { #endif -#include "BKE_asset.h" +#include "BKE_asset_engine.h" struct AssetEngineType; struct AssetEngine; diff --git a/source/blender/editors/space_file/space_file.c b/source/blender/editors/space_file/space_file.c index 9f5fffc73c5..7e230b5befb 100644 --- a/source/blender/editors/space_file/space_file.c +++ b/source/blender/editors/space_file/space_file.c @@ -43,7 +43,7 @@ #include "RNA_types.h" #include "BKE_appdir.h" -#include "BKE_asset.h" +#include "BKE_asset_engine.h" #include "BKE_context.h" #include "BKE_screen.h" #include "BKE_global.h" diff --git a/source/blender/editors/space_graph/graph_draw.c b/source/blender/editors/space_graph/graph_draw.c index b837e516422..ae91a466495 100644 --- a/source/blender/editors/space_graph/graph_draw.c +++ b/source/blender/editors/space_graph/graph_draw.c @@ -826,7 +826,7 @@ static void graph_draw_driver_debug(bAnimContext *ac, ID *id, FCurve *fcu) //if ((driver->flag & DRIVER_FLAG_SHOWDEBUG) == 0) // return; - /* No curve to modify/visualise the result? + /* No curve to modify/visualize the result? * => We still want to show the 1-1 default... */ if ((fcu->totvert == 0) && BLI_listbase_is_empty(&fcu->modifiers)) { diff --git a/source/blender/editors/space_image/image_buttons.c b/source/blender/editors/space_image/image_buttons.c index a2db6827b0e..38a54ade367 100644 --- a/source/blender/editors/space_image/image_buttons.c +++ b/source/blender/editors/space_image/image_buttons.c @@ -345,6 +345,13 @@ struct ImageUI_Data { int rpass_index; }; +static struct ImageUI_Data *ui_imageuser_data_copy(const struct ImageUI_Data *rnd_pt_src) +{ + struct ImageUI_Data *rnd_pt_dst = MEM_mallocN(sizeof(*rnd_pt_src), __func__); + memcpy(rnd_pt_dst, rnd_pt_src, sizeof(*rnd_pt_src)); + return rnd_pt_dst; +} + static void ui_imageuser_layer_menu(bContext *UNUSED(C), uiLayout *layout, void *rnd_pt) { struct ImageUI_Data *rnd_data = rnd_pt; @@ -532,9 +539,10 @@ static void ui_imageuser_view_menu_multiview(bContext *UNUSED(C), uiLayout *layo } /* 5 layer button callbacks... */ -static void image_multi_cb(bContext *C, void *rr_v, void *iuser_v) +static void image_multi_cb(bContext *C, void *rnd_pt, void *rr_v) { - ImageUser *iuser = iuser_v; + struct ImageUI_Data *rnd_data = rnd_pt; + ImageUser *iuser = rnd_data->iuser; BKE_image_multilayer_index(rr_v, iuser); WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); @@ -575,6 +583,8 @@ static bool ui_imageuser_layer_menu_step(bContext *C, int direction, void *rnd_p BLI_assert(0); } + BKE_image_release_renderresult(scene, image); + if (changed) { BKE_image_multilayer_index(rr, iuser); WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); @@ -662,10 +672,11 @@ static bool ui_imageuser_pass_menu_step(bContext *C, int direction, void *rnd_pt } /* 5 view button callbacks... */ -static void image_multiview_cb(bContext *C, void *ima_v, void *iuser_v) +static void image_multiview_cb(bContext *C, void *rnd_pt, void *UNUSED(arg_v)) { - Image *ima = ima_v; - ImageUser *iuser = iuser_v; + struct ImageUI_Data *rnd_data = rnd_pt; + Image *ima = rnd_data->image; + ImageUser *iuser = rnd_data->iuser; BKE_image_multiview_index(ima, iuser); WM_event_add_notifier(C, NC_IMAGE | ND_DRAW, NULL); @@ -692,7 +703,7 @@ static void uiblock_layer_pass_buttons( uiLayout *layout, Image *image, RenderResult *rr, ImageUser *iuser, int w, short *render_slot) { - static struct ImageUI_Data rnd_pt; /* XXX, workaround */ + struct ImageUI_Data rnd_pt_local, *rnd_pt = NULL; uiBlock *block = uiLayoutGetBlock(layout); uiBut *but; RenderLayer *rl = NULL; @@ -708,10 +719,10 @@ static void uiblock_layer_pass_buttons( wmenu2 = (3 * w) / 5; wmenu3 = (3 * w) / 6; wmenu4 = (3 * w) / 6; - - rnd_pt.image = image; - rnd_pt.iuser = iuser; - rnd_pt.rpass_index = 0; + + rnd_pt_local.image = image; + rnd_pt_local.iuser = iuser; + rnd_pt_local.rpass_index = 0; /* menu buts */ if (render_slot) { @@ -723,10 +734,12 @@ static void uiblock_layer_pass_buttons( BLI_snprintf(str, sizeof(str), IFACE_("Slot %d"), *render_slot + 1); } + rnd_pt = ui_imageuser_data_copy(&rnd_pt_local); but = uiDefMenuBut(block, ui_imageuser_slot_menu, image, str, 0, 0, wmenu1, UI_UNIT_Y, TIP_("Select Slot")); UI_but_func_menu_step_set(but, ui_imageuser_slot_menu_step); - UI_but_func_set(but, image_multi_cb, rr, iuser); + UI_but_funcN_set(but, image_multi_cb, rnd_pt, rr); UI_but_type_set_menu_from_pulldown(but); + rnd_pt = NULL; } if (rr) { @@ -738,15 +751,18 @@ static void uiblock_layer_pass_buttons( fake_name = ui_imageuser_layer_fake_name(rr); rpass_index = iuser->layer - (fake_name ? 1 : 0); rl = BLI_findlink(&rr->layers, rpass_index); - rnd_pt.rpass_index = rpass_index; + rnd_pt_local.rpass_index = rpass_index; if (RE_layers_have_name(rr)) { display_name = rl ? rl->name : (fake_name ? fake_name : ""); - but = uiDefMenuBut(block, ui_imageuser_layer_menu, &rnd_pt, display_name, - 0, 0, wmenu2, UI_UNIT_Y, TIP_("Select Layer")); + rnd_pt = ui_imageuser_data_copy(&rnd_pt_local); + but = uiDefMenuBut( + block, ui_imageuser_layer_menu, rnd_pt, display_name, + 0, 0, wmenu2, UI_UNIT_Y, TIP_("Select Layer")); UI_but_func_menu_step_set(but, ui_imageuser_layer_menu_step); - UI_but_func_set(but, image_multi_cb, rr, iuser); + UI_but_funcN_set(but, image_multi_cb, rnd_pt, rr); UI_but_type_set_menu_from_pulldown(but); + rnd_pt = NULL; } /* pass */ @@ -754,11 +770,14 @@ static void uiblock_layer_pass_buttons( rpass = (rl ? BLI_findlink(&rl->passes, iuser->pass - (fake_name ? 1 : 0)) : NULL); display_name = rpass ? rpass->internal_name : (fake_name ? fake_name : ""); - but = uiDefMenuBut(block, ui_imageuser_pass_menu, &rnd_pt, IFACE_(display_name), - 0, 0, wmenu3, UI_UNIT_Y, TIP_("Select Pass")); + rnd_pt = ui_imageuser_data_copy(&rnd_pt_local); + but = uiDefMenuBut( + block, ui_imageuser_pass_menu, rnd_pt, IFACE_(display_name), + 0, 0, wmenu3, UI_UNIT_Y, TIP_("Select Pass")); UI_but_func_menu_step_set(but, ui_imageuser_pass_menu_step); - UI_but_func_set(but, image_multi_cb, rr, iuser); + UI_but_funcN_set(but, image_multi_cb, rnd_pt, rr); UI_but_type_set_menu_from_pulldown(but); + rnd_pt = NULL; /* view */ if (BLI_listbase_count_ex(&rr->views, 2) > 1 && @@ -767,9 +786,13 @@ static void uiblock_layer_pass_buttons( rview = BLI_findlink(&rr->views, iuser->view); display_name = rview ? rview->name : ""; - but = uiDefMenuBut(block, ui_imageuser_view_menu_rr, &rnd_pt, display_name, 0, 0, wmenu4, UI_UNIT_Y, TIP_("Select View")); - UI_but_func_set(but, image_multi_cb, rr, iuser); + rnd_pt = ui_imageuser_data_copy(&rnd_pt_local); + but = uiDefMenuBut( + block, ui_imageuser_view_menu_rr, rnd_pt, display_name, + 0, 0, wmenu4, UI_UNIT_Y, TIP_("Select View")); + UI_but_funcN_set(but, image_multi_cb, rnd_pt, rr); UI_but_type_set_menu_from_pulldown(but); + rnd_pt = NULL; } } @@ -787,9 +810,13 @@ static void uiblock_layer_pass_buttons( } } - but = uiDefMenuBut(block, ui_imageuser_view_menu_multiview, &rnd_pt, display_name, 0, 0, wmenu1, UI_UNIT_Y, TIP_("Select View")); - UI_but_func_set(but, image_multiview_cb, image, iuser); + rnd_pt = ui_imageuser_data_copy(&rnd_pt_local); + but = uiDefMenuBut( + block, ui_imageuser_view_menu_multiview, rnd_pt, display_name, + 0, 0, wmenu1, UI_UNIT_Y, TIP_("Select View")); + UI_but_funcN_set(but, image_multiview_cb, rnd_pt, NULL); UI_but_type_set_menu_from_pulldown(but); + rnd_pt = NULL; } } diff --git a/source/blender/editors/space_image/image_ops.c b/source/blender/editors/space_image/image_ops.c index 06caf930988..1158e692182 100644 --- a/source/blender/editors/space_image/image_ops.c +++ b/source/blender/editors/space_image/image_ops.c @@ -1061,6 +1061,12 @@ typedef struct ImageOpenData { ImageFormatData im_format; } ImageOpenData; +typedef struct ImageFrameRange { + struct ImageFrameRange *next, *prev; + ListBase frames; + char filepath[FILE_MAX]; +} ImageFrameRange; + typedef struct ImageFrame { struct ImageFrame *next, *prev; int framenr; @@ -1086,10 +1092,10 @@ static void image_open_cancel(bContext *UNUSED(C), wmOperator *op) * \param frames [out] the list of frame numbers found in the files matching the first one by name * \param path [out] the full path of the first file in the list of image files */ -static void image_sequence_get_frames(PointerRNA *ptr, ListBase *frames, char *path, const size_t maxlen) +static void image_sequence_get_frame_ranges(PointerRNA *ptr, ListBase *frames_all) { char dir[FILE_MAXDIR]; - bool is_first_entry = true; + ImageFrameRange *frame_range = NULL; RNA_string_get(ptr, "directory", dir); RNA_BEGIN (ptr, itemptr, "files") @@ -1101,29 +1107,26 @@ static void image_sequence_get_frames(PointerRNA *ptr, ListBase *frames, char *p ImageFrame *frame = MEM_callocN(sizeof(ImageFrame), "image_frame"); /* use the first file in the list as base filename */ - if (is_first_entry) { - BLI_join_dirfile(path, maxlen, dir, filename); - frame->framenr = BLI_stringdec(filename, base_head, base_tail, &digits); - BLI_addtail(frames, frame); - is_first_entry = false; + frame->framenr = BLI_stringdec(filename, head, tail, &digits); + + /* still in the same sequence */ + if ((frame_range != NULL) && + (STREQLEN(base_head, head, FILE_MAX)) && + (STREQLEN(base_tail, tail, FILE_MAX))) + { + /* pass */ } else { - frame->framenr = BLI_stringdec(filename, head, tail, &digits); + /* start a new frame range */ + frame_range = MEM_callocN(sizeof(*frame_range), __func__); + BLI_join_dirfile(frame_range->filepath, sizeof(frame_range->filepath), dir, filename); + BLI_addtail(frames_all, frame_range); - /* still in the same sequence */ - if ((STREQLEN(base_head, head, FILE_MAX)) && - (STREQLEN(base_tail, tail, FILE_MAX))) - { - BLI_addtail(frames, frame); - } - else { - /* different file base name found, is ignored */ - MEM_freeN(filename); - MEM_freeN(frame); - break; - } + BLI_strncpy(base_head, head, sizeof(base_head)); + BLI_strncpy(base_tail, tail, sizeof(base_tail)); } + BLI_addtail(&frame_range->frames, frame); MEM_freeN(filename); } RNA_END @@ -1164,6 +1167,52 @@ static int image_sequence_get_len(ListBase *frames, int *ofs) return 0; } +static Image *image_open_single( + wmOperator *op, const char *filepath, const char *relbase, + bool is_relative_path, bool use_multiview, int frame_seq_len) +{ + bool exists = false; + Image *ima = NULL; + + errno = 0; + ima = BKE_image_load_exists_ex(filepath, &exists); + + if (!ima) { + if (op->customdata) MEM_freeN(op->customdata); + BKE_reportf(op->reports, RPT_ERROR, "Cannot read '%s': %s", + filepath, errno ? strerror(errno) : TIP_("unsupported image format")); + return NULL; + } + + if (!exists) { + /* only image path after save, never ibuf */ + if (is_relative_path) { + BLI_path_rel(ima->name, relbase); + } + + /* handle multiview images */ + if (use_multiview) { + ImageOpenData *iod = op->customdata; + ImageFormatData *imf = &iod->im_format; + + ima->flag |= IMA_USE_VIEWS; + ima->views_format = imf->views_format; + *ima->stereo3d_format = imf->stereo3d_format; + } + else { + ima->flag &= ~IMA_USE_VIEWS; + BKE_image_free_views(ima); + } + + if ((frame_seq_len > 1) && (ima->source == IMA_SRC_FILE)) { + ima->source = IMA_SRC_SEQUENCE; + } + } + + return ima; +} + + static int image_open_exec(bContext *C, wmOperator *op) { Main *bmain = CTX_data_main(C); @@ -1174,70 +1223,60 @@ static int image_open_exec(bContext *C, wmOperator *op) ImageOpenData *iod = op->customdata; PointerRNA idptr; Image *ima = NULL; - char path[FILE_MAX]; + char filepath[FILE_MAX]; int frame_seq_len = 0; int frame_ofs = 1; - bool exists = false; const bool is_relative_path = RNA_boolean_get(op->ptr, "relative_path"); + const bool use_multiview = RNA_boolean_get(op->ptr, "use_multiview"); - RNA_string_get(op->ptr, "filepath", path); + if (!op->customdata) + image_open_init(C, op); + + RNA_string_get(op->ptr, "filepath", filepath); if (RNA_struct_property_is_set(op->ptr, "directory") && RNA_struct_property_is_set(op->ptr, "files")) { - /* only to pass to imbuf */ - char path_full[FILE_MAX]; - BLI_strncpy(path_full, path, sizeof(path_full)); - BLI_path_abs(path_full, G.main->name); + bool was_relative = BLI_path_is_rel(filepath); + ListBase frame_ranges_all; - if (!IMB_isanim(path_full)) { - bool was_relative = BLI_path_is_rel(path); - ListBase frames; + BLI_listbase_clear(&frame_ranges_all); + image_sequence_get_frame_ranges(op->ptr, &frame_ranges_all); + for (ImageFrameRange *frame_range = frame_ranges_all.first; frame_range; frame_range = frame_range->next) { + int frame_range_ofs; + int frame_range_seq_len = image_sequence_get_len(&frame_range->frames, &frame_range_ofs); + BLI_freelistN(&frame_range->frames); - BLI_listbase_clear(&frames); - image_sequence_get_frames(op->ptr, &frames, path, sizeof(path)); - frame_seq_len = image_sequence_get_len(&frames, &frame_ofs); - BLI_freelistN(&frames); + char filepath_range[FILE_MAX]; + BLI_strncpy(filepath_range, frame_range->filepath, sizeof(filepath_range)); if (was_relative) { - BLI_path_rel(path, G.main->name); + BLI_path_rel(filepath_range, bmain->name); } - } - } - - errno = 0; - ima = BKE_image_load_exists_ex(path, &exists); + Image *ima_range = image_open_single( + op, filepath_range, bmain->name, + is_relative_path, use_multiview, frame_range_seq_len); - if (!ima) { - if (op->customdata) MEM_freeN(op->customdata); - BKE_reportf(op->reports, RPT_ERROR, "Cannot read '%s': %s", - path, errno ? strerror(errno) : TIP_("unsupported image format")); - return OPERATOR_CANCELLED; - } - - if (!op->customdata) - image_open_init(C, op); - - /* handle multiview images */ - if (RNA_boolean_get(op->ptr, "use_multiview")) { - ImageFormatData *imf = &iod->im_format; - - ima->flag |= IMA_USE_VIEWS; - ima->views_format = imf->views_format; - *ima->stereo3d_format = imf->stereo3d_format; + /* take the first image */ + if ((ima == NULL) && ima_range) { + ima = ima_range; + frame_seq_len = frame_range_seq_len; + frame_ofs = frame_range_ofs; + } + } + BLI_freelistN(&frame_ranges_all); } else { - ima->flag &= ~IMA_USE_VIEWS; - BKE_image_free_views(ima); + /* for drag & drop etc. */ + ima = image_open_single( + op, filepath, bmain->name, + is_relative_path, use_multiview, 1); } - /* only image path after save, never ibuf */ - if (is_relative_path) { - if (!exists) { - BLI_path_rel(ima->name, bmain->name); - } + if (ima == NULL) { + return OPERATOR_CANCELLED; } /* hook into UI */ @@ -1245,11 +1284,9 @@ static int image_open_exec(bContext *C, wmOperator *op) if (iod->pprop.prop) { /* when creating new ID blocks, use is already 1, but RNA - * pointer se also increases user, so this compensates it */ + * pointer use also increases user, so this compensates it */ id_us_min(&ima->id); - if ((frame_seq_len > 1) && ima->source == IMA_SRC_FILE) { - ima->source = IMA_SRC_SEQUENCE; - } + RNA_id_pointer_create(&ima->id, &idptr); RNA_property_pointer_set(&iod->pprop.ptr, iod->pprop.prop, idptr); RNA_property_update(C, &iod->pprop.ptr, iod->pprop.prop); @@ -2359,7 +2396,7 @@ static int image_new_exec(bContext *C, wmOperator *op) if (prop) { /* when creating new ID blocks, use is already 1, but RNA - * pointer se also increases user, so this compensates it */ + * pointer use also increases user, so this compensates it */ id_us_min(&ima->id); RNA_id_pointer_create(&ima->id, &idptr); diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c index d7249897723..ea3869ef387 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.c @@ -1726,7 +1726,7 @@ static int node_insert_offset_modal(bContext *C, wmOperator *UNUSED(op), const w float duration; bool redraw = false; - if (!snode || event->type != TIMER || iofsd->anim_timer != event->customdata) + if (!snode || event->type != TIMER || iofsd == NULL || iofsd->anim_timer != event->customdata) return OPERATOR_PASS_THROUGH; duration = (float)iofsd->anim_timer->duration; diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 5173b18dc9b..b357e742d78 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1568,7 +1568,7 @@ static void outliner_draw_tree_element( else offsx += 2 * ufac; - if (tselem->type == 0 && ID_IS_LINKED_DATABLOCK(tselem->id)) { + if (tselem->type == 0 && ID_IS_LINKED(tselem->id)) { glPixelTransferf(GL_ALPHA_SCALE, 0.5f); if (tselem->id->tag & LIB_TAG_MISSING) { UI_icon_draw((float)startx + offsx, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_BROKEN); @@ -1579,8 +1579,6 @@ static void outliner_draw_tree_element( else { UI_icon_draw((float)startx + offsx, (float)*starty + 2 * ufac, ICON_LIBRARY_DATA_DIRECT); } - /* TODO use proper icons or other UI feedback, for sake of simplicity for now using basic - * color code to show assets and their state. */ if (tselem->id->uuid) { offsx += UI_UNIT_X; UI_icon_draw((float)startx + offsx - 0.5f * ufac, (float)*starty + 1.5f * ufac, ICON_SOLO_ON); diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index b0cd3aabbfd..3c47f542dae 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -417,9 +417,9 @@ static int outliner_id_remap_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - if (!(old_id && (old_id != new_id) && (GS(old_id->name) == GS(new_id->name)))) { + if (!(old_id && new_id && (old_id != new_id) && (GS(old_id->name) == GS(new_id->name)))) { BKE_reportf(op->reports, RPT_ERROR_INVALID_INPUT, "Invalid old/new ID pair ('%s' / '%s')", - old_id->name, new_id->name); + old_id ? old_id->name : "Invalid ID", new_id ? new_id->name : "Invalid ID"); return OPERATOR_CANCELLED; } diff --git a/source/blender/editors/space_outliner/outliner_tools.c b/source/blender/editors/space_outliner/outliner_tools.c index f3235d07757..a840a720b3d 100644 --- a/source/blender/editors/space_outliner/outliner_tools.c +++ b/source/blender/editors/space_outliner/outliner_tools.c @@ -435,11 +435,12 @@ static void id_local_cb( bContext *C, ReportList *UNUSED(reports), Scene *UNUSED(scene), TreeElement *UNUSED(te), TreeStoreElem *UNUSED(tsep), TreeStoreElem *tselem, void *UNUSED(user_data)) { - if (ID_IS_LINKED_DATABLOCK(tselem->id) && (tselem->id->tag & LIB_TAG_EXTERN)) { + if (ID_IS_LINKED(tselem->id) && (tselem->id->tag & LIB_TAG_EXTERN)) { Main *bmain = CTX_data_main(C); /* if the ID type has no special local function, - * just clear the lib */ - if (id_make_local(bmain, tselem->id, false) == false) { + * just clear the lib. */ + /* XXX This is very, very, **very** suspicious - should not be handled that way at all!!! */ + if (id_make_local(bmain, tselem->id, false, false) == false) { id_clear_lib_data(bmain, tselem->id); } } @@ -516,23 +517,16 @@ static void group_linkobs2scene_cb( Group *group = (Group *)tselem->id; GroupObject *gob; Base *base; - + for (gob = group->gobject.first; gob; gob = gob->next) { base = BKE_scene_base_find(scene, gob->ob); - if (base) { - base->object->flag |= SELECT; - base->flag |= SELECT; - } - else { + if (!base) { /* link to scene */ - base = MEM_callocN(sizeof(Base), "add_base"); - BLI_addhead(&scene->base, base); - base->lay = gob->ob->lay; - gob->ob->flag |= SELECT; - base->flag = gob->ob->flag; - base->object = gob->ob; + base = BKE_scene_base_add(scene, gob->ob); id_lib_extern((ID *)gob->ob); /* in case these are from a linked group */ } + base->object->flag |= SELECT; + base->flag |= SELECT; } } @@ -1352,7 +1346,7 @@ static int outliner_lib_operation_exec(bContext *C, wmOperator *op) Scene *scene = CTX_data_scene(C); SpaceOops *soops = CTX_wm_space_outliner(C); int scenelevel = 0, objectlevel = 0, idlevel = 0, datalevel = 0; - eOutlinerIdOpTypes event; + eOutlinerLibOpTypes event; /* check for invalid states */ if (soops == NULL) diff --git a/source/blender/editors/space_sequencer/sequencer_add.c b/source/blender/editors/space_sequencer/sequencer_add.c index c11a4d2e5a3..ede6b7ce469 100644 --- a/source/blender/editors/space_sequencer/sequencer_add.c +++ b/source/blender/editors/space_sequencer/sequencer_add.c @@ -1071,7 +1071,7 @@ static int sequencer_add_effect_strip_invoke(bContext *C, wmOperator *op, const { bool is_type_set = RNA_struct_property_is_set(op->ptr, "type"); int type = -1; - int prop_flag = SEQPROP_ENDFRAME; + int prop_flag = SEQPROP_ENDFRAME | SEQPROP_NOPATHS; if (is_type_set) { type = RNA_enum_get(op->ptr, "type"); @@ -1106,9 +1106,6 @@ void SEQUENCER_OT_effect_strip_add(struct wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - WM_operator_properties_filesel( - ot, 0, FILE_SPECIAL, FILE_OPENFILE, - WM_FILESEL_FILEPATH | WM_FILESEL_RELPATH, FILE_DEFAULTDISPLAY, FILE_SORT_ALPHA); sequencer_generic_props__internal(ot, SEQPROP_STARTFRAME | SEQPROP_ENDFRAME); RNA_def_enum(ot->srna, "type", sequencer_prop_effect_types, SEQ_TYPE_CROSS, "Type", "Sequencer effect type"); RNA_def_float_vector(ot->srna, "color", 3, NULL, 0.0f, 1.0f, "Color", diff --git a/source/blender/editors/space_view3d/drawmesh.c b/source/blender/editors/space_view3d/drawmesh.c index 791ece14cb9..f5289a0d245 100644 --- a/source/blender/editors/space_view3d/drawmesh.c +++ b/source/blender/editors/space_view3d/drawmesh.c @@ -237,7 +237,9 @@ static struct TextureDrawState { bool texpaint_material; /* use material slots for texture painting */ } Gtexdraw = {NULL, NULL, NULL, false, 0, 0, 0, false, false, {0, 0, 0, 0}, false, false}; -static bool set_draw_settings_cached(int clearcache, MTexPoly *texface, Material *ma, struct TextureDrawState gtexdraw) +static bool set_draw_settings_cached( + int clearcache, MTexPoly *texface, Material *ma, + const struct TextureDrawState *gtexdraw) { static Material *c_ma; static int c_textured; @@ -253,7 +255,7 @@ static bool set_draw_settings_cached(int clearcache, MTexPoly *texface, Material int lit = 0; int has_texface = texface != NULL; bool need_set_tpage = false; - bool texpaint = ((gtexdraw.ob->mode & OB_MODE_TEXTURE_PAINT) != 0); + bool texpaint = ((gtexdraw->ob->mode & OB_MODE_TEXTURE_PAINT) != 0); Image *ima = NULL; @@ -271,16 +273,18 @@ static bool set_draw_settings_cached(int clearcache, MTexPoly *texface, Material c_ma = NULL; } else { - textured = gtexdraw.is_tex; + textured = gtexdraw->is_tex; } /* convert number of lights into boolean */ - if (gtexdraw.is_lit) lit = 1; + if (gtexdraw->is_lit) { + lit = 1; + } - backculled = gtexdraw.use_backface_culling; + backculled = gtexdraw->use_backface_culling; if (ma) { if (ma->mode & MA_SHLESS) lit = 0; - if (gtexdraw.use_game_mat) { + if (gtexdraw->use_game_mat) { backculled = backculled || (ma->game.flag & GEMAT_BACKCULL); alphablend = ma->game.alpha_blend; } @@ -294,10 +298,10 @@ static bool set_draw_settings_cached(int clearcache, MTexPoly *texface, Material alphablend = GPU_BLEND_ALPHA; } else if (texpaint) { - if (gtexdraw.texpaint_material) + if (gtexdraw->texpaint_material) ima = ma && ma->texpaintslot ? ma->texpaintslot[ma->paint_active_slot].ima : NULL; else - ima = gtexdraw.canvas; + ima = gtexdraw->canvas; } else textured = 0; @@ -375,7 +379,7 @@ static bool set_draw_settings_cached(int clearcache, MTexPoly *texface, Material if (c_textured && !c_badtex) { options |= GPU_SHADER_TEXTURE_2D; } - if (gtexdraw.two_sided_lighting) { + if (gtexdraw->two_sided_lighting) { options |= GPU_SHADER_TWO_SIDED; } @@ -495,7 +499,7 @@ static void draw_textured_begin(Scene *scene, View3D *v3d, RegionView3D *rv3d, O Gtexdraw.two_sided_lighting = (me->flag & ME_TWOSIDED); memcpy(Gtexdraw.obcol, obcol, sizeof(obcol)); - set_draw_settings_cached(1, NULL, NULL, Gtexdraw); + set_draw_settings_cached(1, NULL, NULL, &Gtexdraw); glCullFace(GL_BACK); } @@ -553,7 +557,7 @@ static DMDrawOption draw_tface__set_draw_legacy(MTexPoly *mtexpoly, const bool h if (ma && (ma->game.flag & GEMAT_INVISIBLE)) return DM_DRAW_OPTION_SKIP; - invalidtexture = set_draw_settings_cached(0, mtexpoly, ma, Gtexdraw); + invalidtexture = set_draw_settings_cached(0, mtexpoly, ma, &Gtexdraw); if (mtexpoly && invalidtexture) { glColor3ub(0xFF, 0x00, 0xFF); @@ -594,7 +598,7 @@ static DMDrawOption draw_tface__set_draw(MTexPoly *mtexpoly, const bool UNUSED(h if (ma && (ma->game.flag & GEMAT_INVISIBLE)) return DM_DRAW_OPTION_SKIP; if (mtexpoly || Gtexdraw.is_texpaint) - set_draw_settings_cached(0, mtexpoly, ma, Gtexdraw); + set_draw_settings_cached(0, mtexpoly, ma, &Gtexdraw); /* always use color from mcol, as set in update_tface_color_layer */ return DM_DRAW_OPTION_NORMAL; @@ -664,7 +668,7 @@ static void update_tface_color_layer(DerivedMesh *dm, bool use_mcol) copy_mode = COPY_PREV; } } - else if (mtexpoly && set_draw_settings_cached(0, mtexpoly, ma, Gtexdraw)) { + else if (mtexpoly && set_draw_settings_cached(0, mtexpoly, ma, &Gtexdraw)) { int loop_index = mp->loopstart; for (j = 0; j < mp->totloop; j++, loop_index++) { finalCol[loop_index].r = 255; @@ -830,7 +834,7 @@ static void draw_mesh_text(Scene *scene, Object *ob, int glsl) } } else { - badtex = set_draw_settings_cached(0, mtpoly, mat, Gtexdraw); + badtex = set_draw_settings_cached(0, mtpoly, mat, &Gtexdraw); if (badtex) { continue; } diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 90f79f0ff69..b117a5e68d8 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -3079,7 +3079,9 @@ static int viewselected_exec(bContext *C, wmOperator *op) else if (ob && (ob->mode & OB_MODE_PARTICLE_EDIT)) { ok = PE_minmax(scene, min, max); } - else if (ob && (ob->mode & (OB_MODE_SCULPT | OB_MODE_TEXTURE_PAINT))) { + else if (ob && + (ob->mode & (OB_MODE_SCULPT | OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT))) + { BKE_paint_stroke_get_average(scene, ob, min); copy_v3_v3(max, min); ok = true; diff --git a/source/blender/editors/space_view3d/view3d_intern.h b/source/blender/editors/space_view3d/view3d_intern.h index 6d831c667a8..bdd2702a6ce 100644 --- a/source/blender/editors/space_view3d/view3d_intern.h +++ b/source/blender/editors/space_view3d/view3d_intern.h @@ -274,6 +274,7 @@ bool ED_view3d_minmax_verts(struct Object *obedit, float min[3], float max[3]); void VIEW3D_OT_snap_selected_to_grid(struct wmOperatorType *ot); void VIEW3D_OT_snap_selected_to_cursor(struct wmOperatorType *ot); +void VIEW3D_OT_snap_selected_to_active(struct wmOperatorType *ot); void VIEW3D_OT_snap_cursor_to_grid(struct wmOperatorType *ot); void VIEW3D_OT_snap_cursor_to_center(struct wmOperatorType *ot); void VIEW3D_OT_snap_cursor_to_selected(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_view3d/view3d_ops.c b/source/blender/editors/space_view3d/view3d_ops.c index 1c84ce3c985..b273f46fca3 100644 --- a/source/blender/editors/space_view3d/view3d_ops.c +++ b/source/blender/editors/space_view3d/view3d_ops.c @@ -214,6 +214,7 @@ void view3d_operatortypes(void) WM_operatortype_append(VIEW3D_OT_snap_selected_to_grid); WM_operatortype_append(VIEW3D_OT_snap_selected_to_cursor); + WM_operatortype_append(VIEW3D_OT_snap_selected_to_active); WM_operatortype_append(VIEW3D_OT_snap_cursor_to_grid); WM_operatortype_append(VIEW3D_OT_snap_cursor_to_center); WM_operatortype_append(VIEW3D_OT_snap_cursor_to_selected); diff --git a/source/blender/editors/space_view3d/view3d_project.c b/source/blender/editors/space_view3d/view3d_project.c index ac05853e6d0..7448d4c658e 100644 --- a/source/blender/editors/space_view3d/view3d_project.c +++ b/source/blender/editors/space_view3d/view3d_project.c @@ -312,25 +312,9 @@ static void view3d_win_to_ray_segment( if (!r_ray_co) r_ray_co = _ray_co; if (!r_ray_dir) r_ray_dir = _ray_dir; + ED_view3d_win_to_origin(ar, mval, r_ray_co); ED_view3d_win_to_vector(ar, mval, r_ray_dir); - if (rv3d->is_persp) { - copy_v3_v3(r_ray_co, rv3d->viewinv[3]); - } - else { - r_ray_co[0] = 2.0f * mval[0] / ar->winx - 1.0f; - r_ray_co[1] = 2.0f * mval[1] / ar->winy - 1.0f; - - if (rv3d->persp == RV3D_CAMOB) { - r_ray_co[2] = -1.0f; - } - else { - r_ray_co[2] = 0.0f; - } - - mul_project_m4_v3(rv3d->persinv, r_ray_co); - } - if ((rv3d->is_persp == false) && (rv3d->persp != RV3D_CAMOB)) { end_offset = v3d->far / 2.0f; start_offset = -end_offset; @@ -347,7 +331,7 @@ static void view3d_win_to_ray_segment( } } -BLI_INLINE bool view3d_clip_segment(const RegionView3D *rv3d, float ray_start[3], float ray_end[3]) +bool ED_view3d_clip_segment(const RegionView3D *rv3d, float ray_start[3], float ray_end[3]) { if ((rv3d->rflag & RV3D_CLIPPING) && (clip_segment_v3_plane_n(ray_start, ray_end, rv3d->clip, 6, @@ -384,7 +368,7 @@ bool ED_view3d_win_to_ray_ex( /* bounds clipping */ if (do_clip) { - return view3d_clip_segment(ar->regiondata, r_ray_start, ray_end); + return ED_view3d_clip_segment(ar->regiondata, r_ray_start, ray_end); } return true; @@ -549,6 +533,37 @@ void ED_view3d_win_to_delta(const ARegion *ar, const float mval[2], float out[3] } /** + * Calculate a 3d origin from 2d window coordinates. + * \note Orthographic views have a less obvious origin, + * Since far clip can be a very large value resulting in numeric precision issues, + * the origin in this case is close to zero coordinate. + * + * \param ar The region (used for the window width and height). + * \param mval The area relative 2d location (such as event->mval converted to floats). + * \param out The resulting normalized world-space direction vector. + */ +void ED_view3d_win_to_origin(const ARegion *ar, const float mval[2], float out[3]) +{ + RegionView3D *rv3d = ar->regiondata; + if (rv3d->is_persp) { + copy_v3_v3(out, rv3d->viewinv[3]); + } + else { + out[0] = 2.0f * mval[0] / ar->winx - 1.0f; + out[1] = 2.0f * mval[1] / ar->winy - 1.0f; + + if (rv3d->persp == RV3D_CAMOB) { + out[2] = -1.0f; + } + else { + out[2] = 0.0f; + } + + mul_project_m4_v3(rv3d->persinv, out); + } +} + +/** * Calculate a 3d direction vector from 2d window coordinates. * This direction vector starts and the view in the direction of the 2d window coordinates. * In orthographic view all window coordinates yield the same vector. @@ -599,7 +614,7 @@ bool ED_view3d_win_to_segment(const ARegion *ar, View3D *v3d, const float mval[2 /* bounds clipping */ if (do_clip) { - return view3d_clip_segment((RegionView3D *)ar->regiondata, r_ray_start, r_ray_end); + return ED_view3d_clip_segment((RegionView3D *)ar->regiondata, r_ray_start, r_ray_end); } return true; diff --git a/source/blender/editors/space_view3d/view3d_snap.c b/source/blender/editors/space_view3d/view3d_snap.c index e8e7d3c62fb..5dd69cc66eb 100644 --- a/source/blender/editors/space_view3d/view3d_snap.c +++ b/source/blender/editors/space_view3d/view3d_snap.c @@ -44,6 +44,7 @@ #include "BKE_main.h" #include "BKE_mball.h" #include "BKE_object.h" +#include "BKE_report.h" #include "BKE_tracking.h" #include "WM_api.h" @@ -204,7 +205,7 @@ void VIEW3D_OT_snap_selected_to_grid(wmOperatorType *ot) /* *************************************************** */ -static int snap_sel_to_curs_exec(bContext *C, wmOperator *op) +static int snap_selected_to_location(bContext *C, const float snap_target_global[3], const bool use_offset) { Scene *scene = CTX_data_scene(C); Object *obedit = CTX_data_edit_object(C); @@ -213,15 +214,10 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op) TransVertStore tvs = {NULL}; TransVert *tv; float imat[3][3], bmat[3][3]; - const float *cursor_global; float center_global[3]; float offset_global[3]; int a; - const bool use_offset = RNA_boolean_get(op->ptr, "use_offset"); - - cursor_global = ED_view3d_cursor3d_get(scene, v3d); - if (use_offset) { if ((v3d && v3d->around == V3D_AROUND_ACTIVE) && snap_calc_active_center(C, true, center_global)) @@ -231,11 +227,11 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op) else { snap_curs_to_sel_ex(C, center_global); } - sub_v3_v3v3(offset_global, cursor_global, center_global); + sub_v3_v3v3(offset_global, snap_target_global, center_global); } if (obedit) { - float cursor_local[3]; + float snap_target_local[3]; if (ED_transverts_check_obedit(obedit)) ED_transverts_create_from_obedit(&tvs, obedit, 0); @@ -246,8 +242,8 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op) invert_m3_m3(imat, bmat); /* get the cursor in object space */ - sub_v3_v3v3(cursor_local, cursor_global, obedit->obmat[3]); - mul_m3_v3(imat, cursor_local); + sub_v3_v3v3(snap_target_local, snap_target_global, obedit->obmat[3]); + mul_m3_v3(imat, snap_target_local); if (use_offset) { float offset_local[3]; @@ -262,7 +258,7 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op) else { tv = tvs.transverts; for (a = 0; a < tvs.transverts_tot; a++, tv++) { - copy_v3_v3(tv->loc, cursor_local); + copy_v3_v3(tv->loc, snap_target_local); } } @@ -274,10 +270,10 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op) bPoseChannel *pchan; bArmature *arm = obact->data; - float cursor_local[3]; + float snap_target_local[3]; invert_m4_m4(obact->imat, obact->obmat); - mul_v3_m4v3(cursor_local, obact->imat, cursor_global); + mul_v3_m4v3(snap_target_local, obact->imat, snap_target_global); for (pchan = obact->pose->chanbase.first; pchan; pchan = pchan->next) { if ((pchan->bone->flag & BONE_SELECTED) && @@ -311,7 +307,7 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op) BKE_armature_loc_pose_to_bone(pchan, cursor_pose, cursor_pose); } else { - BKE_armature_loc_pose_to_bone(pchan, cursor_local, cursor_pose); + BKE_armature_loc_pose_to_bone(pchan, snap_target_local, cursor_pose); } /* copy new position */ @@ -367,7 +363,7 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op) add_v3_v3v3(cursor_parent, ob->obmat[3], offset_global); } else { - copy_v3_v3(cursor_parent, cursor_global); + copy_v3_v3(cursor_parent, snap_target_global); } sub_v3_v3(cursor_parent, ob->obmat[3]); @@ -401,6 +397,18 @@ static int snap_sel_to_curs_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static int snap_selected_to_cursor_exec(bContext *C, wmOperator *op) +{ + const bool use_offset = RNA_boolean_get(op->ptr, "use_offset"); + + Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); + + const float *snap_target_global = ED_view3d_cursor3d_get(scene, v3d); + + return snap_selected_to_location(C, snap_target_global, use_offset); +} + void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot) { /* identifiers */ @@ -409,7 +417,7 @@ void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot) ot->idname = "VIEW3D_OT_snap_selected_to_cursor"; /* api callbacks */ - ot->exec = snap_sel_to_curs_exec; + ot->exec = snap_selected_to_cursor_exec; ot->poll = ED_operator_view3d_active; /* flags */ @@ -419,6 +427,34 @@ void VIEW3D_OT_snap_selected_to_cursor(wmOperatorType *ot) RNA_def_boolean(ot->srna, "use_offset", 1, "Offset", ""); } +static int snap_selected_to_active_exec(bContext *C, wmOperator *op) +{ + float snap_target_global[3]; + + if (snap_calc_active_center(C, false, snap_target_global) == false) { + BKE_report(op->reports, RPT_ERROR, "No active element found!"); + return OPERATOR_CANCELLED; + } + + return snap_selected_to_location(C, snap_target_global, false); +} + +void VIEW3D_OT_snap_selected_to_active(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Snap Selection to Active"; + ot->description = "Snap selected item(s) to the active item"; + ot->idname = "VIEW3D_OT_snap_selected_to_active"; + + /* api callbacks */ + ot->exec = snap_selected_to_active_exec; + ot->poll = ED_operator_view3d_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + + /* *************************************************** */ static int snap_curs_to_grid_exec(bContext *C, wmOperator *UNUSED(op)) diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index fc32613c1ab..b7456facbdf 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5273,13 +5273,9 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) skip_invert = true; if (skip_invert == false && constinv == false) { - if (constinv == false) - ob->transflag |= OB_NO_CONSTRAINTS; /* BKE_object_where_is_calc_time checks this */ - + ob->transflag |= OB_NO_CONSTRAINTS; /* BKE_object_where_is_calc_time checks this */ BKE_object_where_is_calc(t->scene, ob); - - if (constinv == false) - ob->transflag &= ~OB_NO_CONSTRAINTS; + ob->transflag &= ~OB_NO_CONSTRAINTS; } else BKE_object_where_is_calc(t->scene, ob); diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c index 59dfe18139a..1d4872cca7a 100644 --- a/source/blender/editors/transform/transform_snap_object.c +++ b/source/blender/editors/transform/transform_snap_object.c @@ -110,6 +110,12 @@ struct SnapObjectContext { }; +enum eViewProj { + VIEW_PROJ_NONE = -1, + VIEW_PROJ_ORTHO = 0, + VIEW_PROJ_PERSP = -1, +}; + static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt); @@ -137,10 +143,6 @@ struct RayCastAll_Data { Object *ob; unsigned int ob_uuid; - /* DerivedMesh only */ - DerivedMesh *dm; - const struct MLoopTri *dm_looptri; - /* output data */ ListBase *hit_list; bool retval; @@ -218,76 +220,177 @@ static void raycast_all_cb(void *userdata, int index, const BVHTreeRay *ray, BVH /* -------------------------------------------------------------------- */ -/** \name Internal Object Snapping API +/** \Common utilities * \{ */ + +/** + * Struct that kepts basic information about a BVHTree build from a editmesh. + */ +typedef struct BVHTreeFromMeshType { + void *userdata; + char type; +} BVHTreeFromMeshType; + +typedef struct PreDefProject { + float pmat[4][4]; /* perspective matrix multiplied by object matrix */ + float win_half[2]; + float dist_px_sq; +} PreDefProject; + +static void precalc_project( + PreDefProject *projectdefs, const ARegion *ar, + const float dist_px, float obmat[4][4]) +{ + float (*pmat)[4] = ((RegionView3D *)ar->regiondata)->persmat; + if (obmat) { + mul_m4_m4m4(projectdefs->pmat, pmat, obmat); + } + else { + copy_m4_m4(projectdefs->pmat, pmat); + } + projectdefs->win_half[0] = ar->winx / 2; + projectdefs->win_half[1] = ar->winy / 2; + projectdefs->dist_px_sq = SQUARE(dist_px); +} + +/** + * From a threshold (maximum distance to snap in pixels) returns: + * + * - The *real* distance (3D) if you are in orthographic-view. + * - The *tangent* (view cone radius at distance 1.0) if you are in perspective-view. + */ +static float dist_px_to_dist3d_or_tangent(const ARegion *ar, const float dist_px) +{ + const RegionView3D *rv3d = ar->regiondata; + if (ar->winx >= ar->winy) + return 2 * (dist_px / ar->winx) / rv3d->winmat[0][0]; + else + return 2 * (dist_px / ar->winy) / rv3d->winmat[1][1]; +} + +static const float *get_vert_co(const BVHTreeFromMeshType *meshdata, const int index) +{ + switch (meshdata->type) { + case SNAP_MESH: + { + BVHTreeFromMesh *data = meshdata->userdata; + const MVert *vert = data->vert; + return vert[index].co; + } + case SNAP_EDIT_MESH: + { + BVHTreeFromEditMesh *data = meshdata->userdata; + BMVert *eve = BM_vert_at_index(data->em->bm, index); + return eve->co; + } + } + return NULL; +} + +static void copy_vert_no(const BVHTreeFromMeshType *meshdata, const int index, float r_no[3]) +{ + switch (meshdata->type) { + case SNAP_MESH: + { + BVHTreeFromMesh *data = meshdata->userdata; + const MVert *vert = data->vert; + normal_short_to_float_v3(r_no, vert->no); + break; + } + case SNAP_EDIT_MESH: + { + BVHTreeFromEditMesh *data = meshdata->userdata; + BMVert *eve = BM_vert_at_index(data->em->bm, index); + copy_v3_v3(r_no, eve->no); + break; + } + } +} + +static void get_edge_verts( + const BVHTreeFromMeshType *meshdata, const int index, + const float *v_pair[2]) +{ + switch (meshdata->type) { + case SNAP_MESH: + { + BVHTreeFromMesh *data = meshdata->userdata; + + const MVert *vert = data->vert; + const MEdge *edge = data->edge + index; + + v_pair[0] = vert[edge->v1].co; + v_pair[1] = vert[edge->v2].co; + break; + } + case SNAP_EDIT_MESH: + { + BVHTreeFromEditMesh *data = meshdata->userdata; + BMEdge *eed = BM_edge_at_index(data->em->bm, index); + + v_pair[0] = eed->v1->co; + v_pair[1] = eed->v2->co; + break; + } + } +} + #define V3_MUL_ELEM(a, b) \ (a)[0] * (b)[0], \ (a)[1] * (b)[1], \ (a)[2] * (b)[2] -static bool test_vert( - const float vco[3], const float vno[3], const float ray_co[3], const float ray_dir[3], - const float ray_depth_range[2], const float scale[3], const bool is_persp, +static bool test_vert_dist( + const float vco[3], const float ray_co[3], const float ray_dir[3], + const float ray_depth_range[2], const float scale[3], /* read/write args */ float *ray_depth, float *dist_to_ray_sq, /* return args */ - float r_co[3], float r_no[3]) + float r_co[3]) { const float vco_sc[3] = {V3_MUL_ELEM(vco, scale)}; - const float co_sc[3] = {V3_MUL_ELEM(ray_co, scale)}; + const float origin_sc[3] = {V3_MUL_ELEM(ray_co, scale)}; const float dir_sc[3] = {V3_MUL_ELEM(ray_dir, scale)}; - float depth; - float dist_sq = dist_squared_to_ray_v3(co_sc, dir_sc, vco_sc, &depth); + float depth, dist_sq; + dist_sq = dist_squared_to_ray_v3(origin_sc, dir_sc, vco_sc, &depth); if (depth < ray_depth_range[0]) { return false; } - if (is_persp) { - dist_sq /= SQUARE(depth); - } - if ((dist_sq < *dist_to_ray_sq) && (depth < *ray_depth)) { *dist_to_ray_sq = dist_sq; copy_v3_v3(r_co, vco); - if (vno) { - copy_v3_v3(r_no, vno); - } - *ray_depth = depth; return true; } return false; } -static bool test_edge( +static bool test_edge_dist( const float v1[3], const float v2[3], const float ray_co[3], const float ray_dir[3], - const float ray_depth_range[2], const float scale[3], const bool is_persp, + const float ray_depth_range[2], const float scale[3], /* read/write args */ float *ray_depth, float *dist_to_ray_sq, /* return args */ - float r_co[3], float r_no[3]) + float r_co[3]) { const float v1_sc[3] = {V3_MUL_ELEM(v1, scale)}; const float v2_sc[3] = {V3_MUL_ELEM(v2, scale)}; const float co_sc[3] = {V3_MUL_ELEM(ray_co, scale)}; const float dir_sc[3] = {V3_MUL_ELEM(ray_dir, scale)}; - float tmp_co[3], depth; - float dist_sq = dist_squared_ray_to_seg_v3(co_sc, dir_sc, v1_sc, v2_sc, tmp_co, &depth); + float tmp_co[3], depth, dist_sq; + dist_sq = dist_squared_ray_to_seg_v3(co_sc, dir_sc, v1_sc, v2_sc, tmp_co, &depth); if (depth < ray_depth_range[0]) { return false; } - if (is_persp) { - dist_sq /= SQUARE(depth); - } - if ((dist_sq < *dist_to_ray_sq) && (depth < *ray_depth)) { *dist_to_ray_sq = dist_sq; @@ -297,10 +400,6 @@ static bool test_edge( copy_v3_v3(r_co, tmp_co); - if (r_no) { - sub_v3_v3v3(r_no, v1, v2); - } - *ray_depth = depth; return true; } @@ -309,50 +408,369 @@ static bool test_edge( #undef V3_MUL_ELEM +static bool test_projected_vert_dist( + PreDefProject *projectdefs, + const float co[3], const enum eViewProj view_proj, + const float mval[2], const float depth_range[2], + float r_co[3]) +{ + float depth; + float(*pmat)[4] = projectdefs->pmat; + if (view_proj == VIEW_PROJ_PERSP) { + depth = mul_project_m4_v3_zfac(pmat, co); + if (depth < depth_range[0] || depth > depth_range[1]) { + return false; + } + } + + float co2d[2] = { + (dot_m4_v3_row_x(pmat, co) + pmat[3][0]), + (dot_m4_v3_row_y(pmat, co) + pmat[3][1]), + }; + + if (view_proj == VIEW_PROJ_PERSP) { + mul_v2_fl(co2d, 1 / depth); + } + + co2d[0] += 1.0f; + co2d[1] += 1.0f; + co2d[0] *= projectdefs->win_half[0]; + co2d[1] *= projectdefs->win_half[1]; + + const float dist_sq = len_squared_v2v2(mval, co2d); + if (dist_sq < projectdefs->dist_px_sq) { + copy_v3_v3(r_co, co); + projectdefs->dist_px_sq = dist_sq; + return true; + } + return false; +} + +static bool test_projected_edge_dist( + PreDefProject *projectdefs, + const float va[3], const float vb[3], const float ray_start[3], const float ray_normal[3], + const enum eViewProj view_proj, const float mval[2], const float depth_range[2], + float r_co[3]) +{ + + float tmp_co[3], depth; + dist_squared_ray_to_seg_v3(ray_start, ray_normal, va, vb, tmp_co, &depth); + return test_projected_vert_dist(projectdefs, tmp_co, view_proj, mval, depth_range, r_co); +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \Walk DFS + * \{ */ +typedef struct Object_Nearest2dPrecalc { + float ray_origin_local[3]; + float ray_direction_local[3]; + float ray_inv_dir[3]; + + PreDefProject projectdefs; + float mval[2]; + bool sign[3]; + bool r_axis_closest[3]; + float depth_range[2]; + + void *userdata; + int index; + float co[3]; + float no[3]; +} Object_Nearest2dPrecalc; + + +static void nearest2d_precalc( + Object_Nearest2dPrecalc *neasrest_precalc, const ARegion *ar, + const float dist_px, float obmat[4][4], + const float ray_origin_local[3], const float ray_direction_local[3], + const float mval[2], const float depth_range[2]) +{ + precalc_project(&neasrest_precalc->projectdefs, ar, dist_px, obmat); + copy_v3_v3(neasrest_precalc->ray_origin_local, ray_origin_local); + copy_v3_v3(neasrest_precalc->ray_direction_local, ray_direction_local); + copy_v2_v2(neasrest_precalc->mval, mval); + copy_v2_v2(neasrest_precalc->depth_range, depth_range); + + for (int i = 0; i < 3; i++) { + neasrest_precalc->ray_inv_dir[i] = + (neasrest_precalc->ray_direction_local[i] != 0.0f) ? + (1.0f / neasrest_precalc->ray_direction_local[i]) : FLT_MAX; + neasrest_precalc->sign[i] = (neasrest_precalc->ray_inv_dir[i] < 0.0f); + neasrest_precalc->r_axis_closest[i] = true; + } +} + +static bool cb_walk_parent_snap_project(const BVHTreeAxisRange *bounds, void *user_data) +{ + Object_Nearest2dPrecalc *data = user_data; + float local_bvmin[3], local_bvmax[3]; + if (data->sign[0]) { + local_bvmin[0] = bounds[0].max; + local_bvmax[0] = bounds[0].min; + } + else { + local_bvmin[0] = bounds[0].min; + local_bvmax[0] = bounds[0].max; + } + if (data->sign[1]) { + local_bvmin[1] = bounds[1].max; + local_bvmax[1] = bounds[1].min; + } + else { + local_bvmin[1] = bounds[1].min; + local_bvmax[1] = bounds[1].max; + } + if (data->sign[2]) { + local_bvmin[2] = bounds[2].max; + local_bvmax[2] = bounds[2].min; + } + else { + local_bvmin[2] = bounds[2].min; + local_bvmax[2] = bounds[2].max; + } + + const float tmin[3] = { + (local_bvmin[0] - data->ray_origin_local[0]) * data->ray_inv_dir[0], + (local_bvmin[1] - data->ray_origin_local[1]) * data->ray_inv_dir[1], + (local_bvmin[2] - data->ray_origin_local[2]) * data->ray_inv_dir[2], + }; + const float tmax[3] = { + (local_bvmax[0] - data->ray_origin_local[0]) * data->ray_inv_dir[0], + (local_bvmax[1] - data->ray_origin_local[1]) * data->ray_inv_dir[1], + (local_bvmax[2] - data->ray_origin_local[2]) * data->ray_inv_dir[2], + }; + float va[3], vb[3]; + float rtmin, rtmax; + int main_axis; + + if ((tmax[0] <= tmax[1]) && (tmax[0] <= tmax[2])) { + rtmax = tmax[0]; + va[0] = vb[0] = local_bvmax[0]; + main_axis = 3; + data->r_axis_closest[0] = data->sign[0]; + } + else if ((tmax[1] <= tmax[0]) && (tmax[1] <= tmax[2])) { + rtmax = tmax[1]; + va[1] = vb[1] = local_bvmax[1]; + main_axis = 2; + data->r_axis_closest[1] = data->sign[1]; + } + else { + rtmax = tmax[2]; + va[2] = vb[2] = local_bvmax[2]; + main_axis = 1; + data->r_axis_closest[2] = data->sign[2]; + } + + if ((tmin[0] >= tmin[1]) && (tmin[0] >= tmin[2])) { + rtmin = tmin[0]; + va[0] = vb[0] = local_bvmin[0]; + main_axis -= 3; + data->r_axis_closest[0] = !data->sign[0]; + } + else if ((tmin[1] >= tmin[0]) && (tmin[1] >= tmin[2])) { + rtmin = tmin[1]; + va[1] = vb[1] = local_bvmin[1]; + main_axis -= 1; + data->r_axis_closest[1] = !data->sign[1]; + } + else { + rtmin = tmin[2]; + va[2] = vb[2] = local_bvmin[2]; + main_axis -= 2; + data->r_axis_closest[2] = !data->sign[2]; + } + if (main_axis < 0) { + main_axis += 3; + } + + /* if rtmin < rtmax, ray intersect `AABB` */ + if (rtmin <= rtmax) { +#ifdef IGNORE_BEHIND_RAY + /* `if rtmax < depth_min`, the whole `AABB` is behind us */ + if (rtmax < min_depth) { + return fallback; + } +#endif + const float proj = rtmin * data->ray_direction_local[main_axis]; + data->r_axis_closest[main_axis] = (proj - va[main_axis]) < (vb[main_axis] - proj); + return true; + } +#ifdef IGNORE_BEHIND_RAY + /* `if rtmin < depth_min`, the whole `AABB` is behing us */ + else if (rtmin < min_depth) { + return fallback; + } +#endif + if (data->sign[main_axis]) { + va[main_axis] = local_bvmax[main_axis]; + vb[main_axis] = local_bvmin[main_axis]; + } + else { + va[main_axis] = local_bvmin[main_axis]; + vb[main_axis] = local_bvmax[main_axis]; + } + float scale = fabsf(local_bvmax[main_axis] - local_bvmin[main_axis]); + + float (*pmat)[4] = data->projectdefs.pmat; + float depth_a = mul_project_m4_v3_zfac(pmat, va); + float depth_b = depth_a + pmat[main_axis][3] * scale; + + float va2d[2] = { + (dot_m4_v3_row_x(pmat, va) + pmat[3][0]), + (dot_m4_v3_row_y(pmat, va) + pmat[3][1]), + }; + float vb2d[2] = { + (va2d[0] + pmat[main_axis][0] * scale) / depth_b, + (va2d[1] + pmat[main_axis][1] * scale) / depth_b, + }; + + va2d[0] /= depth_a; + va2d[1] /= depth_a; + + va2d[0] += 1.0f; + va2d[1] += 1.0f; + vb2d[0] += 1.0f; + vb2d[1] += 1.0f; + + va2d[0] *= data->projectdefs.win_half[0]; + va2d[1] *= data->projectdefs.win_half[1]; + vb2d[0] *= data->projectdefs.win_half[0]; + vb2d[1] *= data->projectdefs.win_half[1]; + + //float dvec[2], edge[2], rdist; + //sub_v2_v2v2(dvec, data->mval, va2d); + //sub_v2_v2v2(edge, vb2d, va2d); + float rdist; + short dvec[2] = {data->mval[0] - va2d[0], data->mval[1] - va2d[1]}; + short edge[2] = {vb2d[0] - va2d[0], vb2d[1] - va2d[1]}; + float lambda = dvec[0] * edge[0] + dvec[1] * edge[1]; + if (lambda != 0.0f) { + lambda /= edge[0] * edge[0] + edge[1] * edge[1]; + if (lambda <= 0.0f) { + rdist = len_squared_v2v2(data->mval, va2d); + data->r_axis_closest[main_axis] = true; + } + else if (lambda >= 1.0f) { + rdist = len_squared_v2v2(data->mval, vb2d); + data->r_axis_closest[main_axis] = false; + } + else { + va2d[0] += edge[0] * lambda; + va2d[1] += edge[1] * lambda; + rdist = len_squared_v2v2(data->mval, va2d); + data->r_axis_closest[main_axis] = lambda < 0.5f; + } + } + else { + rdist = len_squared_v2v2(data->mval, va2d); + } + return rdist < data->projectdefs.dist_px_sq; +} + +static bool cb_walk_leaf_snap_vert(const BVHTreeAxisRange *bounds, int index, void *userdata) +{ + struct Object_Nearest2dPrecalc *neasrest_precalc = userdata; + const float co[3] = { + (bounds[0].min + bounds[0].max) / 2, + (bounds[1].min + bounds[1].max) / 2, + (bounds[2].min + bounds[2].max) / 2, + }; + + /* Currently the `BLI_bvhtree_walk_dfs` is being used only in the perspective view mode (VIEW_PROJ_PERSP) + * It could be used in orthographic view mode too (VIEW_PROJ_ORTHO), + * but in this case the `BLI_bvhtree_find_nearest_to_ray` is more efficient.*/ + if (test_projected_vert_dist( + &neasrest_precalc->projectdefs, co, VIEW_PROJ_PERSP, + neasrest_precalc->mval, neasrest_precalc->depth_range, + neasrest_precalc->co)) + { + copy_vert_no(neasrest_precalc->userdata, index, neasrest_precalc->no); + neasrest_precalc->index = index; + } + return true; +} + +static bool cb_walk_leaf_snap_edge(const BVHTreeAxisRange *UNUSED(bounds), int index, void *userdata) +{ + struct Object_Nearest2dPrecalc *neasrest_precalc = userdata; + + const float *v_pair[2]; + get_edge_verts(neasrest_precalc->userdata, index, v_pair); + + /* Currently the `BLI_bvhtree_walk_dfs` is being used only in the perspective view mode (VIEW_PROJ_PERSP) + * It could be used in orthographic view mode too (VIEW_PROJ_ORTHO), + * but in this case the `BLI_bvhtree_find_nearest_to_ray` is more efficient.*/ + if (test_projected_edge_dist( + &neasrest_precalc->projectdefs, v_pair[0], v_pair[1], + neasrest_precalc->ray_origin_local, neasrest_precalc->ray_direction_local, + VIEW_PROJ_PERSP, neasrest_precalc->mval, neasrest_precalc->depth_range, + neasrest_precalc->co)) + { + sub_v3_v3v3(neasrest_precalc->no, v_pair[0], v_pair[1]); + neasrest_precalc->index = index; + } + return true; +} + +static bool cb_nearest_walk_order(const BVHTreeAxisRange *UNUSED(bounds), char axis, void *userdata) +{ + const bool *r_axis_closest = ((struct Object_Nearest2dPrecalc *)userdata)->r_axis_closest; + return r_axis_closest[axis]; +} + +/** \} */ + +/* -------------------------------------------------------------------- */ + +/** \name Internal Object Snapping API + * \{ */ + static bool snapArmature( - Object *ob, bArmature *arm, float obmat[4][4], - const short snap_to, const bool is_persp, - const float ray_origin[3], const float ray_normal[3], const float ray_depth_range[2], + const ARegion *ar, Object *ob, bArmature *arm, float obmat[4][4], + const short snap_to, const float origin[3], const float dir[3], + const float mval[2], const enum eViewProj view_proj, const float depth_range[2], /* read/write args */ - float *ray_depth, float *dist_to_ray_sq, + float *dist_px, /* return args */ float r_loc[3], float *UNUSED(r_no)) { - float imat[4][4]; - float ray_origin_local[3], ray_normal_local[3]; bool retval = false; - invert_m4_m4(imat, obmat); + float ray_start_local[3], ray_normal_local[3]; + if (snap_to != SCE_SNAP_MODE_VERTEX) { + float imat[4][4]; + invert_m4_m4(imat, obmat); - mul_v3_m4v3(ray_origin_local, imat, ray_origin); - mul_v3_mat3_m4v3(ray_normal_local, imat, ray_normal); + copy_v3_v3(ray_start_local, origin); + copy_v3_v3(ray_normal_local, dir); + mul_m4_v3(imat, ray_start_local); + mul_mat3_m4_v3(imat, ray_normal_local); + } - float ob_scale[3]; - mat4_to_size(ob_scale, obmat); + PreDefProject projectdefs; + precalc_project(&projectdefs, ar, *dist_px, obmat); if (arm->edbo) { - EditBone *eBone; - - for (eBone = arm->edbo->first; eBone; eBone = eBone->next) { + for (EditBone *eBone = arm->edbo->first; eBone; eBone = eBone->next) { if (eBone->layer & arm->layer) { /* skip hidden or moving (selected) bones */ if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) { switch (snap_to) { case SCE_SNAP_MODE_VERTEX: - retval |= test_vert( - eBone->head, NULL, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); - retval |= test_vert( - eBone->tail, NULL, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); + retval |= test_projected_vert_dist( + &projectdefs, eBone->head, view_proj, mval, depth_range, r_loc); + retval |= test_projected_vert_dist( + &projectdefs, eBone->tail, view_proj, mval, depth_range, r_loc); break; case SCE_SNAP_MODE_EDGE: - retval |= test_edge( - eBone->head, eBone->tail, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); + retval |= test_projected_edge_dist( + &projectdefs, eBone->head, eBone->tail, ray_start_local, ray_normal_local, + view_proj, mval, depth_range, r_loc); break; } } @@ -360,11 +778,8 @@ static bool snapArmature( } } else if (ob->pose && ob->pose->chanbase.first) { - bPoseChannel *pchan; - Bone *bone; - - for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { - bone = pchan->bone; + for (bPoseChannel *pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { + Bone *bone = pchan->bone; /* skip hidden bones */ if (bone && !(bone->flag & (BONE_HIDDEN_P | BONE_HIDDEN_PG))) { const float *head_vec = pchan->pose_head; @@ -372,26 +787,22 @@ static bool snapArmature( switch (snap_to) { case SCE_SNAP_MODE_VERTEX: - retval |= test_vert( - head_vec, NULL, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); - retval |= test_vert( - tail_vec, NULL, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); + retval |= test_projected_vert_dist( + &projectdefs, head_vec, view_proj, mval, depth_range, r_loc); + retval |= test_projected_vert_dist( + &projectdefs, tail_vec, view_proj, mval, depth_range, r_loc); break; case SCE_SNAP_MODE_EDGE: - retval |= test_edge( - head_vec, tail_vec, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); + retval |= test_projected_edge_dist( + &projectdefs, head_vec, tail_vec, ray_start_local, ray_normal_local, + view_proj, mval, depth_range, r_loc); break; } } } } if (retval) { + *dist_px = sqrtf(projectdefs.dist_px_sq); mul_m4_v3(obmat, r_loc); return true; } @@ -399,39 +810,26 @@ static bool snapArmature( } static bool snapCurve( - Object *ob, Curve *cu, float obmat[4][4], - const short snap_to, const bool is_persp, - const float ray_origin[3], const float ray_normal[3], const float ray_depth_range[2], + const ARegion *ar, Object *ob, Curve *cu, float obmat[4][4], + const short snap_to, const float mval[2], const enum eViewProj view_proj, + const float depth_range[2], /* read/write args */ - float *ray_depth, float *dist_to_ray_sq, + float *dist_px, /* return args */ float r_loc[3], float *UNUSED(r_no)) { - float imat[4][4]; - float ray_origin_local[3], ray_normal_local[3]; bool retval = false; - int u; - - Nurb *nu; /* only vertex snapping mode (eg control points and handles) supported for now) */ if (snap_to != SCE_SNAP_MODE_VERTEX) { return retval; } - invert_m4_m4(imat, obmat); - - copy_v3_v3(ray_origin_local, ray_origin); - copy_v3_v3(ray_normal_local, ray_normal); - - mul_m4_v3(imat, ray_origin_local); - mul_mat3_m4_v3(imat, ray_normal_local); - - float ob_scale[3]; - mat4_to_size(ob_scale, obmat); + PreDefProject projectdefs; + precalc_project(&projectdefs, ar, *dist_px, obmat); - for (nu = (ob->mode == OB_MODE_EDIT ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) { - for (u = 0; u < nu->pntsu; u++) { + for (Nurb *nu = (ob->mode == OB_MODE_EDIT ? cu->editnurb->nurbs.first : cu->nurb.first); nu; nu = nu->next) { + for (int u = 0; u < nu->pntsu; u++) { switch (snap_to) { case SCE_SNAP_MODE_VERTEX: { @@ -441,26 +839,20 @@ static bool snapCurve( if (nu->bezt[u].f2 & SELECT || nu->bezt[u].hide != 0) { break; } - retval |= test_vert( - nu->bezt[u].vec[1], NULL, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); + retval |= test_projected_vert_dist( + &projectdefs, nu->bezt[u].vec[1], view_proj, mval, depth_range, r_loc); /* don't snap if handle is selected (moving), or if it is aligning to a moving handle */ if (!(nu->bezt[u].f1 & SELECT) && !(nu->bezt[u].h1 & HD_ALIGN && nu->bezt[u].f3 & SELECT)) { - retval |= test_vert( - nu->bezt[u].vec[0], NULL, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); + retval |= test_projected_vert_dist( + &projectdefs, nu->bezt[u].vec[0], view_proj, mval, depth_range, r_loc); } if (!(nu->bezt[u].f3 & SELECT) && !(nu->bezt[u].h2 & HD_ALIGN && nu->bezt[u].f1 & SELECT)) { - retval |= test_vert( - nu->bezt[u].vec[2], NULL, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); + retval |= test_projected_vert_dist( + &projectdefs, nu->bezt[u].vec[2], view_proj, mval, depth_range, r_loc); } } else { @@ -468,26 +860,20 @@ static bool snapCurve( if (nu->bp[u].f1 & SELECT || nu->bp[u].hide != 0) { break; } - retval |= test_vert( - nu->bp[u].vec, NULL, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); + retval |= test_projected_vert_dist( + &projectdefs, nu->bp[u].vec, view_proj, mval, depth_range, r_loc); } } else { /* curve is not visible outside editmode if nurb length less than two */ if (nu->pntsu > 1) { if (nu->bezt) { - retval |= test_vert( - nu->bezt[u].vec[1], NULL, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); + retval |= test_projected_vert_dist( + &projectdefs, nu->bezt[u].vec[1], view_proj, mval, depth_range, r_loc); } else { - retval |= test_vert( - nu->bp[u].vec, NULL, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); + retval |= test_projected_vert_dist( + &projectdefs, nu->bp[u].vec, view_proj, mval, depth_range, r_loc); } } } @@ -499,6 +885,7 @@ static bool snapCurve( } } if (retval) { + *dist_px = sqrtf(projectdefs.dist_px_sq); mul_m4_v3(obmat, r_loc); return true; } @@ -507,11 +894,11 @@ static bool snapCurve( /* may extend later (for now just snaps to empty center) */ static bool snapEmpty( - Object *ob, float obmat[4][4], - const short snap_to, const bool is_persp, - const float ray_origin[3], const float ray_normal[3], const float ray_depth_range[2], + const ARegion *ar, Object *ob, float obmat[4][4], + const short snap_to, const float mval[2], const enum eViewProj view_proj, + const float depth_range[2], /* read/write args */ - float *ray_depth, float *dist_to_ray_sq, + float *dist_px, /* return args */ float r_loc[3], float *UNUSED(r_no)) { @@ -520,17 +907,19 @@ static bool snapEmpty( if (ob->transflag & OB_DUPLI) { return retval; } + /* for now only vertex supported */ switch (snap_to) { case SCE_SNAP_MODE_VERTEX: { - float ob_loc[3], ob_scale[3] = {1.0, 1.0, 1.0}; - copy_v3_v3(ob_loc, obmat[3]); - - retval |= test_vert( - ob_loc, NULL, ray_origin, ray_normal, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); + PreDefProject projectdefs; + precalc_project(&projectdefs, ar, *dist_px, NULL); + float tmp_co[3]; + copy_v3_v3(tmp_co, obmat[3]); + if (test_projected_vert_dist(&projectdefs, tmp_co, view_proj, mval, depth_range, r_loc)) { + *dist_px = sqrtf(projectdefs.dist_px_sq); + retval = true; + } break; } default: @@ -541,19 +930,23 @@ static bool snapEmpty( } static bool snapCamera( - Scene *scene, Object *object, float obmat[4][4], - const short snap_to, const bool is_persp, - const float ray_origin[3], const float ray_normal[3], const float ray_depth_range[2], + const SnapObjectContext *sctx, Object *object, float obmat[4][4], + const short snap_to, const float mval[2], const enum eViewProj view_proj, + const float depth_range[2], /* read/write args */ - float *ray_depth, float *dist_to_ray_sq, + float *dist_px, /* return args */ float r_loc[3], float *UNUSED(r_no)) { + Scene *scene = sctx->scene; + + PreDefProject projectdefs; + precalc_project(&projectdefs, sctx->v3d_data.ar, *dist_px, NULL); + float orig_camera_mat[4][4], orig_camera_imat[4][4], imat[4][4]; bool retval = false; MovieClip *clip = BKE_object_movieclip_get(scene, object, false); MovieTracking *tracking; - float ray_origin_local[3], ray_normal_local[3]; if (clip == NULL) { return retval; @@ -584,9 +977,6 @@ static bool snapCamera( reconstructed_camera_imat[4][4]; float (*vertex_obmat)[4]; - copy_v3_v3(ray_origin_local, ray_origin); - copy_v3_v3(ray_normal_local, ray_normal); - if ((tracking_object->flag & TRACKING_OBJECT_CAMERA) == 0) { BKE_tracking_camera_get_reconstructed_interpolate(tracking, tracking_object, CFRA, reconstructed_camera_mat); @@ -603,26 +993,16 @@ static bool snapCamera( copy_v3_v3(bundle_pos, track->bundle_pos); if (tracking_object->flag & TRACKING_OBJECT_CAMERA) { - mul_m4_v3(orig_camera_imat, ray_origin_local); - mul_mat3_m4_v3(orig_camera_imat, ray_normal_local); vertex_obmat = orig_camera_mat; } else { mul_m4_v3(reconstructed_camera_imat, bundle_pos); - mul_m4_v3(imat, ray_origin_local); - mul_mat3_m4_v3(imat, ray_normal_local); vertex_obmat = obmat; } - float ob_scale[3]; - mat4_to_size(ob_scale, vertex_obmat); - - retval |= test_vert( - bundle_pos, NULL, ray_origin_local, ray_normal_local, - ray_depth_range, ob_scale, is_persp, ray_depth, dist_to_ray_sq, - r_loc, NULL); - - mul_m4_v3(vertex_obmat, r_loc); + mul_m4_v3(vertex_obmat, bundle_pos); + retval |= test_projected_vert_dist( + &projectdefs, bundle_pos, view_proj, mval, depth_range, r_loc); } } @@ -632,7 +1012,11 @@ static bool snapCamera( break; } - return retval; + if (retval) { + *dist_px = sqrtf(projectdefs.dist_px_sq); + return true; + } + return false; } static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt) @@ -643,44 +1027,45 @@ static int dm_looptri_to_poly_index(DerivedMesh *dm, const MLoopTri *lt) struct NearestDM_Data { void *bvhdata; - bool is_persp; - const float *ray_depth_range; - + const float *depth_range; float *ray_depth; }; -static void test_vert_depth_cb( +static void test_vert_ray_dist_cb( void *userdata, const float origin[3], const float dir[3], const float scale[3], int index, BVHTreeNearest *nearest) { struct NearestDM_Data *ndata = userdata; - const BVHTreeFromMesh *data = ndata->bvhdata; - const MVert *vert = data->vert + index; + const struct BVHTreeFromMeshType *data = ndata->bvhdata; + + const float *co = get_vert_co(data, index); - if (test_vert( - vert->co, NULL, origin, dir, ndata->ray_depth_range, scale, ndata->is_persp, - ndata->ray_depth, &nearest->dist_sq, - nearest->co, NULL)) + if (test_vert_dist( + co, origin, dir, ndata->depth_range, + scale, ndata->ray_depth, &nearest->dist_sq, + nearest->co)) { - normal_short_to_float_v3(nearest->no, vert->no); + copy_vert_no(data, index, nearest->no); nearest->index = index; } } -static void test_edge_depth_cb( +static void test_edge_ray_dist_cb( void *userdata, const float origin[3], const float dir[3], const float scale[3], int index, BVHTreeNearest *nearest) { struct NearestDM_Data *ndata = userdata; - const BVHTreeFromMesh *data = ndata->bvhdata; - const MVert *vert = data->vert; - const MEdge *edge = data->edge + index; - - if (test_edge( - vert[edge->v1].co, vert[edge->v2].co, origin, dir, ndata->ray_depth_range, scale, ndata->is_persp, - ndata->ray_depth, &nearest->dist_sq, - nearest->co, nearest->no)) + BVHTreeFromMeshType *data = ndata->bvhdata; + + const float *v_pair[2]; + get_edge_verts(data, index, v_pair); + + if (test_edge_dist( + v_pair[0], v_pair[1], origin, dir, ndata->depth_range, + scale, ndata->ray_depth, &nearest->dist_sq, + nearest->co)) { + sub_v3_v3v3(nearest->no, v_pair[0], v_pair[1]); nearest->index = index; } } @@ -688,10 +1073,11 @@ static void test_edge_depth_cb( static bool snapDerivedMesh( SnapObjectContext *sctx, Object *ob, DerivedMesh *dm, float obmat[4][4], const unsigned int ob_index, - const short snap_to, const bool is_persp, bool do_bb, - const float ray_origin[3], const float ray_start[3], const float ray_normal[3], const float ray_depth_range[2], + const short snap_to, const float mval[2], const enum eViewProj view_proj, bool do_bb, + const float ray_origin[3], const float ray_start[3], const float ray_normal[3], + const float depth_range[2], /* read/write args */ - float *ray_depth, float *dist_to_ray_sq, + float *ray_depth, float *dist_px, /* return args */ float r_loc[3], float r_no[3], int *r_index, ListBase *r_hit_list) @@ -703,7 +1089,7 @@ static bool snapDerivedMesh( return retval; } } - if (snap_to == SCE_SNAP_MODE_EDGE) { + else if (snap_to == SCE_SNAP_MODE_EDGE) { if (dm->getNumEdges(dm) == 0) { return retval; } @@ -715,7 +1101,7 @@ static bool snapDerivedMesh( } { - bool need_ray_start_correction_init = (snap_to == SCE_SNAP_MODE_FACE) && sctx->use_v3d && !is_persp; + bool need_ray_start_correction_init = (snap_to == SCE_SNAP_MODE_FACE) && (view_proj == VIEW_PROJ_ORTHO); float imat[4][4]; float timat[3][3]; /* transpose inverse matrix for normals */ @@ -823,28 +1209,30 @@ static bool snapDerivedMesh( } } + if (!treedata || !treedata->tree) { + return retval; + } + if (snap_to == SCE_SNAP_MODE_FACE) { /* Only use closer ray_start in case of ortho view! In perspective one, ray_start may already * been *inside* boundbox, leading to snap failures (see T38409). * Note also ar might be null (see T38435), in this case we assume ray_start is ok! */ - if (sctx->use_v3d && !is_persp) { /* do_ray_start_correction */ + if (view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */ if (need_ray_start_correction_init) { /* We *need* a reasonably valid len_diff in this case. * Use BHVTree to find the closest face from ray_start_local. */ - if (treedata && treedata->tree != NULL) { - BVHTreeNearest nearest; - nearest.index = -1; - nearest.dist_sq = FLT_MAX; - /* Compute and store result. */ - BLI_bvhtree_find_nearest( - treedata->tree, ray_start_local, &nearest, treedata->nearest_callback, treedata); - if (nearest.index != -1) { - float dvec[3]; - sub_v3_v3v3(dvec, nearest.co, ray_start_local); - len_diff = dot_v3v3(dvec, ray_normal_local); - } + BVHTreeNearest nearest; + nearest.index = -1; + nearest.dist_sq = FLT_MAX; + /* Compute and store result. */ + BLI_bvhtree_find_nearest( + treedata->tree, ray_start_local, &nearest, treedata->nearest_callback, treedata); + if (nearest.index != -1) { + float dvec[3]; + sub_v3_v3v3(dvec, nearest.co, ray_start_local); + len_diff = dot_v3v3(dvec, ray_normal_local); } } float ray_org_local[3]; @@ -856,8 +1244,8 @@ static bool snapDerivedMesh( * away ray_start values (as returned in case of ortho view3d), see T38358. */ len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ - madd_v3_v3v3fl(ray_start_local, ray_org_local, ray_normal_local, - len_diff + ray_depth_range[0]); + madd_v3_v3v3fl( + ray_start_local, ray_org_local, ray_normal_local, len_diff + depth_range[0] * local_scale); local_depth -= len_diff; } else { @@ -874,24 +1262,19 @@ static bool snapDerivedMesh( data.local_scale = local_scale; data.ob = ob; data.ob_uuid = ob_index; - data.dm = dm; data.hit_list = r_hit_list; data.retval = retval; BLI_bvhtree_ray_cast_all( - treedata->tree, ray_start_local, ray_normal_local, 0.0f, - *ray_depth, raycast_all_cb, &data); + treedata->tree, ray_start_local, ray_normal_local, 0.0f, + *ray_depth, raycast_all_cb, &data); retval = data.retval; } else { - BVHTreeRayHit hit; + BVHTreeRayHit hit = {.index = -1, .dist = local_depth}; - hit.index = -1; - hit.dist = local_depth; - - if (treedata->tree && - BLI_bvhtree_ray_cast( + if (BLI_bvhtree_ray_cast( treedata->tree, ray_start_local, ray_normal_local, 0.0f, &hit, treedata->raycast_callback, treedata) != -1) { @@ -900,12 +1283,15 @@ static bool snapDerivedMesh( if (hit.dist <= *ray_depth) { *ray_depth = hit.dist; copy_v3_v3(r_loc, hit.co); - copy_v3_v3(r_no, hit.no); /* back to worldspace */ mul_m4_v3(obmat, r_loc); - mul_m3_v3(timat, r_no); - normalize_v3(r_no); + + if (r_no) { + copy_v3_v3(r_no, hit.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); + } retval = true; @@ -917,51 +1303,78 @@ static bool snapDerivedMesh( } } else { - /* Vert & edge use nearly identical logic. */ - BLI_assert(ELEM(snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)); + const ARegion *ar = sctx->v3d_data.ar; float ray_org_local[3]; - copy_v3_v3(ray_org_local, ray_origin); mul_m4_v3(imat, ray_org_local); - BVHTreeNearest nearest; + BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_MESH}; - nearest.index = -1; - nearest.dist_sq = *dist_to_ray_sq; + if (view_proj == VIEW_PROJ_PERSP) { + Object_Nearest2dPrecalc neasrest_precalc; + neasrest_precalc.userdata = &treedata_type; + neasrest_precalc.index = -1; - struct NearestDM_Data userdata; - userdata.bvhdata = treedata; - userdata.is_persp = is_persp; - userdata.ray_depth_range = ray_depth_range; - userdata.ray_depth = ray_depth; + nearest2d_precalc(&neasrest_precalc, ar, *dist_px, obmat, + ray_org_local, ray_normal_local, mval, depth_range); - float ob_scale[3]; - mat4_to_size(ob_scale, obmat); + BVHTree_WalkLeafCallback cb_walk_leaf = + (snap_to == SCE_SNAP_MODE_VERTEX) ? + cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge; - BVHTree_NearestToRayCallback callback = - (snap_to == SCE_SNAP_MODE_VERTEX) ? - test_vert_depth_cb : test_edge_depth_cb; + BLI_bvhtree_walk_dfs( + treedata->tree, + cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest_precalc); - if (treedata->tree && - (is_persp ? - BLI_bvhtree_find_nearest_to_ray_angle( - treedata->tree, ray_org_local, ray_normal_local, - true, ob_scale, &nearest, callback, &userdata) : - BLI_bvhtree_find_nearest_to_ray( - treedata->tree, ray_org_local, ray_normal_local, - true, ob_scale, &nearest, callback, &userdata)) != -1) - { - copy_v3_v3(r_loc, nearest.co); - mul_m4_v3(obmat, r_loc); - if (r_no) { - copy_v3_v3(r_no, nearest.no); - mul_m3_v3(timat, r_no); - normalize_v3(r_no); + if (neasrest_precalc.index != -1) { + copy_v3_v3(r_loc, neasrest_precalc.co); + mul_m4_v3(obmat, r_loc); + if (r_no) { + copy_v3_v3(r_no, neasrest_precalc.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); + } + *dist_px = sqrtf(neasrest_precalc.projectdefs.dist_px_sq); + + retval = true; } - *dist_to_ray_sq = nearest.dist_sq; + } + else { + BVHTreeNearest nearest; - retval = true; + nearest.index = -1; + float dist_3d = dist_px_to_dist3d_or_tangent(ar, *dist_px); + nearest.dist_sq = SQUARE(dist_3d); + + + float ob_scale[3]; + mat4_to_size(ob_scale, obmat); + + struct NearestDM_Data userdata; + userdata.bvhdata = &treedata_type; + userdata.depth_range = depth_range; + userdata.ray_depth = ray_depth; + + BVHTree_NearestToRayCallback cb_test_ray_dist = + (snap_to == SCE_SNAP_MODE_VERTEX) ? + test_vert_ray_dist_cb : test_edge_ray_dist_cb; + + if (BLI_bvhtree_find_nearest_to_ray( + treedata->tree, ray_org_local, ray_normal_local, + true, ob_scale, &nearest, cb_test_ray_dist, &userdata) != -1) + { + copy_v3_v3(r_loc, nearest.co); + mul_m4_v3(obmat, r_loc); + if (r_no) { + copy_v3_v3(r_no, nearest.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); + } + *dist_px *= sqrtf(nearest.dist_sq) / dist_3d; + + retval = true; + } } } @@ -975,47 +1388,14 @@ static bool snapDerivedMesh( return retval; } -static void test_bmvert_depth_cb( - void *userdata, const float origin[3], const float dir[3], - const float scale[3], int index, BVHTreeNearest *nearest) -{ - struct NearestDM_Data *ndata = userdata; - const BMEditMesh *em = ndata->bvhdata; - BMVert *eve = BM_vert_at_index(em->bm, index); - - if (test_vert( - eve->co, eve->no, origin, dir, ndata->ray_depth_range, scale, ndata->is_persp, - ndata->ray_depth, &nearest->dist_sq, - nearest->co, nearest->no)) - { - nearest->index = index; - } -} - -static void test_bmedge_depth_cb( - void *userdata, const float origin[3], const float dir[3], - const float scale[3], int index, BVHTreeNearest *nearest) -{ - struct NearestDM_Data *ndata = userdata; - const BMEditMesh *em = ndata->bvhdata; - BMEdge *eed = BM_edge_at_index(em->bm, index); - - if (test_edge( - eed->v1->co, eed->v2->co, origin, dir, ndata->ray_depth_range, scale, ndata->is_persp, - ndata->ray_depth, &nearest->dist_sq, - nearest->co, nearest->no)) - { - nearest->index = index; - } -} - static bool snapEditMesh( SnapObjectContext *sctx, Object *ob, BMEditMesh *em, float obmat[4][4], const unsigned int ob_index, - const short snap_to, const bool is_persp, - const float ray_origin[3], const float ray_start[3], const float ray_normal[3], const float ray_depth_range[2], + const short snap_to, const float mval[2], const enum eViewProj view_proj, + const float ray_origin[3], const float ray_start[3], const float ray_normal[3], + const float depth_range[2], /* read/write args */ - float *ray_depth, float *dist_to_ray_sq, + float *ray_depth, float *dist_px, /* return args */ float r_loc[3], float r_no[3], int *r_index, ListBase *r_hit_list) @@ -1143,6 +1523,10 @@ static bool snapEditMesh( } } + if (!treedata || !treedata->tree) { + return retval; + } + if (snap_to == SCE_SNAP_MODE_FACE) { float ray_start_local[3]; copy_v3_v3(ray_start_local, ray_start); @@ -1160,35 +1544,33 @@ static bool snapEditMesh( * Note also ar might be null (see T38435), in this case we assume ray_start is ok! */ float len_diff = 0.0f; - if (sctx->use_v3d && !is_persp) { /* do_ray_start_correction */ + if (view_proj == VIEW_PROJ_ORTHO) { /* do_ray_start_correction */ /* We *need* a reasonably valid len_diff in this case. * Use BHVTree to find the closest face from ray_start_local. */ - if (treedata && treedata->tree != NULL) { - BVHTreeNearest nearest; - nearest.index = -1; - nearest.dist_sq = FLT_MAX; - /* Compute and store result. */ - if (BLI_bvhtree_find_nearest( - treedata->tree, ray_start_local, &nearest, NULL, NULL) != -1) - { - float dvec[3]; - sub_v3_v3v3(dvec, nearest.co, ray_start_local); - len_diff = dot_v3v3(dvec, ray_normal_local); - float ray_org_local[3]; - - copy_v3_v3(ray_org_local, ray_origin); - mul_m4_v3(imat, ray_org_local); - - /* We pass a temp ray_start, set from object's boundbox, - * to avoid precision issues with very far away ray_start values - * (as returned in case of ortho view3d), see T38358. - */ - len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ - madd_v3_v3v3fl(ray_start_local, ray_org_local, ray_normal_local, - len_diff + ray_depth_range[0]); - local_depth -= len_diff; - } + BVHTreeNearest nearest; + nearest.index = -1; + nearest.dist_sq = FLT_MAX; + /* Compute and store result. */ + if (BLI_bvhtree_find_nearest( + treedata->tree, ray_start_local, &nearest, NULL, NULL) != -1) + { + float dvec[3]; + sub_v3_v3v3(dvec, nearest.co, ray_start_local); + len_diff = dot_v3v3(dvec, ray_normal_local); + float ray_org_local[3]; + + copy_v3_v3(ray_org_local, ray_origin); + mul_m4_v3(imat, ray_org_local); + + /* We pass a temp ray_start, set from object's boundbox, + * to avoid precision issues with very far away ray_start values + * (as returned in case of ortho view3d), see T38358. + */ + len_diff -= local_scale; /* make temp start point a bit away from bbox hit point. */ + madd_v3_v3v3fl( + ray_start_local, ray_org_local, ray_normal_local, len_diff + depth_range[0] * local_scale); + local_depth -= len_diff; } } if (r_hit_list) { @@ -1202,7 +1584,6 @@ static bool snapEditMesh( data.local_scale = local_scale; data.ob = ob; data.ob_uuid = ob_index; - data.dm = NULL; data.hit_list = r_hit_list; data.retval = retval; @@ -1213,13 +1594,9 @@ static bool snapEditMesh( retval = data.retval; } else { - BVHTreeRayHit hit; + BVHTreeRayHit hit = {.index = -1, .dist = local_depth}; - hit.index = -1; - hit.dist = local_depth; - - if (treedata->tree && - BLI_bvhtree_ray_cast( + if (BLI_bvhtree_ray_cast( treedata->tree, ray_start_local, ray_normal_local, 0.0f, &hit, treedata->raycast_callback, treedata) != -1) { @@ -1228,12 +1605,15 @@ static bool snapEditMesh( if (hit.dist <= *ray_depth) { *ray_depth = hit.dist; copy_v3_v3(r_loc, hit.co); - copy_v3_v3(r_no, hit.no); /* back to worldspace */ mul_m4_v3(obmat, r_loc); - mul_m3_v3(timat, r_no); - normalize_v3(r_no); + + if (r_no) { + copy_v3_v3(r_no, hit.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); + } retval = true; @@ -1245,51 +1625,78 @@ static bool snapEditMesh( } } else { - /* Vert & edge use nearly identical logic. */ - BLI_assert(ELEM(snap_to, SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE)); + const ARegion *ar = sctx->v3d_data.ar; float ray_org_local[3]; - copy_v3_v3(ray_org_local, ray_origin); mul_m4_v3(imat, ray_org_local); - BVHTreeNearest nearest; + BVHTreeFromMeshType treedata_type = {.userdata = treedata, .type = SNAP_EDIT_MESH}; - nearest.index = -1; - nearest.dist_sq = *dist_to_ray_sq; + if (view_proj == VIEW_PROJ_PERSP) { + Object_Nearest2dPrecalc neasrest_precalc; + neasrest_precalc.userdata = &treedata_type; + neasrest_precalc.index = -1; - struct NearestDM_Data userdata; - userdata.bvhdata = em; - userdata.is_persp = is_persp; - userdata.ray_depth_range = ray_depth_range; - userdata.ray_depth = ray_depth; + nearest2d_precalc(&neasrest_precalc, ar, *dist_px, obmat, + ray_org_local, ray_normal_local, mval, depth_range); - float ob_scale[3]; - mat4_to_size(ob_scale, obmat); + BVHTree_WalkLeafCallback cb_walk_leaf = + (snap_to == SCE_SNAP_MODE_VERTEX) ? + cb_walk_leaf_snap_vert : cb_walk_leaf_snap_edge; - BVHTree_NearestToRayCallback callback = - (snap_to == SCE_SNAP_MODE_VERTEX) ? - test_bmvert_depth_cb : test_bmedge_depth_cb; + BLI_bvhtree_walk_dfs( + treedata->tree, + cb_walk_parent_snap_project, cb_walk_leaf, cb_nearest_walk_order, &neasrest_precalc); - if (treedata->tree && - (is_persp ? - BLI_bvhtree_find_nearest_to_ray_angle( - treedata->tree, ray_org_local, ray_normal_local, - false, ob_scale, &nearest, callback, &userdata) : - BLI_bvhtree_find_nearest_to_ray( - treedata->tree, ray_org_local, ray_normal_local, - false, ob_scale, &nearest, callback, &userdata)) != -1) - { - copy_v3_v3(r_loc, nearest.co); - mul_m4_v3(obmat, r_loc); - if (r_no) { - copy_v3_v3(r_no, nearest.no); - mul_m3_v3(timat, r_no); - normalize_v3(r_no); + if (neasrest_precalc.index != -1) { + copy_v3_v3(r_loc, neasrest_precalc.co); + mul_m4_v3(obmat, r_loc); + if (r_no) { + copy_v3_v3(r_no, neasrest_precalc.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); + } + *dist_px = sqrtf(neasrest_precalc.projectdefs.dist_px_sq); + + retval = true; } - *dist_to_ray_sq = nearest.dist_sq; + } + else { + BVHTreeNearest nearest; - retval = true; + nearest.index = -1; + float dist_3d = dist_px_to_dist3d_or_tangent(ar, *dist_px); + nearest.dist_sq = SQUARE(dist_3d); + + + float ob_scale[3]; + mat4_to_size(ob_scale, obmat); + + struct NearestDM_Data userdata; + userdata.bvhdata = &treedata_type; + userdata.depth_range = depth_range; + userdata.ray_depth = ray_depth; + + BVHTree_NearestToRayCallback cb_test_ray_dist = + (snap_to == SCE_SNAP_MODE_VERTEX) ? + test_vert_ray_dist_cb : test_edge_ray_dist_cb; + + if (BLI_bvhtree_find_nearest_to_ray( + treedata->tree, ray_org_local, ray_normal_local, + false, ob_scale, &nearest, cb_test_ray_dist, &userdata) != -1) + { + copy_v3_v3(r_loc, nearest.co); + mul_m4_v3(obmat, r_loc); + if (r_no) { + copy_v3_v3(r_no, nearest.no); + mul_m3_v3(timat, r_no); + normalize_v3(r_no); + } + *dist_px *= sqrtf(nearest.dist_sq) / dist_3d; + + retval = true; + } } } @@ -1305,26 +1712,28 @@ static bool snapEditMesh( /** * \param use_obedit: Uses the coordinates of BMesh (if any) to do the snapping; - * \param ray_depth_range: - * - 0: distance from the ray_origin to the clipping plane min (can be negative). - * - 1: maximum distance, elements outside this are ignored. - * \param ray_depth: maximum depth allowed for r_co. * * \note Duplicate args here are documented at #snapObjectsRay */ static bool snapObject( SnapObjectContext *sctx, Object *ob, float obmat[4][4], const unsigned int ob_index, - bool use_obedit, const short snap_to, - const float ray_origin[3], const float ray_start[3], const float ray_normal[3], const float ray_depth_range[2], + bool use_obedit, const short snap_to, const float mval[2], + const float ray_origin[3], const float ray_start[3], const float ray_normal[3], + const float depth_range[2], /* read/write args */ - float *ray_depth, float *dist_to_ray_sq, + float *ray_depth, float *dist_px, /* return args */ float r_loc[3], float r_no[3], int *r_index, Object **r_ob, float r_obmat[4][4], ListBase *r_hit_list) { - const bool is_persp = sctx->use_v3d && ((RegionView3D *)sctx->v3d_data.ar->regiondata)->is_persp; + const enum eViewProj view_proj = + ((sctx->use_v3d == false) || (mval == NULL)) ? VIEW_PROJ_NONE : + (((RegionView3D *)sctx->v3d_data.ar->regiondata)->is_persp ? VIEW_PROJ_PERSP : VIEW_PROJ_ORTHO); + + const ARegion *ar = sctx->v3d_data.ar; + bool retval = false; if (ob->type == OB_MESH) { @@ -1334,9 +1743,9 @@ static bool snapObject( em = BKE_editmesh_from_object(ob); retval = snapEditMesh( sctx, ob, em, obmat, ob_index, - snap_to, is_persp, - ray_origin, ray_start, ray_normal, ray_depth_range, - ray_depth, dist_to_ray_sq, + snap_to, mval, view_proj, + ray_origin, ray_start, ray_normal, depth_range, + ray_depth, dist_px, r_loc, r_no, r_index, r_hit_list); } @@ -1353,42 +1762,43 @@ static bool snapObject( } retval = snapDerivedMesh( sctx, ob, dm, obmat, ob_index, - snap_to, is_persp, true, - ray_origin, ray_start, ray_normal, ray_depth_range, - ray_depth, dist_to_ray_sq, + snap_to, mval, view_proj, true, + ray_origin, ray_start, ray_normal, depth_range, + ray_depth, dist_px, r_loc, r_no, r_index, r_hit_list); dm->release(dm); } } - else if (ob->type == OB_ARMATURE) { - retval = snapArmature( - ob, ob->data, obmat, snap_to, is_persp, - ray_origin, ray_normal, ray_depth_range, - ray_depth, dist_to_ray_sq, - r_loc, r_no); - } - else if (ob->type == OB_CURVE) { - retval = snapCurve( - ob, ob->data, obmat, snap_to, is_persp, - ray_origin, ray_normal, ray_depth_range, - ray_depth, dist_to_ray_sq, - r_loc, r_no); - } - else if (ob->type == OB_EMPTY) { - retval = snapEmpty( - ob, obmat, snap_to, is_persp, - ray_origin, ray_normal, ray_depth_range, - ray_depth, dist_to_ray_sq, - r_loc, r_no); - } - else if (ob->type == OB_CAMERA) { - retval = snapCamera( - sctx->scene, ob, obmat, snap_to, is_persp, - ray_origin, ray_normal, ray_depth_range, - ray_depth, dist_to_ray_sq, - r_loc, r_no); + else if (snap_to != SCE_SNAP_MODE_FACE) { + if (ob->type == OB_ARMATURE) { + retval = snapArmature( + ar, ob, ob->data, obmat, snap_to, ray_origin, ray_normal, + mval, view_proj, depth_range, dist_px, + r_loc, r_no); + } + else if (ob->type == OB_CURVE) { + retval = snapCurve( + ar, ob, ob->data, obmat, snap_to, mval, view_proj, + depth_range, + dist_px, + r_loc, r_no); + } + else if (ob->type == OB_EMPTY) { + retval = snapEmpty( + ar, ob, obmat, snap_to, mval, view_proj, + depth_range, + dist_px, + r_loc, r_no); + } + else if (ob->type == OB_CAMERA) { + retval = snapCamera( + sctx, ob, obmat, snap_to, mval, view_proj, + depth_range, + dist_px, + r_loc, r_no); + } } if (retval) { @@ -1414,16 +1824,18 @@ static bool snapObject( * \param snap_select: from enum SnapSelect. * * \param use_object_edit_cage: Uses the coordinates of BMesh (if any) to do the snapping. + * \param mval: Mouse coords. + * When NULL, ray-casting is handled without any projection matrix correction. * \param ray_origin: ray_start before being moved toward the ray_normal at the distance from vew3d clip_min. * \param ray_start: ray_origin moved for the start clipping plane (clip_min). * \param ray_normal: Unit length direction of the ray. + * \param depth_range: distances of clipe plane min and clip plane max; * * Read/Write Args * --------------- * * \param ray_depth: maximum depth allowed for r_co, elements deeper than this value will be ignored. - * \param dist_to_ray_sq: Real distance (3D) or Tangent (view cone radius at distance 1.0) squared. - * resulting of the function #dist_px_to_dist3d_or_tangent. + * \param dist_px: Maximum threshold distance (in pixels). * * Output Args * ----------- @@ -1440,10 +1852,11 @@ static bool snapObject( static bool snapObjectsRay( SnapObjectContext *sctx, const unsigned short snap_to, const SnapSelect snap_select, - const bool use_object_edit_cage, + const bool use_object_edit_cage, const float mval[2], const float ray_origin[3], const float ray_start[3], const float ray_normal[3], + const float depth_range[2], /* read/write args */ - float *ray_depth, float *dist_to_ray_sq, + float *ray_depth, float *dist_px, /* return args */ float r_loc[3], float r_no[3], int *r_index, Object **r_ob, float r_obmat[4][4], @@ -1451,14 +1864,6 @@ static bool snapObjectsRay( { bool retval = false; - float dvec[3]; - sub_v3_v3v3(dvec, ray_start, ray_origin); - - const float ray_depth_range[2] = { - dot_v3v3(dvec, ray_normal), - *ray_depth, - }; - unsigned int ob_index = 0; Object *obedit = use_object_edit_cage ? sctx->scene->obedit : NULL; @@ -1473,9 +1878,9 @@ static bool snapObjectsRay( retval |= snapObject( sctx, ob, ob->obmat, ob_index++, - false, snap_to, - ray_origin, ray_start, ray_normal, ray_depth_range, - ray_depth, dist_to_ray_sq, + false, snap_to, mval, + ray_origin, ray_start, ray_normal, depth_range, + ray_depth, dist_px, r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list); } @@ -1509,9 +1914,9 @@ static bool snapObjectsRay( retval |= snapObject( sctx, dupli_snap, dupli_ob->mat, ob_index++, - use_obedit_dupli, snap_to, - ray_origin, ray_start, ray_normal, ray_depth_range, - ray_depth, dist_to_ray_sq, + use_obedit_dupli, snap_to, mval, + ray_origin, ray_start, ray_normal, depth_range, + ray_depth, dist_px, r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list); } @@ -1523,9 +1928,9 @@ static bool snapObjectsRay( retval |= snapObject( sctx, ob_snap, ob->obmat, ob_index++, - use_obedit, snap_to, - ray_origin, ray_start, ray_normal, ray_depth_range, - ray_depth, dist_to_ray_sq, + use_obedit, snap_to, mval, + ray_origin, ray_start, ray_normal, depth_range, + ray_depth, dist_px, r_loc, r_no, r_index, r_ob, r_obmat, r_hit_list); } } @@ -1632,13 +2037,12 @@ bool ED_transform_snap_object_project_ray_ex( float r_loc[3], float r_no[3], int *r_index, Object **r_ob, float r_obmat[4][4]) { - float dist_to_ray_sq = 0.0f; - + const float depth_range[2] = {0.0f, FLT_MAX}; return snapObjectsRay( sctx, - snap_to, params->snap_select, params->use_object_edit_cage, - ray_start, ray_start, ray_normal, - ray_depth, &dist_to_ray_sq, + snap_to, params->snap_select, params->use_object_edit_cage, NULL, + ray_start, ray_start, ray_normal, depth_range, + ray_depth, NULL, r_loc, r_no, r_index, r_ob, r_obmat, NULL); } @@ -1657,8 +2061,7 @@ bool ED_transform_snap_object_project_ray_all( float ray_depth, bool sort, ListBase *r_hit_list) { - float dist_to_ray_sq = 0.0f; - + const float depth_range[2] = {0.0f, FLT_MAX}; if (ray_depth == -1.0f) { ray_depth = BVH_RAYCAST_DIST_MAX; } @@ -1669,9 +2072,9 @@ bool ED_transform_snap_object_project_ray_all( bool retval = snapObjectsRay( sctx, - snap_to, params->snap_select, params->use_object_edit_cage, - ray_start, ray_start, ray_normal, - &ray_depth, &dist_to_ray_sq, + snap_to, params->snap_select, params->use_object_edit_cage, NULL, + ray_start, ray_start, ray_normal, depth_range, + &ray_depth, NULL, NULL, NULL, NULL, NULL, NULL, r_hit_list); @@ -1726,11 +2129,6 @@ bool ED_transform_snap_object_project_ray( ray_depth = &ray_depth_fallback; } - float no_fallback[3]; - if (r_no == NULL) { - r_no = no_fallback; - } - return transform_snap_context_project_ray_impl( sctx, params, @@ -1749,11 +2147,6 @@ static bool transform_snap_context_project_view3d_mixed_impl( float ray_depth = BVH_RAYCAST_DIST_MAX; bool is_hit = false; - float r_no_dummy[3]; - if (r_no == NULL) { - r_no = r_no_dummy; - } - const int elem_type[3] = {SCE_SNAP_MODE_VERTEX, SCE_SNAP_MODE_EDGE, SCE_SNAP_MODE_FACE}; BLI_assert(snap_to_flag != 0); @@ -1780,21 +2173,6 @@ static bool transform_snap_context_project_view3d_mixed_impl( } /** - * From a threshold (maximum distance to snap in pixels) returns: - * - * - The *real* distance (3D) if you are in orthographic-view. - * - The *tangent* (view cone radius at distance 1.0) if you are in perspective-view. - */ -static float dist_px_to_dist3d_or_tangent(const ARegion *ar, const float dist_px) -{ - const RegionView3D *rv3d = ar->regiondata; - if (ar->winx >= ar->winy) - return 2 * (dist_px / ar->winx) / rv3d->winmat[0][0]; - else - return 2 * (dist_px / ar->winy) / rv3d->winmat[1][1]; -} - -/** * Convenience function for performing snapping. * * Given a 2D region value, snap to vert/edge/face. @@ -1830,55 +2208,37 @@ bool ED_transform_snap_object_project_view3d_ex( float *ray_depth, float r_loc[3], float r_no[3], int *r_index) { - float ray_start[3], ray_normal[3], ray_origin[3]; + float ray_origin[3], ray_start[3], ray_normal[3], depth_range[2], ray_end[3]; - float ray_depth_fallback; - if (ray_depth == NULL) { - ray_depth_fallback = BVH_RAYCAST_DIST_MAX; - ray_depth = &ray_depth_fallback; - } + const ARegion *ar = sctx->v3d_data.ar; + const RegionView3D *rv3d = ar->regiondata; - if (!ED_view3d_win_to_ray_ex( - sctx->v3d_data.ar, sctx->v3d_data.v3d, - mval, ray_origin, ray_normal, ray_start, true)) - { + ED_view3d_win_to_origin(ar, mval, ray_origin); + ED_view3d_win_to_vector(ar, mval, ray_normal); + + ED_view3d_clip_range_get( + sctx->v3d_data.v3d, sctx->v3d_data.ar->regiondata, + &depth_range[0], &depth_range[1], false); + + madd_v3_v3v3fl(ray_start, ray_origin, ray_normal, depth_range[0]); + madd_v3_v3v3fl(ray_end, ray_origin, ray_normal, depth_range[1]); + + if (!ED_view3d_clip_segment(rv3d, ray_start, ray_end)) { return false; } - float radius, dist_to_ray_sq = 0.0f; - if (dist_px) { - radius = dist_px_to_dist3d_or_tangent(sctx->v3d_data.ar, *dist_px); - /** - * Workaround to use of cone (Instead of project the radius on view plane): - * In perspective view, the radius of the cone may decrease depending on the ray direction. - * This is more evident with small values of the `Viewport lens angle`. - * The threshold becomes distorted that way. - */ - RegionView3D *rv3d = sctx->v3d_data.ar->regiondata; - if (rv3d->is_persp) { - float view_dir[3]; - negate_v3_v3(view_dir, rv3d->viewinv[2]); - normalize_v3(view_dir); - radius *= dot_v3v3(ray_normal, view_dir); - } - - dist_to_ray_sq = SQUARE(radius); + float ray_depth_fallback; + if (ray_depth == NULL) { + ray_depth_fallback = BVH_RAYCAST_DIST_MAX; + ray_depth = &ray_depth_fallback; } - if (snapObjectsRay( + return snapObjectsRay( sctx, snap_to, params->snap_select, params->use_object_edit_cage, - ray_origin, ray_start, ray_normal, - ray_depth, &dist_to_ray_sq, - r_loc, r_no, r_index, NULL, NULL, NULL)) - { - if (dist_px) { - *dist_px *= sqrtf(dist_to_ray_sq) / radius; - } - return true; - } - - return false; + mval, ray_origin, ray_start, ray_normal, depth_range, + ray_depth, dist_px, + r_loc, r_no, r_index, NULL, NULL, NULL); } bool ED_transform_snap_object_project_view3d( diff --git a/source/blender/freestyle/intern/stroke/Curve.cpp b/source/blender/freestyle/intern/stroke/Curve.cpp index 69c5dcdfe28..a8dbce84971 100644 --- a/source/blender/freestyle/intern/stroke/Curve.cpp +++ b/source/blender/freestyle/intern/stroke/Curve.cpp @@ -133,7 +133,7 @@ iA_B_eq_iB_A: //_t2d = t3; _t2d = t2 * t3; } - else if ((iA->getPoint2D() - iA->getPoint2D()).norm() < 1.0e-6) { + else if ((iA->getPoint2D() - iB->getPoint2D()).norm() < 1.0e-6) { __A = iB->A(); __B = iB->B(); //_t2d = t3; diff --git a/source/blender/freestyle/intern/view_map/Functions1D.cpp b/source/blender/freestyle/intern/view_map/Functions1D.cpp index 11e0cc37d4d..8f16f78cb10 100644 --- a/source/blender/freestyle/intern/view_map/Functions1D.cpp +++ b/source/blender/freestyle/intern/view_map/Functions1D.cpp @@ -104,7 +104,7 @@ int QuantitativeInvisibilityF1D::operator()(Interface1D& inter) } FEdge *fe = dynamic_cast<FEdge*>(&inter); if (fe) { - result = ve->qi(); + result = fe->qi(); return 0; } result = integrate(_func, inter.verticesBegin(), inter.verticesEnd(), _integration); diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c index c663af0ccbb..370841327aa 100644 --- a/source/blender/gpu/intern/gpu_buffers.c +++ b/source/blender/gpu/intern/gpu_buffers.c @@ -916,7 +916,7 @@ void GPU_buffer_unlock(GPUBuffer *UNUSED(buffer), GPUBindingType binding) { int bindtypegl = gpu_binding_type_gl[binding]; /* note: this operation can fail, could return - * an error code from this function? */ + * an error code from this function? */ glUnmapBuffer(bindtypegl); glBindBuffer(bindtypegl, 0); } diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index 3c028ff0805..aec94f9f2cb 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -853,11 +853,14 @@ static char *code_generate_geometry(ListBase *nodes, bool use_opensubdiv) for (input = node->inputs.first; input; input = input->next) { if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) { if (input->attribtype == CD_MTFACE) { + /* NOTE: For now we are using varying on purpose, + * otherwise we are not able to write to the varying. + */ BLI_dynstr_appendf(ds, "%s %s var%d%s;\n", - GLEW_VERSION_3_0 ? "in" : "varying", + "varying", GPU_DATATYPE_STR[input->type], input->attribid, - GLEW_VERSION_3_0 ? "[]" : ""); + ""); BLI_dynstr_appendf(ds, "uniform int fvar%d_offset;\n", input->attribid); } @@ -868,22 +871,20 @@ static char *code_generate_geometry(ListBase *nodes, bool use_opensubdiv) BLI_dynstr_append(ds, datatoc_gpu_shader_geometry_glsl); /* Generate varying assignments. */ - /* TODO(sergey): Disabled for now, needs revisit. */ -#if 0 for (node = nodes->first; node; node = node->next) { for (input = node->inputs.first; input; input = input->next) { if (input->source == GPU_SOURCE_ATTRIB && input->attribfirst) { if (input->attribtype == CD_MTFACE) { - BLI_dynstr_appendf(ds, - "\tINTERP_FACE_VARYING_2(var%d, " - "fvar%d_offset, st);\n", - input->attribid, - input->attribid); + BLI_dynstr_appendf( + ds, + "\tINTERP_FACE_VARYING_2(var%d, " + "int(texelFetch(FVarDataOffsetBuffer, fvar%d_offset).r), st);\n", + input->attribid, + input->attribid); } } } } -#endif BLI_dynstr_append(ds, "}\n"); code = BLI_dynstr_get_cstring(ds); diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index 064e91743e8..7936811ab4d 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -803,7 +803,7 @@ static void **gpu_gen_cube_map(unsigned int *rect, float *frect, int rectw, int * | | | | * | NegZ | PosZ | PosY | * |______|______|______| - */ + */ if (use_high_bit_depth) { float (*frectb)[4] = (float(*)[4])frect; float (**fsides)[4] = (float(**)[4])sides; diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index b8a39c81122..d41573b681b 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -77,9 +77,10 @@ static struct GPUGlobal { GPUDeviceType device; GPUOSType os; GPUDriverType driver; - float dfdyfactors[2]; /* workaround for different calculation of dfdy factors on GPUs. Some GPUs/drivers - calculate dfdy in shader differently when drawing to an offscreen buffer. First - number is factor on screen and second is off-screen */ + /* workaround for different calculation of dfdy factors on GPUs. Some GPUs/drivers + * calculate dfdy in shader differently when drawing to an offscreen buffer. First + * number is factor on screen and second is off-screen */ + float dfdyfactors[2]; float max_anisotropy; } GG = {1, 0}; diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 0f95107c018..4775d2ed30a 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -1745,8 +1745,7 @@ void GPU_shaderesult_set(GPUShadeInput *shi, GPUShadeResult *shr) (GPU_link_changed(shi->refl) || ma->ref != 0.0f)) { if (world->aocolor != WO_AOPLAIN) { - if (!(is_zero_v3(&world->horr) & is_zero_v3(&world->zenr))) - { + if (!(is_zero_v3(&world->horr) & is_zero_v3(&world->zenr))) { GPUNodeLink *fcol, *f; GPU_link(mat, "math_multiply", shi->amb, shi->refl, &f); GPU_link(mat, "math_multiply", f, GPU_uniform(&world->ao_env_energy), &f); @@ -2887,8 +2886,7 @@ void GPU_material_update_fvar_offset(GPUMaterial *gpu_material, "fvar%d_offset", input->attribid); location = GPU_shader_get_uniform(shader, name); - /* Multiply by 2 because we're offseting U and V variables. */ - GPU_shader_uniform_int(shader, location, layer_index * 2); + GPU_shader_uniform_int(shader, location, layer_index); } } diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c index 5a1b38e6be7..df1213b01e2 100644 --- a/source/blender/gpu/intern/gpu_shader.c +++ b/source/blender/gpu/intern/gpu_shader.c @@ -437,6 +437,10 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode, /* TODO(sergey): Find a better place for this. */ if (use_opensubdiv && GLEW_VERSION_4_1) { glProgramUniform1i(shader->program, + glGetUniformLocation(shader->program, "FVarDataOffsetBuffer"), + 30); /* GL_TEXTURE30 */ + + glProgramUniform1i(shader->program, glGetUniformLocation(shader->program, "FVarDataBuffer"), 31); /* GL_TEXTURE31 */ } diff --git a/source/blender/gpu/shaders/gpu_shader_geometry.glsl b/source/blender/gpu/shaders/gpu_shader_geometry.glsl index 1663915549c..6f063883e37 100644 --- a/source/blender/gpu/shaders/gpu_shader_geometry.glsl +++ b/source/blender/gpu/shaders/gpu_shader_geometry.glsl @@ -32,6 +32,7 @@ uniform int osd_fvar_count; } uniform samplerBuffer FVarDataBuffer; +uniform isamplerBuffer FVarDataOffsetBuffer; out block { VertexData v; diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index f3bd817a7cc..845a78720ba 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -1142,14 +1142,10 @@ void mtex_rgb_color(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 i void mtex_rgb_soft(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) { - float facm; - - fact *= facg; - facm = 1.0 - fact; + vec4 col; - vec3 one = vec3(1.0); - vec3 scr = one - (one - texcol) * (one - outcol); - incol = facm * outcol + fact * ((one - texcol) * outcol * texcol + outcol * scr); + mix_soft(fact * facg, vec4(outcol, 1.0), vec4(texcol, 1.0), col); + incol.rgb = col.rgb; } void mtex_rgb_linear(vec3 outcol, vec3 texcol, float fact, float facg, out vec3 incol) diff --git a/source/blender/imbuf/intern/filter.c b/source/blender/imbuf/intern/filter.c index 26ced49a333..1987c6d2a9a 100644 --- a/source/blender/imbuf/intern/filter.c +++ b/source/blender/imbuf/intern/filter.c @@ -206,7 +206,7 @@ void imb_filterx(struct ImBuf *ibuf) static void imb_filterN(ImBuf *out, ImBuf *in) { BLI_assert(out->channels == in->channels); - BLI_assert(out->x == in->x && out->y == out->y); + BLI_assert(out->x == in->x && out->y == in->y); const int channels = in->channels; const int rowlen = in->x; diff --git a/source/blender/imbuf/intern/stereoimbuf.c b/source/blender/imbuf/intern/stereoimbuf.c index a55cef60943..a4418443790 100644 --- a/source/blender/imbuf/intern/stereoimbuf.c +++ b/source/blender/imbuf/intern/stereoimbuf.c @@ -117,7 +117,7 @@ static void imb_stereo3d_write_anaglyph(Stereo3DData *s3d, enum eStereo3dAnaglyp to[0] = from[r][0]; to[1] = from[g][1]; to[2] = from[b][2]; - to[3] = MAX2(from[0][3], from[0][3]); + to[3] = MAX2(from[0][3], from[1][3]); } } } @@ -154,7 +154,7 @@ static void imb_stereo3d_write_anaglyph(Stereo3DData *s3d, enum eStereo3dAnaglyp to[0] = from[r][0]; to[1] = from[g][1]; to[2] = from[b][2]; - to[3] = MAX2(from[0][3], from[0][3]); + to[3] = MAX2(from[0][3], from[1][3]); } } } diff --git a/source/blender/makesdna/DNA_ID.h b/source/blender/makesdna/DNA_ID.h index d7feb3a3880..0936284e354 100644 --- a/source/blender/makesdna/DNA_ID.h +++ b/source/blender/makesdna/DNA_ID.h @@ -354,7 +354,10 @@ typedef struct PreviewImage { #define ID_MISSING(_id) (((_id)->tag & LIB_TAG_MISSING) != 0) -#define ID_IS_LINKED_DATABLOCK(_id) (((ID *)(_id))->lib != NULL) +#define ID_IS_LINKED(_id) (((ID *)(_id))->lib != NULL) +#define LIB_IS_VIRTUAL(_lib) (((_lib)->flag & LIBRARY_FLAG_VIRTUAL) != 0) +#define ID_IS_LINKED_DATABLOCK(_id) (ID_IS_LINKED(_id) && !LIB_IS_VIRTUAL(((ID *)(_id))->lib)) +#define ID_IS_LINKED_DATAPATH(_id) (ID_IS_LINKED(_id) && LIB_IS_VIRTUAL(((ID *)(_id))->lib)) #ifdef GS # undef GS diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h index 3dca087c7fa..f4a1677efc4 100644 --- a/source/blender/makesdna/DNA_brush_types.h +++ b/source/blender/makesdna/DNA_brush_types.h @@ -4,7 +4,7 @@ * 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. + * 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 @@ -70,7 +70,6 @@ typedef struct Brush { float normal_weight; float rake_factor; /* rake actual data (not texture), used for sculpt */ - int pad; short blend; /* blend mode */ short ob_mode; /* & with ob->mode to see if the brush is compatible, use for display only. */ @@ -95,7 +94,6 @@ typedef struct Brush { float plane_offset; /* offset for plane brushes (clay, flatten, fill, scrape) */ - int flag2; int gradient_spacing; int gradient_stroke_mode; /* source for stroke color gradient application */ int gradient_fill_mode; /* source for fill tool color gradient application */ @@ -104,7 +102,7 @@ typedef struct Brush { char vertexpaint_tool; /* active vertex/weight paint blend mode (poorly named) */ char imagepaint_tool; /* active image paint tool */ char mask_tool; /* enum BrushMaskTool, only used if sculpt_tool is SCULPT_TOOL_MASK */ - + float autosmooth_factor; float crease_pinch_factor; @@ -333,5 +331,4 @@ typedef enum BlurKernelType { #define MAX_BRUSH_PIXEL_RADIUS 500 -#endif - +#endif /* __DNA_BRUSH_TYPES_H__ */ diff --git a/source/blender/makesdna/DNA_cloth_types.h b/source/blender/makesdna/DNA_cloth_types.h index 07bc2478837..d385e303a7c 100644 --- a/source/blender/makesdna/DNA_cloth_types.h +++ b/source/blender/makesdna/DNA_cloth_types.h @@ -42,7 +42,7 @@ * * I've tried to keep similar, if not exact names for the variables as * are presented in the paper. Where I've changed the concept slightly, - * as in stepsPerFrame comapred to the time step in the paper, I've used + * as in stepsPerFrame compared to the time step in the paper, I've used * variables with different names to minimize confusion. */ diff --git a/source/blender/makesdna/DNA_color_types.h b/source/blender/makesdna/DNA_color_types.h index c9a5e056e4a..1d88b01cf62 100644 --- a/source/blender/makesdna/DNA_color_types.h +++ b/source/blender/makesdna/DNA_color_types.h @@ -157,10 +157,11 @@ typedef struct Scopes { /* scopes->wavefrm_mode */ #define SCOPES_WAVEFRM_LUMA 0 -#define SCOPES_WAVEFRM_RGB 1 +#define SCOPES_WAVEFRM_RGB_PARADE 1 #define SCOPES_WAVEFRM_YCC_601 2 #define SCOPES_WAVEFRM_YCC_709 3 #define SCOPES_WAVEFRM_YCC_JPEG 4 +#define SCOPES_WAVEFRM_RGB 5 typedef struct ColorManagedViewSettings { int flag, pad; diff --git a/source/blender/makesdna/DNA_genfile.h b/source/blender/makesdna/DNA_genfile.h index bc127ac2c82..a2981c0aa76 100644 --- a/source/blender/makesdna/DNA_genfile.h +++ b/source/blender/makesdna/DNA_genfile.h @@ -69,8 +69,11 @@ typedef enum eSDNA_Type { * For use with #DNA_struct_reconstruct & #DNA_struct_get_compareflags */ enum eSDNA_StructCompare { + /* Struct has disappeared (values of this struct type will not be loaded by the current Blender) */ SDNA_CMP_REMOVED = 0, + /* Struct is the same (can be loaded with straight memory copy after any necessary endian conversion) */ SDNA_CMP_EQUAL = 1, + /* Struct is different in some way (needs to be copied/converted field by field) */ SDNA_CMP_NOT_EQUAL = 2, }; @@ -89,15 +92,15 @@ void DNA_sdna_current_free(void); int DNA_struct_find_nr_ex(const struct SDNA *sdna, const char *str, unsigned int *index_last); int DNA_struct_find_nr(const struct SDNA *sdna, const char *str); void DNA_struct_switch_endian(const struct SDNA *oldsdna, int oldSDNAnr, char *data); -char *DNA_struct_get_compareflags(const struct SDNA *sdna, const struct SDNA*newsdna); +const char *DNA_struct_get_compareflags(const struct SDNA *sdna, const struct SDNA *newsdna); void *DNA_struct_reconstruct( const struct SDNA *newsdna, const struct SDNA *oldsdna, - char *compflags, int oldSDNAnr, int blocks, void *data); + const char *compflags, int oldSDNAnr, int blocks, const void *data); int DNA_elem_array_size(const char *str); int DNA_elem_offset(struct SDNA *sdna, const char *stype, const char *vartype, const char *name); -bool DNA_struct_elem_find(struct SDNA *sdna, const char *stype, const char *vartype, const char *name); +bool DNA_struct_elem_find(const struct SDNA *sdna, const char *stype, const char *vartype, const char *name); int DNA_elem_type_size(const eSDNA_Type elem_nr); diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index a58e995f1c6..bbc8edf4344 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -641,8 +641,9 @@ typedef struct BooleanModifierData { struct Object *object; char operation; - char bm_flag, pad[2]; - float threshold; + char solver; + char pad[2]; + float double_threshold; } BooleanModifierData; typedef enum { @@ -651,13 +652,10 @@ typedef enum { eBooleanModifierOp_Difference = 2, } BooleanModifierOp; -/* temp bm_flag (debugging only) */ -enum { - eBooleanModifierBMeshFlag_Enabled = (1 << 0), - eBooleanModifierBMeshFlag_BMesh_Separate = (1 << 1), - eBooleanModifierBMeshFlag_BMesh_NoDissolve = (1 << 2), - eBooleanModifierBMeshFlag_BMesh_NoConnectRegions = (1 << 3), -}; +typedef enum { + eBooleanModifierSolver_Carve = 0, + eBooleanModifierSolver_BMesh = 1, +} BooleanSolver; typedef struct MDefInfluence { int vertex; diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 58f4255068c..4c739203e77 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1273,7 +1273,9 @@ typedef struct CurvePaintSettings { char flag; char depth_mode; char surface_plane; - int error_threshold; + char fit_method; + char pad; + short error_threshold; float radius_min, radius_max; float radius_taper_start, radius_taper_end; float surface_offset; @@ -1288,6 +1290,12 @@ enum { CURVE_PAINT_FLAG_DEPTH_STROKE_OFFSET_ABS = (1 << 3), }; +/* CurvePaintSettings.fit_method */ +enum { + CURVE_PAINT_FIT_METHOD_REFIT = 0, + CURVE_PAINT_FIT_METHOD_SPLIT = 1, +}; + /* CurvePaintSettings.depth_mode */ enum { CURVE_PAINT_PROJECT_CURSOR = 0, diff --git a/source/blender/makesdna/DNA_sdna_types.h b/source/blender/makesdna/DNA_sdna_types.h index 26ea5cd4e93..bd8f23f30c1 100644 --- a/source/blender/makesdna/DNA_sdna_types.h +++ b/source/blender/makesdna/DNA_sdna_types.h @@ -45,7 +45,7 @@ typedef struct SDNA { int pointerlen; /* size of a pointer in bytes */ int nr_types; /* number of basic types + struct types */ - char **types; /* type names */ + const char **types; /* type names */ short *typelens; /* type lengths */ int nr_structs; /* number of struct types */ diff --git a/source/blender/makesdna/DNA_view3d_types.h b/source/blender/makesdna/DNA_view3d_types.h index 5b533d1ec48..4c243507e82 100644 --- a/source/blender/makesdna/DNA_view3d_types.h +++ b/source/blender/makesdna/DNA_view3d_types.h @@ -239,7 +239,7 @@ typedef struct View3D { float stereo3d_convergence_alpha; /* Previous viewport draw type. - * Runtime-only, set in the rendered viewport otggle operator. + * Runtime-only, set in the rendered viewport toggle operator. */ short prev_drawtype; short pad1; diff --git a/source/blender/makesdna/intern/CMakeLists.txt b/source/blender/makesdna/intern/CMakeLists.txt index 0bb6e866bf4..8c758c33dc5 100644 --- a/source/blender/makesdna/intern/CMakeLists.txt +++ b/source/blender/makesdna/intern/CMakeLists.txt @@ -52,6 +52,8 @@ endif() # SRC_DNA_INC is defined in the parent dir +add_cc_flags_custom_test(makesdna) + add_executable(makesdna ${SRC} ${SRC_DNA_INC}) # Output dna.c diff --git a/source/blender/makesdna/intern/dna_genfile.c b/source/blender/makesdna/intern/dna_genfile.c index 1e3c91d5ddc..6a41591e051 100644 --- a/source/blender/makesdna/intern/dna_genfile.c +++ b/source/blender/makesdna/intern/dna_genfile.c @@ -134,39 +134,6 @@ * */ -/* ************************* ENDIAN STUFF ********************** */ - -/** - * converts a short between big/little endian. - */ -static short le_short(short temp) -{ - short new; - char *rt = (char *)&temp, *rtn = (char *)&new; - - rtn[0] = rt[1]; - rtn[1] = rt[0]; - - return new; -} - -/** - * converts an int between big/little endian. - */ -static int le_int(int temp) -{ - int new; - char *rt = (char *)&temp, *rtn = (char *)&new; - - rtn[0] = rt[3]; - rtn[1] = rt[2]; - rtn[2] = rt[1]; - rtn[3] = rt[0]; - - return new; -} - - /* ************************* MAKE DNA ********************** */ /* allowed duplicate code from makesdna.c */ @@ -338,6 +305,11 @@ int DNA_struct_find_nr(const SDNA *sdna, const char *str) /* ************************* READ DNA ********************** */ +BLI_INLINE const char *pad_up_4(const char *ptr) +{ + return (const char *)((((uintptr_t)ptr) + 3) & ~3); +} + /** * In sdna->data the data, now we convert that to something understandable */ @@ -366,8 +338,7 @@ static bool init_structDNA( return false; } else { - intptr_t nr; - char *cp; + const char *cp; data++; @@ -376,8 +347,10 @@ static bool init_structDNA( if (*data == *verg) { data++; - if (do_endian_swap) sdna->nr_names = le_int(*data); - else sdna->nr_names = *data; + sdna->nr_names = *data; + if (do_endian_swap) { + BLI_endian_switch_int32(&sdna->nr_names); + } data++; sdna->names = MEM_callocN(sizeof(void *) * sdna->nr_names, "sdnanames"); @@ -387,9 +360,8 @@ static bool init_structDNA( return false; } - nr = 0; cp = (char *)data; - while (nr < sdna->nr_names) { + for (int nr = 0; nr < sdna->nr_names; nr++) { sdna->names[nr] = cp; /* "float gravity [3]" was parsed wrong giving both "gravity" and @@ -404,20 +376,20 @@ static bool init_structDNA( while (*cp) cp++; cp++; - nr++; } - nr = (intptr_t)cp; /* prevent BUS error */ - nr = (nr + 3) & ~3; - cp = (char *)nr; + + cp = pad_up_4(cp); /* load type names array */ data = (int *)cp; strcpy(str, "TYPE"); if (*data == *verg) { data++; - - if (do_endian_swap) sdna->nr_types = le_int(*data); - else sdna->nr_types = *data; + + sdna->nr_types = *data; + if (do_endian_swap) { + BLI_endian_switch_int32(&sdna->nr_types); + } data++; sdna->types = MEM_callocN(sizeof(void *) * sdna->nr_types, "sdnatypes"); @@ -427,9 +399,8 @@ static bool init_structDNA( return false; } - nr = 0; cp = (char *)data; - while (nr < sdna->nr_types) { + for (int nr = 0; nr < sdna->nr_types; nr++) { sdna->types[nr] = cp; /* this is a patch, to change struct names without a conflict with SDNA */ @@ -442,11 +413,9 @@ static bool init_structDNA( while (*cp) cp++; cp++; - nr++; } - nr = (intptr_t)cp; /* prevent BUS error */ - nr = (nr + 3) & ~3; - cp = (char *)nr; + + cp = pad_up_4(cp); /* load typelen array */ data = (int *)cp; @@ -457,13 +426,7 @@ static bool init_structDNA( sdna->typelens = sp; if (do_endian_swap) { - short a, *spo = sp; - - a = sdna->nr_types; - while (a--) { - spo[0] = le_short(spo[0]); - spo++; - } + BLI_endian_switch_int16_array(sp, sdna->nr_types); } sp += sdna->nr_types; @@ -480,8 +443,10 @@ static bool init_structDNA( if (*data == *verg) { data++; - if (do_endian_swap) sdna->nr_structs = le_int(*data); - else sdna->nr_structs = *data; + sdna->nr_structs = *data; + if (do_endian_swap) { + BLI_endian_switch_int32(&sdna->nr_structs); + } data++; sdna->structs = MEM_callocN(sizeof(void *) * sdna->nr_structs, "sdnastrcs"); @@ -491,37 +456,34 @@ static bool init_structDNA( return false; } - nr = 0; sp = (short *)data; - while (nr < sdna->nr_structs) { + for (int nr = 0; nr < sdna->nr_structs; nr++) { sdna->structs[nr] = sp; if (do_endian_swap) { short a; - sp[0] = le_short(sp[0]); - sp[1] = le_short(sp[1]); + BLI_endian_switch_int16(&sp[0]); + BLI_endian_switch_int16(&sp[1]); a = sp[1]; sp += 2; while (a--) { - sp[0] = le_short(sp[0]); - sp[1] = le_short(sp[1]); + BLI_endian_switch_int16(&sp[0]); + BLI_endian_switch_int16(&sp[1]); sp += 2; } } else { sp += 2 * sp[1] + 2; } - - nr++; } } { /* second part of gravity problem, setting "gravity" type to void */ if (gravity_fix > -1) { - for (intptr_t nr = 0; nr < sdna->nr_structs; nr++) { + for (int nr = 0; nr < sdna->nr_structs; nr++) { sp = sdna->structs[nr]; if (strcmp(sdna->types[sp[0]], "ClothSimSettings") == 0) sp[10] = SDNA_TYPE_VOID; @@ -536,7 +498,7 @@ static bool init_structDNA( for (intptr_t nr = 0; nr < sdna->nr_structs; nr++) { sp = sdna->structs[nr]; - BLI_ghash_insert(sdna->structs_map, sdna->types[sp[0]], SET_INT_IN_POINTER(nr)); + BLI_ghash_insert(sdna->structs_map, (void *)sdna->types[sp[0]], SET_INT_IN_POINTER(nr)); } } #endif @@ -670,13 +632,8 @@ static void recurs_test_compflags(const SDNA *sdna, char *compflags, int structn /** * Constructs and returns an array of byte flags with one element for each struct in oldsdna, * indicating how it compares to newsdna: - * - * flag value: - * - 0 Struct has disappeared (values of this struct type will not be loaded by the current Blender) - * - 1 Struct is the same (can be loaded with straight memory copy after any necessary endian conversion) - * - 2 Struct is different in some way (needs to be copied/converted field by field) */ -char *DNA_struct_get_compareflags(const SDNA *oldsdna, const SDNA *newsdna) +const char *DNA_struct_get_compareflags(const SDNA *oldsdna, const SDNA *newsdna) { int a, b; const short *sp_old, *sp_new; @@ -947,12 +904,12 @@ static int elem_strcmp(const char *name, const char *oname) * \param sppo Optional place to return pointer to field info in sdna * \return Data address. */ -static char *find_elem( +static const char *find_elem( const SDNA *sdna, const char *type, const char *name, const short *old, - char *olddata, + const char *olddata, const short **sppo) { int a, elemcount, len; @@ -1100,7 +1057,7 @@ static void reconstruct_struct( const char *compflags, int oldSDNAnr, - char *data, + const char *data, int curSDNAnr, char *cur) { @@ -1111,7 +1068,8 @@ static void reconstruct_struct( int a, elemcount, elen, eleno, mul, mulo, firststructtypenr; const short *spo, *spc, *sppo; const char *type; - char *cpo, *cpc; + const char *cpo; + char *cpc; const char *name, *nameo; unsigned int oldsdna_index_last = UINT_MAX; @@ -1149,7 +1107,7 @@ static void reconstruct_struct( if (spc[0] >= firststructtypenr && !ispointer(name)) { /* struct field type */ /* where does the old struct data start (and is there an old one?) */ - cpo = find_elem(oldsdna, type, name, spo, data, &sppo); + cpo = (char *)find_elem(oldsdna, type, name, spo, data, &sppo); if (cpo) { oldSDNAnr = DNA_struct_find_nr_ex(oldsdna, type, &oldsdna_index_last); @@ -1226,7 +1184,7 @@ void DNA_struct_switch_endian(const SDNA *oldsdna, int oldSDNAnr, char *data) if (spc[0] >= firststructtypenr && !ispointer(name)) { /* struct field type */ /* where does the old data start (is there one?) */ - char *cpo = find_elem(oldsdna, type, name, spo, data, NULL); + char *cpo = (char *)find_elem(oldsdna, type, name, spo, data, NULL); if (cpo) { oldSDNAnr = DNA_struct_find_nr_ex(oldsdna, type, &oldsdna_index_last); @@ -1288,11 +1246,12 @@ void DNA_struct_switch_endian(const SDNA *oldsdna, int oldSDNAnr, char *data) */ void *DNA_struct_reconstruct( const SDNA *newsdna, const SDNA *oldsdna, - char *compflags, int oldSDNAnr, int blocks, void *data) + const char *compflags, int oldSDNAnr, int blocks, const void *data) { int a, curSDNAnr, curlen = 0, oldlen; const short *spo, *spc; - char *cur, *cpc, *cpo; + char *cur, *cpc; + const char *cpo; const char *type; /* oldSDNAnr == structnr, we're looking for the corresponding 'cur' number */ @@ -1335,7 +1294,7 @@ int DNA_elem_offset(SDNA *sdna, const char *stype, const char *vartype, const ch return (int)((intptr_t)cp); } -bool DNA_struct_elem_find(SDNA *sdna, const char *stype, const char *vartype, const char *name) +bool DNA_struct_elem_find(const SDNA *sdna, const char *stype, const char *vartype, const char *name) { const int SDNAnr = DNA_struct_find_nr(sdna, stype); diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h index b1048f72022..7ae3d552916 100644 --- a/source/blender/makesrna/RNA_enum_types.h +++ b/source/blender/makesrna/RNA_enum_types.h @@ -52,6 +52,7 @@ extern EnumPropertyItem rna_enum_proportional_editing_items[]; extern EnumPropertyItem rna_enum_snap_target_items[]; extern EnumPropertyItem rna_enum_snap_element_items[]; extern EnumPropertyItem rna_enum_snap_node_element_items[]; +extern EnumPropertyItem rna_enum_curve_fit_method_items[]; extern EnumPropertyItem rna_enum_mesh_select_mode_items[]; extern EnumPropertyItem rna_enum_mesh_delimit_mode_items[]; extern EnumPropertyItem rna_enum_space_type_items[]; diff --git a/source/blender/makesrna/intern/CMakeLists.txt b/source/blender/makesrna/intern/CMakeLists.txt index 17b65a9d529..01db7b338b9 100644 --- a/source/blender/makesrna/intern/CMakeLists.txt +++ b/source/blender/makesrna/intern/CMakeLists.txt @@ -351,7 +351,10 @@ blender_include_dirs_sys( "${GLEW_INCLUDE_PATH}" ) +add_cc_flags_custom_test(makesrna) + add_executable(makesrna ${SRC} ${SRC_RNA_INC} ${SRC_DNA_INC}) + target_link_libraries(makesrna bf_dna) target_link_libraries(makesrna bf_dna_blenlib) diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 813c1062a02..8af9fa87865 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -3299,7 +3299,7 @@ static RNAProcessItem PROCESS_ITEMS[] = { {"rna_animviz.c", NULL, RNA_def_animviz}, {"rna_actuator.c", "rna_actuator_api.c", RNA_def_actuator}, {"rna_armature.c", "rna_armature_api.c", RNA_def_armature}, - {"rna_asset.c", NULL, RNA_def_asset}, + {"rna_asset.c", NULL, RNA_def_asset}, {"rna_boid.c", NULL, RNA_def_boid}, {"rna_brush.c", NULL, RNA_def_brush}, {"rna_camera.c", "rna_camera_api.c", RNA_def_camera}, diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 533b1991ba5..528aabf33ee 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -698,7 +698,7 @@ static void rna_ImagePreview_icon_pixels_float_set(PointerRNA *ptr, const float static int rna_ImagePreview_icon_id_get(PointerRNA *ptr) { /* Using a callback here allows us to only generate icon matching that preview when icon_id is requested. */ - return BKE_icon_preview_ensure((PreviewImage *)(ptr->data)); + return BKE_icon_preview_ensure(ptr->id.data, (PreviewImage *)(ptr->data)); } static void rna_ImagePreview_icon_reload(PreviewImage *prv) { @@ -1061,6 +1061,7 @@ static void rna_def_ID(BlenderRNA *brna) static void rna_def_library(BlenderRNA *brna) { StructRNA *srna; + FunctionRNA *func; PropertyRNA *prop; srna = RNA_def_struct(brna, "Library", "ID"); @@ -1079,6 +1080,10 @@ static void rna_def_library(BlenderRNA *brna) prop = RNA_def_property(srna, "packed_file", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "packedfile"); RNA_def_property_ui_text(prop, "Packed File", ""); + + func = RNA_def_function(srna, "reload", "WM_lib_reload"); + RNA_def_function_flag(func, FUNC_USE_REPORTS | FUNC_USE_CONTEXT); + RNA_def_function_ui_description(func, "Reload this library and all its linked datablocks"); } void RNA_def_ID(BlenderRNA *brna) { diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 00b7df122ee..5a93e18a7dd 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -3127,8 +3127,11 @@ void RNA_property_collection_add(PointerRNA *ptr, PropertyRNA *prop, PointerRNA RNA_parameter_list_free(¶ms); } } - /*else - printf("%s %s.%s: not implemented for this property.\n", __func__, ptr->type->identifier, prop->identifier);*/ +#if 0 + else { + printf("%s %s.%s: not implemented for this property.\n", __func__, ptr->type->identifier, prop->identifier); + } +#endif #endif if (r_ptr) { @@ -3187,8 +3190,11 @@ bool RNA_property_collection_remove(PointerRNA *ptr, PropertyRNA *prop, int key) return false; } - /*else - printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier);*/ +#if 0 + else { + printf("%s %s.%s: only supported for id properties.\n", __func__, ptr->type->identifier, prop->identifier); + } +#endif #endif return false; } diff --git a/source/blender/makesrna/intern/rna_animation.c b/source/blender/makesrna/intern/rna_animation.c index c3d1070b8c2..7a1954036e3 100644 --- a/source/blender/makesrna/intern/rna_animation.c +++ b/source/blender/makesrna/intern/rna_animation.c @@ -116,6 +116,23 @@ static void rna_AnimData_action_set(PointerRNA *ptr, PointerRNA value) } } +static void rna_AnimData_tweakmode_set(PointerRNA *ptr, const int value) +{ + AnimData *adt = (AnimData *)ptr->data; + + /* NOTE: technically we should also set/unset SCE_NLA_EDIT_ON flag on the + * scene which is used to make polling tests faster, but this flag is weak + * and can easily break e.g. by changing layer visibility. This needs to be + * dealt with at some point. */ + + if (value) { + BKE_nla_tweakmode_enter(adt); + } + else { + BKE_nla_tweakmode_exit(adt); + } +} + /* ****************************** */ /* wrapper for poll callback */ @@ -1041,6 +1058,12 @@ static void rna_def_animdata(BlenderRNA *brna) RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", ADT_NLA_EVAL_OFF); RNA_def_property_ui_text(prop, "NLA Evaluation Enabled", "NLA stack is evaluated when evaluating this block"); RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); /* this will do? */ + + prop = RNA_def_property(srna, "use_tweak_mode", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", ADT_NLA_EDIT_ON); + RNA_def_property_boolean_funcs(prop, NULL, "rna_AnimData_tweakmode_set"); + RNA_def_property_ui_text(prop, "Use NLA Tweak Mode", "Whether to enable or disable tweak mode in NLA"); + RNA_def_property_update(prop, NC_ANIMATION | ND_NLA, NULL); } /* --- */ diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index 842e220e8b5..5c7f51516cb 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -498,13 +498,13 @@ void rna_def_bone_curved_common(StructRNA *srna, bool is_posebone) /* Roll In/Out */ prop = RNA_def_property(srna, "bbone_rollin", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "roll1"); - RNA_def_property_range(prop, -M_PI * 2.0f, M_PI * 2.0f); + RNA_def_property_range(prop, -M_PI * 2.0, M_PI * 2.0); RNA_def_property_ui_text(prop, "Roll In", "Roll offset for the start of the B-Bone, adjusts twist"); RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone); prop = RNA_def_property(srna, "bbone_rollout", PROP_FLOAT, PROP_ANGLE); RNA_def_property_float_sdna(prop, NULL, "roll2"); - RNA_def_property_range(prop, -M_PI * 2.0f, M_PI * 2.0f); + RNA_def_property_range(prop, -M_PI * 2.0, M_PI * 2.0); RNA_def_property_ui_text(prop, "Roll Out", "Roll offset for the end of the B-Bone, adjusts twist"); RNA_DEF_CURVEBONE_UPDATE(prop, is_posebone); diff --git a/source/blender/makesrna/intern/rna_asset.c b/source/blender/makesrna/intern/rna_asset.c index 0d1279e96df..afd23e9fa0d 100644 --- a/source/blender/makesrna/intern/rna_asset.c +++ b/source/blender/makesrna/intern/rna_asset.c @@ -35,7 +35,7 @@ #include "rna_internal.h" -#include "BKE_asset.h" +#include "BKE_asset_engine.h" #include "BKE_idprop.h" #include "WM_types.h" @@ -46,7 +46,6 @@ #include "RNA_access.h" -#include "BKE_asset.h" #include "BKE_context.h" #include "BKE_report.h" diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c index 492430fbda6..078ba13d76d 100644 --- a/source/blender/makesrna/intern/rna_camera.c +++ b/source/blender/makesrna/intern/rna_camera.c @@ -159,13 +159,13 @@ static void rna_def_camera_stereo_data(BlenderRNA *brna) RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); prop = RNA_def_property(srna, "pole_merge_angle_from", PROP_FLOAT, PROP_ANGLE); - RNA_def_property_range(prop, 0.0f, M_PI / 2.0f); + RNA_def_property_range(prop, 0.0f, M_PI / 2.0); RNA_def_property_ui_text(prop, "Pole Merge Start Angle", "Angle at which interocular distance starts to fade to 0"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); prop = RNA_def_property(srna, "pole_merge_angle_to", PROP_FLOAT, PROP_ANGLE); - RNA_def_property_range(prop, 0.0f, M_PI / 2.0f); + RNA_def_property_range(prop, 0.0f, M_PI / 2.0); RNA_def_property_ui_text(prop, "Pole Merge End Angle", "Angle at which interocular distance is 0"); RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL); diff --git a/source/blender/makesrna/intern/rna_color.c b/source/blender/makesrna/intern/rna_color.c index 021bc608564..78e3bbe4176 100644 --- a/source/blender/makesrna/intern/rna_color.c +++ b/source/blender/makesrna/intern/rna_color.c @@ -1018,10 +1018,11 @@ static void rna_def_scopes(BlenderRNA *brna) static EnumPropertyItem prop_wavefrm_mode_items[] = { {SCOPES_WAVEFRM_LUMA, "LUMA", ICON_COLOR, "Luma", ""}, - {SCOPES_WAVEFRM_RGB, "RGB", ICON_COLOR, "Red Green Blue", ""}, + {SCOPES_WAVEFRM_RGB_PARADE, "PARADE", ICON_COLOR, "Parade", ""}, {SCOPES_WAVEFRM_YCC_601, "YCBCR601", ICON_COLOR, "YCbCr (ITU 601)", ""}, {SCOPES_WAVEFRM_YCC_709, "YCBCR709", ICON_COLOR, "YCbCr (ITU 709)", ""}, {SCOPES_WAVEFRM_YCC_JPEG, "YCBCRJPG", ICON_COLOR, "YCbCr (Jpeg)", ""}, + {SCOPES_WAVEFRM_RGB, "RGB", ICON_COLOR, "Red Green Blue", ""}, {0, NULL, 0, NULL, NULL} }; diff --git a/source/blender/makesrna/intern/rna_fluidsim.c b/source/blender/makesrna/intern/rna_fluidsim.c index 16e0f17eac5..091950a8e66 100644 --- a/source/blender/makesrna/intern/rna_fluidsim.c +++ b/source/blender/makesrna/intern/rna_fluidsim.c @@ -204,18 +204,6 @@ static char *rna_FluidSettings_path(PointerRNA *ptr) return BLI_sprintfN("modifiers[\"%s\"].settings", name_esc); } -static void rna_FluidMeshVertex_data_begin(CollectionPropertyIterator *iter, PointerRNA *ptr) -{ - FluidsimSettings *fss = (FluidsimSettings *)ptr->data; - rna_iterator_array_begin(iter, fss->meshVelocities, sizeof(float) * 3, fss->totvert, 0, NULL); -} - -static int rna_FluidMeshVertex_data_length(PointerRNA *ptr) -{ - FluidsimSettings *fss = (FluidsimSettings *)ptr->data; - return fss->totvert; -} - #else static void rna_def_fluidsim_slip(StructRNA *srna) @@ -251,9 +239,8 @@ static void rna_def_fluid_mesh_vertices(BlenderRNA *brna) StructRNA *srna; PropertyRNA *prop; - srna = RNA_def_struct(brna, "FluidMeshVertex", NULL); - RNA_def_struct_sdna(srna, "FluidVertexVelocity"); - RNA_def_struct_ui_text(srna, "Fluid Mesh Vertex", "Vertex of a simulated fluid mesh"); + srna = RNA_def_struct(brna, "FluidVertexVelocity", NULL); + RNA_def_struct_ui_text(srna, "Fluid Mesh Velocity", "Velocity of a simulated fluid mesh"); RNA_def_struct_ui_icon(srna, ICON_VERTEXSEL); prop = RNA_def_property(srna, "velocity", PROP_FLOAT, PROP_VELOCITY); @@ -442,11 +429,10 @@ static void rna_def_fluidsim_domain(BlenderRNA *brna) /* simulated fluid mesh data */ prop = RNA_def_property(srna, "fluid_mesh_vertices", PROP_COLLECTION, PROP_NONE); - RNA_def_property_struct_type(prop, "FluidMeshVertex"); + RNA_def_property_collection_sdna(prop, NULL, "meshVelocities", "totvert"); + RNA_def_property_struct_type(prop, "FluidVertexVelocity"); RNA_def_property_ui_text(prop, "Fluid Mesh Vertices", "Vertices of the fluid mesh generated by simulation"); - RNA_def_property_collection_funcs(prop, "rna_FluidMeshVertex_data_begin", "rna_iterator_array_next", - "rna_iterator_array_end", "rna_iterator_array_get", - "rna_FluidMeshVertex_data_length", NULL, NULL, NULL); + rna_def_fluid_mesh_vertices(brna); } diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index ef74f01f9be..a23ef6eaa82 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -1895,6 +1895,12 @@ static void rna_def_modifier_boolean(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; + static EnumPropertyItem prop_solver_items[] = { + {eBooleanModifierSolver_BMesh, "BMESH", 0, "BMesh", "Use the BMesh boolean solver"}, + {eBooleanModifierSolver_Carve, "CARVE", 0, "Carve", "Use the Carve boolean solver"}, + {0, NULL, 0, NULL, NULL} + }; + srna = RNA_def_struct(brna, "BooleanModifier", "Modifier"); RNA_def_struct_ui_text(srna, "Boolean Modifier", "Boolean operations modifier"); RNA_def_struct_sdna(srna, "BooleanModifierData"); @@ -1911,35 +1917,17 @@ static void rna_def_modifier_boolean(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Operation", ""); RNA_def_property_update(prop, 0, "rna_Modifier_update"); -#if 0 /* WITH_MOD_BOOLEAN */ - /* BMesh intersection options */ - prop = RNA_def_property(srna, "use_bmesh", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "bm_flag", eBooleanModifierBMeshFlag_Enabled); - RNA_def_property_ui_text(prop, "Use BMesh", "Use BMesh boolean calculation"); - RNA_def_property_update(prop, 0, "rna_Modifier_update"); - - prop = RNA_def_property(srna, "use_bmesh_separate", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "bm_flag", eBooleanModifierBMeshFlag_BMesh_Separate); - RNA_def_property_ui_text(prop, "Separate", "Keep edges separate"); + prop = RNA_def_property(srna, "solver", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_items(prop, prop_solver_items); + RNA_def_property_ui_text(prop, "Solver", ""); RNA_def_property_update(prop, 0, "rna_Modifier_update"); - prop = RNA_def_property(srna, "use_bmesh_dissolve", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "bm_flag", eBooleanModifierBMeshFlag_BMesh_NoDissolve); - RNA_def_property_ui_text(prop, "Dissolve", "Dissolve verts created from tessellated intersection"); - RNA_def_property_update(prop, 0, "rna_Modifier_update"); - - prop = RNA_def_property(srna, "use_bmesh_connect_regions", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_negative_sdna(prop, NULL, "bm_flag", eBooleanModifierBMeshFlag_BMesh_NoConnectRegions); - RNA_def_property_ui_text(prop, "Calculate Holes", "Connect regions (needed for hole filling)"); - RNA_def_property_update(prop, 0, "rna_Modifier_update"); - - prop = RNA_def_property(srna, "threshold", PROP_FLOAT, PROP_DISTANCE); - RNA_def_property_float_sdna(prop, NULL, "threshold"); + prop = RNA_def_property(srna, "double_threshold", PROP_FLOAT, PROP_DISTANCE); + RNA_def_property_float_sdna(prop, NULL, "double_threshold"); RNA_def_property_range(prop, 0, 1.0f); - RNA_def_property_ui_range(prop, 0, 1, 1, 7); - RNA_def_property_ui_text(prop, "Threshold", ""); + RNA_def_property_ui_range(prop, 0, 1, 0.0001, 7); + RNA_def_property_ui_text(prop, "Overlap Threshold", "Threshold for checking overlapping geometry"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); -#endif } static void rna_def_modifier_array(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index f15625259a9..9683495c54c 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -1033,7 +1033,7 @@ static void rna_GameObjectSettings_physics_type_set(PointerRNA *ptr, int value) ob->gameflag &= ~(OB_SENSOR | OB_OCCLUDER | OB_DYNAMIC | OB_RIGID_BODY | OB_SOFT_BODY | OB_ACTOR | OB_ANISOTROPIC_FRICTION | OB_DO_FH | OB_ROT_FH | OB_COLLISION_RESPONSE | OB_NAVMESH); /* When we switch to character physics and the collision bounds is set to triangle mesh - we have to change collision bounds because triangle mesh is not supported by Characters*/ + * we have to change collision bounds because triangle mesh is not supported by Characters */ if ((ob->gameflag & OB_BOUNDS) && ob->collision_boundtype == OB_BOUND_TRIANGLE_MESH) { ob->boundtype = ob->collision_boundtype = OB_BOUND_BOX; } diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index d1f8c4e5bed..ed90f146f4d 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -178,6 +178,11 @@ EnumPropertyItem snap_uv_element_items[] = { {0, NULL, 0, NULL, NULL} }; +EnumPropertyItem rna_enum_curve_fit_method_items[] = { + {CURVE_PAINT_FIT_METHOD_REFIT, "REFIT", 0, "Refit", "Incrementally re-fit the curve (high quality)"}, + {CURVE_PAINT_FIT_METHOD_SPLIT, "SPLIT", 0, "Split", "Split the curve until the tolerance is met (fast)"}, + {0, NULL, 0, NULL, NULL}}; + /* workaround for duplicate enums, * have each enum line as a define then conditionally set it or not */ @@ -2638,6 +2643,11 @@ static void rna_def_curve_paint_settings(BlenderRNA *brna) RNA_def_property_range(prop, 1, 100); RNA_def_property_ui_text(prop, "Tolerance", "Allow deviation for a smoother, less precise line"); + prop = RNA_def_property(srna, "fit_method", PROP_ENUM, PROP_PIXEL); + RNA_def_property_enum_sdna(prop, NULL, "fit_method"); + RNA_def_property_enum_items(prop, rna_enum_curve_fit_method_items); + RNA_def_property_ui_text(prop, "Method", "Curve fitting method"); + prop = RNA_def_property(srna, "corner_angle", PROP_FLOAT, PROP_ANGLE); RNA_def_property_range(prop, 0, M_PI); RNA_def_property_ui_text(prop, "Corner Angle", "Angles above this are considered corners"); diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 738554af9c0..4437c26f0be 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -35,7 +35,7 @@ #include "RNA_define.h" -#include "BKE_asset.h" +#include "BKE_asset_engine.h" #include "BKE_image.h" #include "BKE_key.h" #include "BKE_movieclip.h" @@ -253,7 +253,7 @@ EnumPropertyItem rna_enum_file_sort_items[] = { #include "BLI_math.h" #include "BKE_animsys.h" -#include "BKE_asset.h" +#include "BKE_asset_engine.h" #include "BKE_brush.h" #include "BKE_colortools.h" #include "BKE_context.h" @@ -3661,7 +3661,7 @@ static void rna_def_space_nla(BlenderRNA *brna) prop = RNA_def_property(srna, "show_local_markers", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", SNLA_NOLOCALMARKERS); RNA_def_property_ui_text(prop, "Show Local Markers", - "Show action-local markers on the strips, useful when synchronising timing across strips"); + "Show action-local markers on the strips, useful when synchronizing timing across strips"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_NLA, NULL); /* editing */ diff --git a/source/blender/modifiers/intern/MOD_boolean.c b/source/blender/modifiers/intern/MOD_boolean.c index 3f418fa16f3..da0f5aa3923 100644 --- a/source/blender/modifiers/intern/MOD_boolean.c +++ b/source/blender/modifiers/intern/MOD_boolean.c @@ -33,7 +33,7 @@ */ // #ifdef DEBUG_TIME -// #define USE_BMESH +#define USE_BMESH #ifdef WITH_MOD_BOOLEAN # define USE_CARVE WITH_MOD_BOOLEAN #endif @@ -71,6 +71,14 @@ #include "PIL_time_utildefines.h" #endif +static void initData(ModifierData *md) +{ + BooleanModifierData *bmd = (BooleanModifierData *)md; + + bmd->solver = eBooleanModifierSolver_BMesh; + bmd->double_threshold = 1e-6f; +} + static void copyData(ModifierData *md, ModifierData *target) { #if 0 @@ -222,7 +230,9 @@ static DerivedMesh *applyModifier_bmesh( #ifdef DEBUG_TIME TIMEIT_START(boolean_bmesh); #endif - bm = BM_mesh_create_ex(&allocsize, ); + bm = BM_mesh_create( + &allocsize, + &((struct BMeshCreateParams){.use_toolflags = false,})); DM_to_bmesh_ex(dm_other, bm, true); DM_to_bmesh_ex(dm, bm, true); @@ -296,16 +306,21 @@ static DerivedMesh *applyModifier_bmesh( * currently this is ok for 'BM_mesh_intersect' */ // BM_mesh_normals_update(bm); + /* change for testing */ + bool use_separate = false; + bool use_dissolve = true; + bool use_island_connect = true; + BM_mesh_intersect( bm, looptris, tottri, bm_face_isect_pair, NULL, false, - (bmd->bm_flag & eBooleanModifierBMeshFlag_BMesh_Separate) != 0, - (bmd->bm_flag & eBooleanModifierBMeshFlag_BMesh_NoDissolve) == 0, - (bmd->bm_flag & eBooleanModifierBMeshFlag_BMesh_NoConnectRegions) == 0, + use_separate, + use_dissolve, + use_island_connect, bmd->operation, - bmd->threshold); + bmd->double_threshold); MEM_freeN(looptris); } @@ -409,15 +424,14 @@ static DerivedMesh *applyModifier( ModifierApplyFlag flag) { BooleanModifierData *bmd = (BooleanModifierData *)md; - const int method = (bmd->bm_flag & eBooleanModifierBMeshFlag_Enabled) ? 1 : 0; - switch (method) { + switch (bmd->solver) { #ifdef USE_CARVE - case 0: + case eBooleanModifierSolver_Carve: return applyModifier_carve(md, ob, derivedData, flag); #endif #ifdef USE_BMESH - case 1: + case eBooleanModifierSolver_BMesh: return applyModifier_bmesh(md, ob, derivedData, flag); #endif default: @@ -441,7 +455,7 @@ ModifierTypeInfo modifierType_Boolean = { /* deformMatricesEM */ NULL, /* applyModifier */ applyModifier, /* applyModifierEM */ NULL, - /* initData */ NULL, + /* initData */ initData, /* requiredDataMask */ requiredDataMask, /* freeData */ NULL, /* isDisabled */ isDisabled, diff --git a/source/blender/modifiers/intern/MOD_normal_edit.c b/source/blender/modifiers/intern/MOD_normal_edit.c index 2cfa746ab3c..ceb7dc02699 100644 --- a/source/blender/modifiers/intern/MOD_normal_edit.c +++ b/source/blender/modifiers/intern/MOD_normal_edit.c @@ -144,8 +144,9 @@ static void mix_normals( break; } - interp_v3_v3v3_slerp_safe(*no_new, *no_old, *no_new, - (mix_limit < M_PI) ? min_ff(fac, mix_limit / angle_v3v3(*no_new, *no_old)) : fac); + interp_v3_v3v3_slerp_safe( + *no_new, *no_old, *no_new, + (mix_limit < (float)M_PI) ? min_ff(fac, mix_limit / angle_v3v3(*no_new, *no_old)) : fac); } MEM_SAFE_FREE(facs); @@ -390,7 +391,7 @@ static DerivedMesh *normalEditModifier_do(NormalEditModifierData *smd, Object *o const bool use_current_clnors = !((smd->mix_mode == MOD_NORMALEDIT_MIX_COPY) && (smd->mix_factor == 1.0f) && (smd->defgrp_name[0] == '\0') && - (smd->mix_limit == M_PI)); + (smd->mix_limit == (float)M_PI)); int defgrp_index; MDeformVert *dvert; diff --git a/source/blender/python/bmesh/bmesh_py_api.c b/source/blender/python/bmesh/bmesh_py_api.c index eb1594688c7..d5973baeadb 100644 --- a/source/blender/python/bmesh/bmesh_py_api.c +++ b/source/blender/python/bmesh/bmesh_py_api.c @@ -207,20 +207,21 @@ PyObject *BPyInit_bmesh(void) /* bmesh.types */ PyModule_AddObject(mod, "types", (submodule = BPyInit_bmesh_types())); - PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); Py_INCREF(submodule); + /* bmesh.ops (not a real module, exposes module like access). */ PyModule_AddObject(mod, "ops", (submodule = BPyInit_bmesh_ops())); - /* PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); */ + /* PyDict_SetItemString(sys_modules, PyModule_GetNameObject(submodule), submodule); */ PyDict_SetItemString(sys_modules, "bmesh.ops", submodule); /* fake module */ Py_INCREF(submodule); PyModule_AddObject(mod, "utils", (submodule = BPyInit_bmesh_utils())); - PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); Py_INCREF(submodule); PyModule_AddObject(mod, "geometry", (submodule = BPyInit_bmesh_geometry())); - PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); Py_INCREF(submodule); return mod; diff --git a/source/blender/python/generic/idprop_py_api.c b/source/blender/python/generic/idprop_py_api.c index db8ed072722..11646f3f3df 100644 --- a/source/blender/python/generic/idprop_py_api.c +++ b/source/blender/python/generic/idprop_py_api.c @@ -1560,7 +1560,7 @@ PyObject *BPyInit_idprop(void) /* idprop.types */ PyModule_AddObject(mod, "types", (submodule = BPyInit_idprop_types())); - PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); Py_INCREF(submodule); return mod; diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index 7f13a7a4d94..72dec55e50b 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -177,7 +177,7 @@ PyObject *PyC_FromArray(const void *array, int length, const PyTypeObject *type, /** * Caller needs to ensure tuple is uninitialized. - * Handy for filling a typle with None for eg. + * Handy for filling a tuple with None for eg. */ void PyC_Tuple_Fill(PyObject *tuple, PyObject *value) { @@ -367,11 +367,12 @@ PyObject *PyC_FrozenSetFromStrings(const char **strings) } -/* similar to PyErr_Format(), +/** + * Similar to #PyErr_Format(), * - * implementation - we cant actually preprend the existing exception, + * Implementation - we cant actually prepend the existing exception, * because it could have _any_ arguments given to it, so instead we get its - * __str__ output and raise our own exception including it. + * ``__str__`` output and raise our own exception including it. */ PyObject *PyC_Err_Format_Prefix(PyObject *exception_type_prefix, const char *format, ...) { @@ -748,6 +749,7 @@ void PyC_RunQuicky(const char *filepath, int n, ...) /* set the value so we can access it */ PyDict_SetItemString(py_dict, "values", values); + Py_DECREF(values); py_result = PyRun_File(fp, filepath, Py_file_input, py_dict, py_dict); diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index 9f83bc94760..538ff7ba257 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -236,7 +236,7 @@ static int bpy_app_debug_set(PyObject *UNUSED(self), PyObject *value, void *clos PyDoc_STRVAR(bpy_app_binary_path_python_doc, "String, the path to the python executable (read-only)" ); -static PyObject *bpy_app_binary_path_python_get(PyObject *UNUSED(self), void *UNUSED(closure)) +static PyObject *bpy_app_binary_path_python_get(PyObject *self, void *UNUSED(closure)) { /* refcount is held in BlenderAppType.tp_dict */ static PyObject *ret = NULL; @@ -248,7 +248,7 @@ static PyObject *bpy_app_binary_path_python_get(PyObject *UNUSED(self), void *UN fullpath, sizeof(fullpath), PY_MAJOR_VERSION, PY_MINOR_VERSION); ret = PyC_UnicodeFromByte(fullpath); - PyDict_SetItemString(BlenderAppType.tp_dict, "binary_path_python", ret); + PyDict_SetItem(BlenderAppType.tp_dict, PyDescr_NAME(self), ret); } else { Py_INCREF(ret); @@ -363,10 +363,10 @@ static PyGetSetDef bpy_app_getsets[] = { static void py_struct_seq_getset_init(void) { /* tricky dynamic members, not to py-spec! */ - PyGetSetDef *getset; - - for (getset = bpy_app_getsets; getset->name; getset++) { - PyDict_SetItemString(BlenderAppType.tp_dict, getset->name, PyDescr_NewGetSet(&BlenderAppType, getset)); + for (PyGetSetDef *getset = bpy_app_getsets; getset->name; getset++) { + PyObject *item = PyDescr_NewGetSet(&BlenderAppType, getset); + PyDict_SetItem(BlenderAppType.tp_dict, PyDescr_NAME(item), item); + Py_DECREF(item); } } /* end dynamic bpy.app */ diff --git a/source/blender/python/intern/bpy_driver.c b/source/blender/python/intern/bpy_driver.c index 9b477e384db..65b6bd501ce 100644 --- a/source/blender/python/intern/bpy_driver.c +++ b/source/blender/python/intern/bpy_driver.c @@ -110,9 +110,11 @@ static void bpy_pydriver_update_dict(const float evaltime) bpy_pydriver_InternStr__frame = PyUnicode_FromString("frame"); } + PyObject *item = PyFloat_FromDouble(evaltime); PyDict_SetItem(bpy_pydriver_Dict, bpy_pydriver_InternStr__frame, - PyFloat_FromDouble(evaltime)); + item); + Py_DECREF(item); bpy_pydriver_evaltime_prev = evaltime; } @@ -301,7 +303,10 @@ float BPY_driver_exec(ChannelDriver *driver, const float evaltime) /* try to add to dictionary */ /* if (PyDict_SetItemString(driver_vars, dvar->name, driver_arg)) { */ - if (PyDict_SetItem(driver_vars, PyTuple_GET_ITEM(expr_vars, i++), driver_arg) < 0) { + if (PyDict_SetItem(driver_vars, PyTuple_GET_ITEM(expr_vars, i++), driver_arg) != -1) { + Py_DECREF(driver_arg); + } + else { /* this target failed - bad name */ if (targets_ok) { /* first one - print some extra info for easier identification */ diff --git a/source/blender/python/intern/bpy_library_load.c b/source/blender/python/intern/bpy_library_load.c index a120e4886e0..37a7e0e23dd 100644 --- a/source/blender/python/intern/bpy_library_load.c +++ b/source/blender/python/intern/bpy_library_load.c @@ -39,7 +39,6 @@ #include "BLO_readfile.h" -#include "BKE_global.h" #include "BKE_main.h" #include "BKE_library.h" #include "BKE_idcode.h" @@ -186,6 +185,7 @@ PyDoc_STRVAR(bpy_lib_load_doc, static PyObject *bpy_lib_load(PyObject *UNUSED(self), PyObject *args, PyObject *kwds) { static const char *kwlist[] = {"filepath", "link", "relative", NULL}; + Main *bmain = CTX_data_main(BPy_GetContext()); BPy_Library *ret; const char *filename = NULL; bool is_rel = false, is_link = false; @@ -204,7 +204,7 @@ static PyObject *bpy_lib_load(PyObject *UNUSED(self), PyObject *args, PyObject * BLI_strncpy(ret->relpath, filename, sizeof(ret->relpath)); BLI_strncpy(ret->abspath, filename, sizeof(ret->abspath)); - BLI_path_abs(ret->abspath, G.main->name); + BLI_path_abs(ret->abspath, bmain->name); ret->blo_handle = NULL; ret->flag = ((is_link ? FILE_LINK : 0) | @@ -222,19 +222,16 @@ static PyObject *_bpy_names(BPy_Library *self, int blocktype) int totnames; names = BLO_blendhandle_get_datablock_names(self->blo_handle, blocktype, &totnames); + list = PyList_New(totnames); if (names) { int counter = 0; - list = PyList_New(totnames); for (l = names; l; l = l->next) { PyList_SET_ITEM(list, counter, PyUnicode_FromString((char *)l->link)); counter++; } BLI_linklist_free(names, free); /* free linklist *and* each node's data */ } - else { - list = PyList_New(0); - } return list; } @@ -264,8 +261,13 @@ static PyObject *bpy_lib_enter(BPy_Library *self, PyObject *UNUSED(args)) if (BKE_idcode_is_linkable(code)) { const char *name_plural = BKE_idcode_to_name_plural(code); PyObject *str = PyUnicode_FromString(name_plural); - PyDict_SetItem(self->dict, str, PyList_New(0)); - PyDict_SetItem(from_dict, str, _bpy_names(self, code)); + PyObject *item; + + PyDict_SetItem(self->dict, str, item = PyList_New(0)); + Py_DECREF(item); + PyDict_SetItem(from_dict, str, item = _bpy_names(self, code)); + Py_DECREF(item); + Py_DECREF(str); } } @@ -346,48 +348,44 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) /* loop */ Py_ssize_t size = PyList_GET_SIZE(ls); Py_ssize_t i; - PyObject *item; - const char *item_str; for (i = 0; i < size; i++) { - item = PyList_GET_ITEM(ls, i); - item_str = _PyUnicode_AsString(item); + PyObject *item_src = PyList_GET_ITEM(ls, i); + PyObject *item_dst; /* must be set below */ + const char *item_idname = _PyUnicode_AsString(item_src); - // printf(" %s\n", item_str); + // printf(" %s\n", item_idname); - if (item_str) { - ID *id = BLO_library_link_named_part(mainl, &(self->blo_handle), idcode, item_str); + if (item_idname) { + ID *id = BLO_library_link_named_part(mainl, &(self->blo_handle), idcode, item_idname); if (id) { #ifdef USE_RNA_DATABLOCKS /* swap name for pointer to the id */ - Py_DECREF(item); - item = PyCapsule_New((void *)id, NULL, NULL); + item_dst = PyCapsule_New((void *)id, NULL, NULL); +#else + /* leave as is */ + continue; #endif } else { - bpy_lib_exit_warn_idname(self, name_plural, item_str); + bpy_lib_exit_warn_idname(self, name_plural, item_idname); /* just warn for now */ /* err = -1; */ -#ifdef USE_RNA_DATABLOCKS - item = Py_INCREF_RET(Py_None); -#endif + item_dst = Py_INCREF_RET(Py_None); } /* ID or None */ } else { /* XXX, could complain about this */ - bpy_lib_exit_warn_type(self, item); + bpy_lib_exit_warn_type(self, item_src); PyErr_Clear(); - -#ifdef USE_RNA_DATABLOCKS - item = Py_INCREF_RET(Py_None); -#endif + item_dst = Py_INCREF_RET(Py_None); } -#ifdef USE_RNA_DATABLOCKS - PyList_SET_ITEM(ls, i, item); -#endif + /* item_dst must be new or already incref'd */ + Py_DECREF(item_src); + PyList_SET_ITEM(ls, i, item_dst); } } } @@ -410,7 +408,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) /* copied from wm_operator.c */ { /* mark all library linked objects to be updated */ - BKE_main_lib_objects_recalc_all(G.main); + BKE_main_lib_objects_recalc_all(bmain); /* append, rather than linking */ if ((self->flag & FILE_LINK) == 0) { @@ -422,6 +420,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) /* finally swap the capsules for real bpy objects * important since BLO_library_append_end initializes NodeTree types used by srna->refine */ +#ifdef USE_RNA_DATABLOCKS { int idcode_step = 0, idcode; while ((idcode = BKE_idcode_iter_step(&idcode_step))) { @@ -451,6 +450,7 @@ static PyObject *bpy_lib_exit(BPy_Library *self, PyObject *UNUSED(args)) } } } +#endif /* USE_RNA_DATABLOCKS */ Py_RETURN_NONE; } diff --git a/source/blender/python/intern/bpy_operator.c b/source/blender/python/intern/bpy_operator.c index eaa96e6243c..bd3e5736c6c 100644 --- a/source/blender/python/intern/bpy_operator.c +++ b/source/blender/python/intern/bpy_operator.c @@ -223,9 +223,9 @@ static PyObject *pyop_call(PyObject *UNUSED(self), PyObject *args) WM_operator_properties_create_ptr(&ptr, ot); WM_operator_properties_sanitize(&ptr, 0); - if (kw && PyDict_Size(kw)) - error_val = pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: "); - + if (kw && PyDict_Size(kw)) { + error_val = pyrna_pydict_to_props(&ptr, kw, false, "Converting py args to operator properties: "); + } if (error_val == 0) { ReportList *reports; @@ -353,8 +353,9 @@ static PyObject *pyop_as_string(PyObject *UNUSED(self), PyObject *args) /* Save another lookup */ RNA_pointer_create(NULL, ot->srna, NULL, &ptr); - if (kw && PyDict_Size(kw)) - error_val = pyrna_pydict_to_props(&ptr, kw, 0, "Converting py args to operator properties: "); + if (kw && PyDict_Size(kw)) { + error_val = pyrna_pydict_to_props(&ptr, kw, false, "Converting py args to operator properties: "); + } if (error_val == 0) buf = WM_operator_pystring_ex(C, NULL, all_args, macro_args, ot, &ptr); diff --git a/source/blender/python/intern/bpy_props.c b/source/blender/python/intern/bpy_props.c index bce1d923462..3baeae0384a 100644 --- a/source/blender/python/intern/bpy_props.c +++ b/source/blender/python/intern/bpy_props.c @@ -2627,17 +2627,29 @@ PyDoc_STRVAR(BPy_EnumProperty_doc, " Returns a new enumerator property definition.\n" "\n" " :arg items: sequence of enum items formatted:\n" -" [(identifier, name, description, icon, number), ...] where the identifier is used\n" -" for python access and other values are used for the interface.\n" -" The three first elements of the tuples are mandatory.\n" -" The fourth one is either the (unique!) number id of the item or, if followed by a fith element\n" -" (which must be the numid), an icon string identifier or integer icon value (e.g. returned by icon()...).\n" -" Note the item is optional.\n" +" ``[(identifier, name, description, icon, number), ...]``.\n" +"\n" +" The first three elements of the tuples are mandatory.\n" +"\n" +" :identifier: The identifier is used for Python access.\n" +" :name: Name for the interace.\n" +" :description: Used for documentation and tooltips.\n" +" :icon: An icon string identifier or integer icon value\n" +" (e.g. returned by :class:`bpy.types.UILayout.icon`)\n" +" :number: Unique value used as the identifier for this item (stored in file data).\n" +" Use when the identifier may need to change.\n" +"\n" +" When an item only contains 4 items they define ``(identifier, name, description, number)``.\n" +"\n" " For dynamic values a callback can be passed which returns a list in\n" " the same format as the static list.\n" -" This function must take 2 arguments (self, context), **context may be None**.\n" -" WARNING: There is a known bug with using a callback,\n" -" Python must keep a reference to the strings returned or Blender will crash.\n" +" This function must take 2 arguments ``(self, context)``, **context may be None**.\n" +"\n" +" .. warning::\n" +"\n" +" There is a known bug with using a callback,\n" +" Python must keep a reference to the strings returned or Blender will crash.\n" +"\n" " :type items: sequence of string tuples or a function\n" BPY_PROPDEF_NAME_DOC BPY_PROPDEF_DESC_DOC @@ -2986,7 +2998,7 @@ static struct PyModuleDef props_module = { "This module defines properties to extend Blender's internal data. The result of these functions" " is used to assign properties to classes registered with Blender and can't be used directly.\n" "\n" - ".. warning:: All parameters to these functions must be passed as keywords.\n", + ".. note:: All parameters to these functions must be passed as keywords.\n", -1, /* multiple "initialization" just copies the module dict. */ props_methods, NULL, NULL, NULL, NULL diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 4bd30ba4dff..05bd55d3781 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -136,7 +136,9 @@ static void id_release_gc(struct ID *id) PyGC_Head *g = gen->gc.gc_next; while ((g = g->gc.gc_next) != gen) { PyObject *ob = FROM_GC(g); - if (PyType_IsSubtype(Py_TYPE(ob), &pyrna_struct_Type) || PyType_IsSubtype(Py_TYPE(ob), &pyrna_prop_Type)) { + if (PyType_IsSubtype(Py_TYPE(ob), &pyrna_struct_Type) || + PyType_IsSubtype(Py_TYPE(ob), &pyrna_prop_Type)) + { BPy_DummyPointerRNA *ob_ptr = (BPy_DummyPointerRNA *)ob; if (ob_ptr->ptr.id.data == id) { pyrna_invalidate(ob_ptr); @@ -358,9 +360,12 @@ static int deferred_register_prop(StructRNA *srna, PyObject *key, PyObject *item #ifdef USE_MATHUTILS #include "../mathutils/mathutils.h" /* so we can have mathutils callbacks */ -static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, - Py_ssize_t start, Py_ssize_t stop, Py_ssize_t length); -static short pyrna_rotation_euler_order_get(PointerRNA *ptr, PropertyRNA **prop_eul_order, const short order_fallback); +static PyObject *pyrna_prop_array_subscript_slice( + BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, + Py_ssize_t start, Py_ssize_t stop, Py_ssize_t length); +static short pyrna_rotation_euler_order_get( + PointerRNA *ptr, const short order_fallback, + PropertyRNA **r_prop_eul_order); /* bpyrna vector/euler/quat callbacks */ static unsigned char mathutils_rna_array_cb_index = -1; /* index for our callbacks */ @@ -395,7 +400,7 @@ static int mathutils_rna_vector_get(BaseMathObject *bmo, int subtype) if (subtype == MATHUTILS_CB_SUBTYPE_EUL) { EulerObject *eul = (EulerObject *)bmo; PropertyRNA *prop_eul_order = NULL; - eul->order = pyrna_rotation_euler_order_get(&self->ptr, &prop_eul_order, eul->order); + eul->order = pyrna_rotation_euler_order_get(&self->ptr, eul->order, &prop_eul_order); } return 0; @@ -442,7 +447,7 @@ static int mathutils_rna_vector_set(BaseMathObject *bmo, int subtype) if (subtype == MATHUTILS_CB_SUBTYPE_EUL) { EulerObject *eul = (EulerObject *)bmo; PropertyRNA *prop_eul_order = NULL; - short order = pyrna_rotation_euler_order_get(&self->ptr, &prop_eul_order, eul->order); + short order = pyrna_rotation_euler_order_get(&self->ptr, eul->order, &prop_eul_order); if (order != eul->order) { RNA_property_enum_set(&self->ptr, prop_eul_order, eul->order); if (RNA_property_update_check(prop_eul_order)) { @@ -562,16 +567,21 @@ static Mathutils_Callback mathutils_rna_matrix_cb = { NULL }; -static short pyrna_rotation_euler_order_get(PointerRNA *ptr, PropertyRNA **prop_eul_order, const short order_fallback) +static short pyrna_rotation_euler_order_get( + PointerRNA *ptr, const short order_fallback, + PropertyRNA **r_prop_eul_order) { /* attempt to get order */ - if (*prop_eul_order == NULL) - *prop_eul_order = RNA_struct_find_property(ptr, "rotation_mode"); + if (*r_prop_eul_order == NULL) { + *r_prop_eul_order = RNA_struct_find_property(ptr, "rotation_mode"); + } - if (*prop_eul_order) { - short order = RNA_property_enum_get(ptr, *prop_eul_order); - if (order >= EULER_ORDER_XYZ && order <= EULER_ORDER_ZYX) /* could be quat or axisangle */ + if (*r_prop_eul_order) { + short order = RNA_property_enum_get(ptr, *r_prop_eul_order); + /* could be quat or axisangle */ + if (order >= EULER_ORDER_XYZ && order <= EULER_ORDER_ZYX) { return order; + } } return order_fallback; @@ -639,7 +649,8 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) RNA_property_float_get_array(ptr, prop, ((VectorObject *)ret)->vec); } else { - PyObject *vec_cb = Vector_CreatePyObject_cb(ret, len, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_VEC); + PyObject *vec_cb = Vector_CreatePyObject_cb( + ret, len, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_VEC); Py_DECREF(ret); /* the vector owns now */ ret = vec_cb; /* return the vector instead */ } @@ -652,7 +663,8 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) RNA_property_float_get_array(ptr, prop, ((MatrixObject *)ret)->matrix); } else { - PyObject *mat_cb = Matrix_CreatePyObject_cb(ret, 4, 4, mathutils_rna_matrix_cb_index, 0); + PyObject *mat_cb = Matrix_CreatePyObject_cb( + ret, 4, 4, mathutils_rna_matrix_cb_index, 0); Py_DECREF(ret); /* the matrix owns now */ ret = mat_cb; /* return the matrix instead */ } @@ -663,7 +675,8 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) RNA_property_float_get_array(ptr, prop, ((MatrixObject *)ret)->matrix); } else { - PyObject *mat_cb = Matrix_CreatePyObject_cb(ret, 3, 3, mathutils_rna_matrix_cb_index, 0); + PyObject *mat_cb = Matrix_CreatePyObject_cb( + ret, 3, 3, mathutils_rna_matrix_cb_index, 0); Py_DECREF(ret); /* the matrix owns now */ ret = mat_cb; /* return the matrix instead */ } @@ -675,14 +688,16 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) if (is_thick) { /* attempt to get order, only needed for thick types since wrapped with update via callbacks */ PropertyRNA *prop_eul_order = NULL; - short order = pyrna_rotation_euler_order_get(ptr, &prop_eul_order, EULER_ORDER_XYZ); + short order = pyrna_rotation_euler_order_get(ptr, EULER_ORDER_XYZ, &prop_eul_order); ret = Euler_CreatePyObject(NULL, order, NULL); /* TODO, get order from RNA */ RNA_property_float_get_array(ptr, prop, ((EulerObject *)ret)->eul); } else { /* order will be updated from callback on use */ - PyObject *eul_cb = Euler_CreatePyObject_cb(ret, EULER_ORDER_XYZ, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_EUL); // TODO, get order from RNA + // TODO, get order from RNA + PyObject *eul_cb = Euler_CreatePyObject_cb( + ret, EULER_ORDER_XYZ, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_EUL); Py_DECREF(ret); /* the euler owns now */ ret = eul_cb; /* return the euler instead */ } @@ -693,7 +708,8 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) RNA_property_float_get_array(ptr, prop, ((QuaternionObject *)ret)->quat); } else { - PyObject *quat_cb = Quaternion_CreatePyObject_cb(ret, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_QUAT); + PyObject *quat_cb = Quaternion_CreatePyObject_cb( + ret, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_QUAT); Py_DECREF(ret); /* the quat owns now */ ret = quat_cb; /* return the quat instead */ } @@ -707,7 +723,8 @@ PyObject *pyrna_math_object_from_array(PointerRNA *ptr, PropertyRNA *prop) RNA_property_float_get_array(ptr, prop, ((ColorObject *)ret)->col); } else { - PyObject *col_cb = Color_CreatePyObject_cb(ret, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_COLOR); + PyObject *col_cb = Color_CreatePyObject_cb( + ret, mathutils_rna_array_cb_index, MATHUTILS_CB_SUBTYPE_COLOR); Py_DECREF(ret); /* the color owns now */ ret = col_cb; /* return the color instead */ } @@ -738,9 +755,11 @@ thick_wrap_slice: } /* same as RNA_enum_value_from_id but raises an exception */ -int pyrna_enum_value_from_id(EnumPropertyItem *item, const char *identifier, int *value, const char *error_prefix) +int pyrna_enum_value_from_id( + EnumPropertyItem *item, const char *identifier, int *r_value, + const char *error_prefix) { - if (RNA_enum_value_from_id(item, identifier, value) == 0) { + if (RNA_enum_value_from_id(item, identifier, r_value) == 0) { const char *enum_str = BPy_enum_as_string(item); PyErr_Format(PyExc_ValueError, "%s: '%.200s' not found in (%s)", @@ -1165,7 +1184,9 @@ static const char *pyrna_enum_as_string(PointerRNA *ptr, PropertyRNA *prop) } -static int pyrna_string_to_enum(PyObject *item, PointerRNA *ptr, PropertyRNA *prop, int *val, const char *error_prefix) +static int pyrna_string_to_enum( + PyObject *item, PointerRNA *ptr, PropertyRNA *prop, int *r_value, + const char *error_prefix) { const char *param = _PyUnicode_AsString(item); @@ -1176,7 +1197,7 @@ static int pyrna_string_to_enum(PyObject *item, PointerRNA *ptr, PropertyRNA *pr return -1; } else { - if (!RNA_property_enum_value(BPy_GetContext(), ptr, prop, param, val)) { + if (!RNA_property_enum_value(BPy_GetContext(), ptr, prop, param, r_value)) { const char *enum_str = pyrna_enum_as_string(ptr, prop); PyErr_Format(PyExc_TypeError, "%.200s enum \"%.200s\" not found in (%.200s)", @@ -1253,7 +1274,9 @@ error: } /* 'value' _must_ be a set type, error check before calling */ -int pyrna_set_to_enum_bitfield(EnumPropertyItem *items, PyObject *value, int *r_value, const char *error_prefix) +int pyrna_set_to_enum_bitfield( + EnumPropertyItem *items, PyObject *value, int *r_value, + const char *error_prefix) { /* set of enum items, concatenate all values with OR */ int ret, flag = 0; @@ -1286,7 +1309,9 @@ int pyrna_set_to_enum_bitfield(EnumPropertyItem *items, PyObject *value, int *r_ return 0; } -static int pyrna_prop_to_enum_bitfield(PointerRNA *ptr, PropertyRNA *prop, PyObject *value, int *r_value, const char *error_prefix) +static int pyrna_prop_to_enum_bitfield( + PointerRNA *ptr, PropertyRNA *prop, PyObject *value, int *r_value, + const char *error_prefix) { EnumPropertyItem *item; int ret; @@ -1505,9 +1530,13 @@ PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop) return ret; } -/* This function is used by operators and converting dicts into collections. - * Its takes keyword args and fills them with property values */ -int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, int all_args, const char *error_prefix) +/** + * This function is used by operators and converting dicts into collections. + * Its takes keyword args and fills them with property values + */ +int pyrna_pydict_to_props( + PointerRNA *ptr, PyObject *kw, const bool all_args, + const char *error_prefix) { int error_val = 0; int totkw; @@ -1582,7 +1611,9 @@ static PyObject *pyrna_func_to_py(const PointerRNA *ptr, FunctionRNA *func) } -static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value, const char *error_prefix) +static int pyrna_py_to_prop( + PointerRNA *ptr, PropertyRNA *prop, void *data, PyObject *value, + const char *error_prefix) { /* XXX hard limits should be checked here */ const int type = RNA_property_type(prop); @@ -1713,7 +1744,8 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb } else { /* same as unicode */ - if (data) *((char **)data) = (char *)param; /*XXX, this is suspect but needed for function calls, need to see if theres a better way */ + /* XXX, this is suspect but needed for function calls, need to see if theres a better way */ + if (data) *((char **)data) = (char *)param; else RNA_property_string_set(ptr, prop, param); } } @@ -1753,7 +1785,8 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb } else { /* same as bytes */ - if (data) *((char **)data) = (char *)param; /*XXX, this is suspect but needed for function calls, need to see if theres a better way */ + /* XXX, this is suspect but needed for function calls, need to see if theres a better way */ + if (data) *((char **)data) = (char *)param; else RNA_property_string_set(ptr, prop, param); } #ifdef USE_STRING_COERCE @@ -1801,8 +1834,8 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb * if the prop is not an operator type and the pyobject is an operator, * use its properties in place of its self. * - * this is so bad that its almost a good reason to do away with fake 'self.properties -> self' class mixing - * if this causes problems in the future it should be removed. + * this is so bad that its almost a good reason to do away with fake 'self.properties -> self' + * class mixing if this causes problems in the future it should be removed. */ if ((ptr_type == &RNA_AnyType) && (BPy_StructRNA_Check(value)) && @@ -1817,7 +1850,7 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb * forward back to pyrna_pydict_to_props */ if (RNA_struct_is_a(ptr_type, &RNA_OperatorProperties) && PyDict_Check(value)) { PointerRNA opptr = RNA_property_pointer_get(ptr, prop); - return pyrna_pydict_to_props(&opptr, value, 0, error_prefix); + return pyrna_pydict_to_props(&opptr, value, false, error_prefix); } /* another exception, allow to pass a collection as an RNA property */ @@ -1983,7 +2016,10 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb else RNA_property_collection_add(ptr, prop, &itemptr); - if (pyrna_pydict_to_props(&itemptr, item, 1, "Converting a python list to an RNA collection") == -1) { + if (pyrna_pydict_to_props( + &itemptr, item, true, + "Converting a python list to an RNA collection") == -1) + { PyObject *msg = PyC_ExceptionBuffer(); const char *msg_char = _PyUnicode_AsString(msg); @@ -2245,19 +2281,21 @@ static PyObject *pyrna_prop_collection_subscript_str(BPy_PropertyRNA *self, cons } /* static PyObject *pyrna_prop_array_subscript_str(BPy_PropertyRNA *self, char *keyname) */ -/* special case: bpy.data.objects["some_id_name", "//some_lib_name.blend"] - * also for: bpy.data.objects.get(("some_id_name", "//some_lib_name.blend"), fallback) +/** + * Special case: `bpy.data.objects["some_id_name", "//some_lib_name.blend"]` + * also for: `bpy.data.objects.get(("some_id_name", "//some_lib_name.blend"), fallback)` * - * note: + * \note * error codes since this is not to be called directly from python, - * this matches pythons __contains__ values capi. - * -1: exception set - * 0: not found - * 1: found */ -static int pyrna_prop_collection_subscript_str_lib_pair_ptr(BPy_PropertyRNA *self, PyObject *key, - const char *err_prefix, const short err_not_found, - PointerRNA *r_ptr - ) + * this matches pythons `__contains__` values capi. + * - -1: exception set + * - 0: not found + * - 1: found + */ +static int pyrna_prop_collection_subscript_str_lib_pair_ptr( + BPy_PropertyRNA *self, PyObject *key, + const char *err_prefix, const short err_not_found, + PointerRNA *r_ptr) { const char *keyname; @@ -2342,8 +2380,9 @@ static int pyrna_prop_collection_subscript_str_lib_pair_ptr(BPy_PropertyRNA *sel } } -static PyObject *pyrna_prop_collection_subscript_str_lib_pair(BPy_PropertyRNA *self, PyObject *key, - const char *err_prefix, const bool err_not_found) +static PyObject *pyrna_prop_collection_subscript_str_lib_pair( + BPy_PropertyRNA *self, PyObject *key, + const char *err_prefix, const bool err_not_found) { PointerRNA ptr; const int contains = pyrna_prop_collection_subscript_str_lib_pair_ptr(self, key, err_prefix, err_not_found, &ptr); @@ -2395,8 +2434,9 @@ static PyObject *pyrna_prop_collection_subscript_slice(BPy_PropertyRNA *self, Py * note: could also use pyrna_prop_array_to_py_index(self, count) in a loop but its a lot slower * since at the moment it reads (and even allocates) the entire array for each index. */ -static PyObject *pyrna_prop_array_subscript_slice(BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, - Py_ssize_t start, Py_ssize_t stop, Py_ssize_t length) +static PyObject *pyrna_prop_array_subscript_slice( + BPy_PropertyArrayRNA *self, PointerRNA *ptr, PropertyRNA *prop, + Py_ssize_t start, Py_ssize_t stop, Py_ssize_t length) { int count, totdim; PyObject *tuple; @@ -4588,9 +4628,10 @@ static PyObject *pyrna_prop_collection_find(BPy_PropertyRNA *self, PyObject *key return PyLong_FromLong(index); } -static bool foreach_attr_type(BPy_PropertyRNA *self, const char *attr, - /* values to assign */ - RawPropertyType *raw_type, int *attr_tot, bool *attr_signed) +static bool foreach_attr_type( + BPy_PropertyRNA *self, const char *attr, + /* values to assign */ + RawPropertyType *raw_type, int *attr_tot, bool *attr_signed) { PropertyRNA *prop; bool attr_ok = true; @@ -4618,12 +4659,12 @@ static bool foreach_attr_type(BPy_PropertyRNA *self, const char *attr, } /* pyrna_prop_collection_foreach_get/set both use this */ -static int foreach_parse_args(BPy_PropertyRNA *self, PyObject *args, +static int foreach_parse_args( + BPy_PropertyRNA *self, PyObject *args, - /* values to assign */ - const char **attr, PyObject **seq, int *tot, int *size, - RawPropertyType *raw_type, int *attr_tot, bool *attr_signed - ) + /* values to assign */ + const char **attr, PyObject **seq, int *tot, int *size, + RawPropertyType *raw_type, int *attr_tot, bool *attr_signed) { #if 0 int array_tot; @@ -7500,7 +7541,8 @@ static int bpy_class_call(bContext *C, PointerRNA *ptr, FunctionRNA *func, Param } } - if (err != -1 && (is_staticmethod || is_classmethod || py_class_instance)) { /* Initializing the class worked, now run its invoke function */ + /* Initializing the class worked, now run its invoke function */ + if (err != -1 && (is_staticmethod || is_classmethod || py_class_instance)) { PyObject *item = PyObject_GetAttrString((PyObject *)py_class, RNA_function_identifier(func)); if (item) { @@ -7913,7 +7955,9 @@ static PyObject *pyrna_register_class(PyObject *UNUSED(self), PyObject *py_class } -static int pyrna_srna_contains_pointer_prop_srna(StructRNA *srna_props, StructRNA *srna, const char **prop_identifier) +static int pyrna_srna_contains_pointer_prop_srna( + StructRNA *srna_props, StructRNA *srna, + const char **r_prop_identifier) { PropertyRNA *prop; LinkData *link; @@ -7928,7 +7972,7 @@ static int pyrna_srna_contains_pointer_prop_srna(StructRNA *srna_props, StructRN RNA_pointer_create(NULL, &RNA_Struct, srna_props, &tptr); if (RNA_property_pointer_type(&tptr, prop) == srna) { - *prop_identifier = RNA_property_identifier(prop); + *r_prop_identifier = RNA_property_identifier(prop); return 1; } } diff --git a/source/blender/python/intern/bpy_rna.h b/source/blender/python/intern/bpy_rna.h index c5d4a346f56..e38d4f095d6 100644 --- a/source/blender/python/intern/bpy_rna.h +++ b/source/blender/python/intern/bpy_rna.h @@ -181,7 +181,7 @@ PyObject *pyrna_id_CreatePyObject(struct ID *id); bool pyrna_id_FromPyObject(PyObject *obj, struct ID **id); /* operators also need this to set args */ -int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, int all_args, const char *error_prefix); +int pyrna_pydict_to_props(PointerRNA *ptr, PyObject *kw, const bool all_args, const char *error_prefix); PyObject *pyrna_prop_to_py(PointerRNA *ptr, PropertyRNA *prop); unsigned int *pyrna_set_to_enum_bitmap( diff --git a/source/blender/python/intern/gpu.c b/source/blender/python/intern/gpu.c index c3bb588f7eb..50dd4618166 100644 --- a/source/blender/python/intern/gpu.c +++ b/source/blender/python/intern/gpu.c @@ -330,10 +330,10 @@ PyObject *GPU_initPython(void) /* gpu.offscreen */ PyModule_AddObject(module, "offscreen", (submodule = BPyInit_gpu_offscreen())); - PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); Py_INCREF(submodule); - PyDict_SetItemString(PyImport_GetModuleDict(), "gpu", module); + PyDict_SetItem(PyImport_GetModuleDict(), PyModule_GetNameObject(module), module); return module; } diff --git a/source/blender/python/mathutils/mathutils.c b/source/blender/python/mathutils/mathutils.c index 635090869ea..5c505247a97 100644 --- a/source/blender/python/mathutils/mathutils.c +++ b/source/blender/python/mathutils/mathutils.c @@ -638,30 +638,30 @@ PyMODINIT_FUNC PyInit_mathutils(void) /* XXX, python doesnt do imports with this usefully yet * 'from mathutils.geometry import PolyFill' * ...fails without this. */ - PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); Py_INCREF(submodule); PyModule_AddObject(mod, "interpolate", (submodule = PyInit_mathutils_interpolate())); /* XXX, python doesnt do imports with this usefully yet * 'from mathutils.geometry import PolyFill' * ...fails without this. */ - PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); Py_INCREF(submodule); #ifndef MATH_STANDALONE /* Noise submodule */ PyModule_AddObject(mod, "noise", (submodule = PyInit_mathutils_noise())); - PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); Py_INCREF(submodule); /* BVHTree submodule */ PyModule_AddObject(mod, "bvhtree", (submodule = PyInit_mathutils_bvhtree())); - PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); Py_INCREF(submodule); /* KDTree submodule */ PyModule_AddObject(mod, "kdtree", (submodule = PyInit_mathutils_kdtree())); - PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule); + PyDict_SetItem(sys_modules, PyModule_GetNameObject(submodule), submodule); Py_INCREF(submodule); #endif diff --git a/source/blender/quicktime/apple/qtkit_import.m b/source/blender/quicktime/apple/qtkit_import.m index d42d0ee8ebb..ba7ee0a8936 100644 --- a/source/blender/quicktime/apple/qtkit_import.m +++ b/source/blender/quicktime/apple/qtkit_import.m @@ -200,7 +200,7 @@ static ImBuf *nsImageToiBuf(NSImage *sourceImage, int width, int height) /* Convert the image in a RGBA 32bit format */ /* As Core Graphics does not support contextes with non premutliplied alpha, - we need to get alpha key values in a separate batch */ + * we need to get alpha key values in a separate batch */ /* First get RGB values w/o Alpha to avoid pre-multiplication, 32bit but last byte is unused */ blBitmapFormatImageRGB = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:NULL diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index ce0691b7632..39f62f9fc33 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -231,8 +231,9 @@ struct RenderStats *RE_GetStats(struct Render *re); void RE_ResultGet32(struct Render *re, unsigned int *rect); void RE_AcquiredResultGet32(struct Render *re, struct RenderResult *result, unsigned int *rect, const int view_id); -void RE_render_result_rect_from_ibuf(struct RenderResult *rr, struct RenderData *rd, - struct ImBuf *ibuf, const int view_id); +void RE_render_result_rect_from_ibuf( + struct RenderResult *rr, struct RenderData *rd, + struct ImBuf *ibuf, const int view_id); struct RenderLayer *RE_GetRenderLayer(struct RenderResult *rr, const char *name); float *RE_RenderLayerGetPass(volatile struct RenderLayer *rl, int passtype, const char *viewname); @@ -249,8 +250,8 @@ struct Object *RE_GetCamera(struct Render *re); /* return camera override if set void RE_SetOverrideCamera(struct Render *re, struct Object *camera); void RE_SetCamera(struct Render *re, struct Object *camera); void RE_SetEnvmapCamera(struct Render *re, struct Object *cam_ob, float viewscale, float clipsta, float clipend); -void RE_SetWindow(struct Render *re, rctf *viewplane, float clipsta, float clipend); -void RE_SetOrtho(struct Render *re, rctf *viewplane, float clipsta, float clipend); +void RE_SetWindow(struct Render *re, const rctf *viewplane, float clipsta, float clipend); +void RE_SetOrtho(struct Render *re, const rctf *viewplane, float clipsta, float clipend); void RE_SetPixelSize(struct Render *re, float pixsize); /* option to set viewmatrix before making dbase */ @@ -258,10 +259,12 @@ void RE_SetView(struct Render *re, float mat[4][4]); /* get current view and window transform */ void RE_GetView(struct Render *re, float mat[4][4]); -void RE_GetViewPlane(struct Render *re, rctf *viewplane, rcti *disprect); +void RE_GetViewPlane(struct Render *re, rctf *r_viewplane, rcti *r_disprect); /* make or free the dbase */ -void RE_Database_FromScene(struct Render *re, struct Main *bmain, struct Scene *scene, unsigned int lay, int use_camera_view); +void RE_Database_FromScene( + struct Render *re, struct Main *bmain, struct Scene *scene, + unsigned int lay, int use_camera_view); void RE_Database_Preprocess(struct Render *re); void RE_Database_Free(struct Render *re); @@ -304,11 +307,16 @@ void RE_SetReports(struct Render *re, struct ReportList *reports); void RE_PreviewRender(struct Render *re, struct Main *bmain, struct Scene *scene); bool RE_ReadRenderResult(struct Scene *scene, struct Scene *scenode); -bool RE_WriteRenderResult(struct ReportList *reports, RenderResult *rr, const char *filename, struct ImageFormatData *imf, const bool multiview, const char *view); -struct RenderResult *RE_MultilayerConvert(void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty); +bool RE_WriteRenderResult( + struct ReportList *reports, RenderResult *rr, const char *filename, + struct ImageFormatData *imf, const bool multiview, const char *view); +struct RenderResult *RE_MultilayerConvert( + void *exrhandle, const char *colorspace, bool predivide, int rectx, int recty); extern const float default_envmap_layout[]; -bool RE_WriteEnvmapResult(struct ReportList *reports, struct Scene *scene, struct EnvMap *env, const char *relpath, const char imtype, float layout[12]); +bool RE_WriteEnvmapResult( + struct ReportList *reports, struct Scene *scene, struct EnvMap *env, + const char *relpath, const char imtype, float layout[12]); /* do a full sample buffer compo */ void RE_MergeFullSample(struct Render *re, struct Main *bmain, struct Scene *sce, struct bNodeTree *ntree); @@ -326,7 +334,9 @@ void RE_current_scene_update_cb(struct Render *re, void *handle, void (*f)(void /* should move to kernel once... still unsure on how/where */ float RE_filter_value(int type, float x); /* vector blur zbuffer method */ -void RE_zbuf_accumulate_vecblur(struct NodeBlurData *nbd, int xsize, int ysize, float *newrect, float *imgrect, float *vecbufrect, float *zbufrect); +void RE_zbuf_accumulate_vecblur( + struct NodeBlurData *nbd, int xsize, int ysize, float *newrect, + const float *imgrect, float *vecbufrect, const float *zbufrect); int RE_seq_render_active(struct Scene *scene, struct RenderData *rd); @@ -351,7 +361,9 @@ struct RenderPass *RE_pass_find_by_type(volatile struct RenderLayer *rl, int pas #define RE_BAKE_DERIVATIVE 13 #define RE_BAKE_VERTEX_COLORS 14 -void RE_Database_Baking(struct Render *re, struct Main *bmain, struct Scene *scene, unsigned int lay, const int type, struct Object *actob); +void RE_Database_Baking( + struct Render *re, struct Main *bmain, struct Scene *scene, + unsigned int lay, const int type, struct Object *actob); void RE_DataBase_GetView(struct Render *re, float mat[4][4]); void RE_GetCameraWindow(struct Render *re, struct Object *camera, int frame, float mat[4][4]); diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 6de5da3795a..b3a5ccdae17 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -180,6 +180,7 @@ struct Render { float jit[32][2]; float mblur_jit[32][2]; ListBase *qmcsamplers; + int num_qmc_samplers; /* shadow counter, detect shadow-reuse for shaders */ int shadowsamplenr[BLENDER_MAX_THREADS]; diff --git a/source/blender/render/intern/include/rendercore.h b/source/blender/render/intern/include/rendercore.h index 308903c6c6d..7254fd25ee6 100644 --- a/source/blender/render/intern/include/rendercore.h +++ b/source/blender/render/intern/include/rendercore.h @@ -90,7 +90,7 @@ extern void ray_shadow(ShadeInput *shi, LampRen *lar, float shadfac[4]); extern void ray_trace(ShadeInput *shi, ShadeResult *); extern void ray_ao(ShadeInput *shi, float ao[3], float env[3]); extern void init_jitter_plane(LampRen *lar); -extern void init_ao_sphere(struct World *wrld); +extern void init_ao_sphere(Render *re, struct World *wrld); extern void init_render_qmcsampler(Render *re); extern void free_render_qmcsampler(Render *re); diff --git a/source/blender/render/intern/raytrace/rayobject.cpp b/source/blender/render/intern/raytrace/rayobject.cpp index f511042749e..2104315dc00 100644 --- a/source/blender/render/intern/raytrace/rayobject.cpp +++ b/source/blender/render/intern/raytrace/rayobject.cpp @@ -145,8 +145,8 @@ MALWAYS_INLINE int isec_tri_quad(float start[3], const struct IsectRayPrecalc *i if (isect_ray_tri_watertight_v3(start, isect_precalc, face->v1, face->v2, face->v3, &l, uv)) { /* check if intersection is within ray length */ if (l > -RE_RAYTRACE_EPSILON && l < *lambda) { - r_uv[0] = uv[0]; - r_uv[1] = uv[1]; + r_uv[0] = -uv[0]; + r_uv[1] = -uv[1]; *lambda = l; return 1; } @@ -157,8 +157,8 @@ MALWAYS_INLINE int isec_tri_quad(float start[3], const struct IsectRayPrecalc *i if (isect_ray_tri_watertight_v3(start, isect_precalc, face->v1, face->v3, face->v4, &l, uv)) { /* check if intersection is within ray length */ if (l > -RE_RAYTRACE_EPSILON && l < *lambda) { - r_uv[0] = uv[0]; - r_uv[1] = uv[1]; + r_uv[0] = -uv[0]; + r_uv[1] = -uv[1]; *lambda = l; return 2; } diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index 907974e20dc..86961cdd169 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -4192,7 +4192,7 @@ static void split_quads(ObjectRen *obr, int dir) vlr= RE_findOrAddVlak(obr, a); /* test if rendering as a quad or triangle, skip wire */ - if (vlr->v4 && (vlr->flag & R_STRAND)==0 && (vlr->mat->material_type != MA_TYPE_WIRE)) { + if ((vlr->flag & R_STRAND)==0 && (vlr->mat->material_type != MA_TYPE_WIRE)) { if (vlr->v4) { @@ -5230,7 +5230,7 @@ void RE_Database_FromScene(Render *re, Main *bmain, Scene *scene, unsigned int l if (re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) if (re->wrld.ao_samp_method == WO_AOSAMP_CONSTANT) - init_ao_sphere(&re->wrld); + init_ao_sphere(re, &re->wrld); } /* still bad... doing all */ @@ -5956,7 +5956,7 @@ void RE_Database_Baking(Render *re, Main *bmain, Scene *scene, unsigned int lay, if (re->wrld.mode & (WO_AMB_OCC|WO_ENV_LIGHT|WO_INDIRECT_LIGHT)) if (re->wrld.ao_samp_method == WO_AOSAMP_CONSTANT) - init_ao_sphere(&re->wrld); + init_ao_sphere(re, &re->wrld); } /* still bad... doing all */ diff --git a/source/blender/render/intern/source/occlusion.c b/source/blender/render/intern/source/occlusion.c index c5c3b6bbf94..b3d31e3b93a 100644 --- a/source/blender/render/intern/source/occlusion.c +++ b/source/blender/render/intern/source/occlusion.c @@ -115,6 +115,8 @@ typedef struct OcclusionTree { int doindirect; OcclusionCache *cache; + + int num_threads; } OcclusionTree; typedef struct OcclusionThread { @@ -641,6 +643,7 @@ static void occ_build_sh_normalize(OccNode *node) static OcclusionTree *occ_tree_build(Render *re) { + const int num_threads = re->r.threads; OcclusionTree *tree; ObjectInstanceRen *obi; ObjectRen *obr; @@ -679,7 +682,7 @@ static OcclusionTree *occ_tree_build(Render *re) BLI_memarena_use_calloc(tree->arena); if (re->wrld.aomode & WO_AOCACHE) - tree->cache = MEM_callocN(sizeof(OcclusionCache) * BLENDER_MAX_THREADS, "OcclusionCache"); + tree->cache = MEM_callocN(sizeof(OcclusionCache) * num_threads, "OcclusionCache"); tree->face = MEM_callocN(sizeof(OccFace) * totface, "OcclusionFace"); tree->co = MEM_callocN(sizeof(float) * 3 * totface, "OcclusionCo"); @@ -730,9 +733,11 @@ static OcclusionTree *occ_tree_build(Render *re) if (!(re->test_break(re->tbh))) occ_build_sh_normalize(tree->root); - for (a = 0; a < BLENDER_MAX_THREADS; a++) + for (a = 0; a < num_threads; a++) tree->stack[a] = MEM_callocN(sizeof(OccNode) * TOTCHILD * (tree->maxdepth + 1), "OccStack"); + tree->num_threads = num_threads; + return tree; } @@ -742,7 +747,7 @@ static void occ_free_tree(OcclusionTree *tree) if (tree) { if (tree->arena) BLI_memarena_free(tree->arena); - for (a = 0; a < BLENDER_MAX_THREADS; a++) + for (a = 0; a < tree->num_threads; a++) if (tree->stack[a]) MEM_freeN(tree->stack[a]); if (tree->occlusion) MEM_freeN(tree->occlusion); diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 6b910dc9fc4..1ee905c596c 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -355,7 +355,7 @@ Scene *RE_GetScene(Render *re) * Same as #RE_AcquireResultImage but creating the necessary views to store the result * fill provided result struct with a copy of thew views of what is done so far the * #RenderResult.views #ListBase needs to be freed after with #RE_ReleaseResultImageViews -*/ + */ void RE_AcquireResultImageViews(Render *re, RenderResult *rr) { memset(rr, 0, sizeof(RenderResult)); @@ -931,7 +931,7 @@ void render_update_anim_renderdata(Render *re, RenderData *rd) BLI_duplicatelist(&re->r.views, &rd->views); } -void RE_SetWindow(Render *re, rctf *viewplane, float clipsta, float clipend) +void RE_SetWindow(Render *re, const rctf *viewplane, float clipsta, float clipend) { /* re->ok flag? */ @@ -946,7 +946,7 @@ void RE_SetWindow(Render *re, rctf *viewplane, float clipsta, float clipend) } -void RE_SetOrtho(Render *re, rctf *viewplane, float clipsta, float clipend) +void RE_SetOrtho(Render *re, const rctf *viewplane, float clipsta, float clipend) { /* re->ok flag? */ @@ -967,15 +967,17 @@ void RE_SetView(Render *re, float mat[4][4]) invert_m4_m4(re->viewinv, re->viewmat); } -void RE_GetViewPlane(Render *re, rctf *viewplane, rcti *disprect) +void RE_GetViewPlane(Render *re, rctf *r_viewplane, rcti *r_disprect) { - *viewplane = re->viewplane; + *r_viewplane = re->viewplane; /* make disprect zero when no border render, is needed to detect changes in 3d view render */ - if (re->r.mode & R_BORDER) - *disprect = re->disprect; - else - BLI_rcti_init(disprect, 0, 0, 0, 0); + if (re->r.mode & R_BORDER) { + *r_disprect = re->disprect; + } + else { + BLI_rcti_init(r_disprect, 0, 0, 0, 0); + } } void RE_GetView(Render *re, float mat[4][4]) diff --git a/source/blender/render/intern/source/rayshade.c b/source/blender/render/intern/source/rayshade.c index 9aac5ed1f1d..26a0b0c71b4 100644 --- a/source/blender/render/intern/source/rayshade.c +++ b/source/blender/render/intern/source/rayshade.c @@ -174,10 +174,11 @@ void freeraytree(Render *re) #ifdef RE_RAYCOUNTER { + const int num_threads = re->r.threads; RayCounter sum; memset(&sum, 0, sizeof(sum)); int i; - for (i=0; i<BLENDER_MAX_THREADS; i++) + for (i=0; i<num_threads; i++) RE_RC_MERGE(&sum, re_rc_counter+i); RE_RC_INFO(&sum); } @@ -1186,7 +1187,9 @@ static void QMC_sampleHemiCosine(float vec[3], QMCSampler *qsa, int thread, int /* called from convertBlenderScene.c */ void init_render_qmcsampler(Render *re) { - re->qmcsamplers= MEM_callocN(sizeof(ListBase)*BLENDER_MAX_THREADS, "QMCListBase"); + const int num_threads = re->r.threads; + re->qmcsamplers= MEM_callocN(sizeof(ListBase)*num_threads, "QMCListBase"); + re->num_qmc_samplers = num_threads; } static QMCSampler *get_thread_qmcsampler(Render *re, int thread, int type, int tot) @@ -1220,7 +1223,7 @@ void free_render_qmcsampler(Render *re) if (re->qmcsamplers) { QMCSampler *qsa, *next; int a; - for (a=0; a<BLENDER_MAX_THREADS; a++) { + for (a = 0; a < re->num_qmc_samplers; a++) { for (qsa=re->qmcsamplers[a].first; qsa; qsa=next) { next= qsa->next; QMC_freeSampler(qsa); @@ -1695,9 +1698,10 @@ static void DS_energy(float *sphere, int tot, float vec[3]) /* called from convertBlenderScene.c */ /* creates an equally distributed spherical sample pattern */ /* and allocates threadsafe memory */ -void init_ao_sphere(World *wrld) +void init_ao_sphere(Render *re, World *wrld) { /* fixed random */ + const int num_threads = re->r.threads; RNG *rng; float *fp; int a, tot, iter= 16; @@ -1721,7 +1725,7 @@ void init_ao_sphere(World *wrld) } /* tables */ - wrld->aotables= MEM_mallocN(BLENDER_MAX_THREADS*3*tot*sizeof(float), "AO tables"); + wrld->aotables= MEM_mallocN(num_threads*3*tot*sizeof(float), "AO tables"); BLI_rng_free(rng); } diff --git a/source/blender/render/intern/source/render_texture.c b/source/blender/render/intern/source/render_texture.c index 513cfa6df7d..b4a14f5337d 100644 --- a/source/blender/render/intern/source/render_texture.c +++ b/source/blender/render/intern/source/render_texture.c @@ -3653,7 +3653,8 @@ void render_realtime_texture(ShadeInput *shi, Image *ima) if (firsttime) { BLI_lock_thread(LOCK_IMAGE); if (firsttime) { - for (a=0; a<BLENDER_MAX_THREADS; a++) { + const int num_threads = BLI_system_thread_count(); + for (a = 0; a < num_threads; a++) { memset(&imatex[a], 0, sizeof(Tex)); BKE_texture_default(&imatex[a]); imatex[a].type= TEX_IMAGE; diff --git a/source/blender/render/intern/source/renderdatabase.c b/source/blender/render/intern/source/renderdatabase.c index d3d26011a57..76e6ca8d467 100644 --- a/source/blender/render/intern/source/renderdatabase.c +++ b/source/blender/render/intern/source/renderdatabase.c @@ -1006,7 +1006,7 @@ HaloRen *RE_inithalo(Render *re, ObjectRen *obr, Material *ma, xn= har->xs - 0.5f*re->winx*(hoco1[0]/hoco1[3]); yn= har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]); - if (xn==0.0f || (xn==0.0f && yn==0.0f)) zn= 0.0f; + if (yn == 0.0f && xn >= 0.0f) zn = 0.0f; else zn = atan2f(yn, xn); har->sin = sinf(zn); @@ -1136,7 +1136,7 @@ HaloRen *RE_inithalo_particle(Render *re, ObjectRen *obr, DerivedMesh *dm, Mater xn= har->xs - 0.5f*re->winx*(hoco1[0]/hoco1[3]); yn= har->ys - 0.5f*re->winy*(hoco1[1]/hoco1[3]); - if (xn==0.0f || (xn==0.0f && yn==0.0f)) zn= 0.0; + if (yn == 0.0f && xn >= 0.0f) zn = 0.0f; else zn = atan2f(yn, xn); har->sin = sinf(zn); diff --git a/source/blender/render/intern/source/sss.c b/source/blender/render/intern/source/sss.c index 553710b4367..26ca3ad50e0 100644 --- a/source/blender/render/intern/source/sss.c +++ b/source/blender/render/intern/source/sss.c @@ -279,13 +279,19 @@ static void build_Rd_table(ScatterSettings *ss) for (i= 0; i < size; i++) { r= i*(RD_TABLE_RANGE/RD_TABLE_SIZE); - /*if (r < ss->invsigma_t_*ss->invsigma_t_) - r= ss->invsigma_t_*ss->invsigma_t_;*/ +#if 0 + if (r < ss->invsigma_t_*ss->invsigma_t_) { + r= ss->invsigma_t_*ss->invsigma_t_; + } +#endif ss->tableRd[i]= Rd(ss, sqrtf(r)); r= i*(RD_TABLE_RANGE_2/RD_TABLE_SIZE); - /*if (r < ss->invsigma_t_) - r= ss->invsigma_t_;*/ +#if 0 + if (r < ss->invsigma_t_) { + r= ss->invsigma_t_; + } +#endif ss->tableRd2[i]= Rd(ss, r); } } diff --git a/source/blender/render/intern/source/zbuf.c b/source/blender/render/intern/source/zbuf.c index d3a1dcfd8ce..9f777631e52 100644 --- a/source/blender/render/intern/source/zbuf.c +++ b/source/blender/render/intern/source/zbuf.c @@ -2883,14 +2883,17 @@ static void set_quad_bezier_ipo(float fac, float *data) data[2]= fac*fac; } -void RE_zbuf_accumulate_vecblur(NodeBlurData *nbd, int xsize, int ysize, float *newrect, float *imgrect, float *vecbufrect, float *zbufrect) +void RE_zbuf_accumulate_vecblur( + NodeBlurData *nbd, int xsize, int ysize, float *newrect, + const float *imgrect, float *vecbufrect, const float *zbufrect) { ZSpan zspan; DrawBufPixel *rectdraw, *dr; static float jit[256][2]; float v1[3], v2[3], v3[3], v4[3], fx, fy; - float *rectvz, *dvz, *dimg, *dvec1, *dvec2, *dz, *dz1, *dz2, *rectz; - float *minvecbufrect= NULL, *rectweight, *rw, *rectmax, *rm, *ro; + const float *dimg, *dz, *ro; + float *rectvz, *dvz, *dvec1, *dvec2, *dz1, *dz2, *rectz; + float *minvecbufrect= NULL, *rectweight, *rw, *rectmax, *rm; float maxspeedsq= (float)nbd->maxspeed*nbd->maxspeed; int y, x, step, maxspeed=nbd->maxspeed, samples= nbd->samples; int tsktsk= 0; diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 3fbbea72046..127525bb857 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -114,6 +114,8 @@ void WM_autosave_init(struct wmWindowManager *wm); void WM_recover_last_session(struct bContext *C, struct ReportList *reports); void WM_file_tag_modified(const struct bContext *C); +void WM_lib_reload(struct Library *lib, struct bContext *C, struct ReportList *reports); + /* mouse cursors */ void WM_cursor_set(struct wmWindow *win, int curs); void WM_cursor_modal_set(struct wmWindow *win, int curs); diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 4a48143b87b..51fbabac638 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -52,7 +52,7 @@ #include "RNA_access.h" -#include "BKE_asset.h" +#include "BKE_asset_engine.h" #include "BKE_context.h" #include "BKE_idprop.h" #include "BKE_global.h" diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 638d6fe96d2..a85e39ac65e 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -482,8 +482,6 @@ static void wm_file_read_post(bContext *C, bool is_startup_file) BPY_python_reset(C); addons_loaded = true; } -#else - UNUSED_VARS(is_startup_file); #endif /* WITH_PYTHON */ WM_operatortype_last_properties_clear_all(); @@ -492,8 +490,12 @@ static void wm_file_read_post(bContext *C, bool is_startup_file) BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_VERSION_UPDATE); BLI_callback_exec(CTX_data_main(C), NULL, BLI_CB_EVT_LOAD_POST); - /* would otherwise be handled by event loop */ - if (G.background) { + /* Would otherwise be handled by event loop. + * + * Disabled for startup file, since it causes problems when PyDrivers are used in the startup file. + * While its possible state of startup file may be wrong, + * in this case users nearly always load a file to replace the startup file. */ + if (G.background && (is_startup_file == false)) { Main *bmain = CTX_data_main(C); BKE_scene_update_tagged(bmain->eval_ctx, bmain, CTX_data_scene(C)); } diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c index f3792e0bac6..8195212f3c3 100644 --- a/source/blender/windowmanager/intern/wm_files_link.c +++ b/source/blender/windowmanager/intern/wm_files_link.c @@ -62,7 +62,7 @@ #include "BLO_readfile.h" -#include "BKE_asset.h" +#include "BKE_asset_engine.h" #include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_library.h" @@ -691,9 +691,13 @@ static int wm_lib_relocate_invoke(bContext *C, wmOperator *op, const wmEvent *UN return OPERATOR_CANCELLED; } -/* Note that IDs listed in lapp_data items *must* have been removed from bmain by caller. */ +/** + * \param library if given, all IDs from that library will be removed and reloaded. Otherwise, IDs must have already + * been removed from \a bmain, and added to \a lapp_data. + */ static void lib_relocate_do( - Main *bmain, WMLinkAppendData *lapp_data, ReportList *reports, AssetEngineType *aet, const bool do_reload) + Main *bmain, Scene *scene, + Library *library, WMLinkAppendData *lapp_data, ReportList *reports, AssetEngineType *aet, const bool do_reload) { ListBase *lbarray[MAX_LIBARRAY]; int lba_idx; @@ -701,6 +705,36 @@ static void lib_relocate_do( LinkNode *itemlink; int item_idx; + /* Remove all IDs to be reloaded from Main. */ + if (library) { + lba_idx = set_listbasepointers(bmain, lbarray); + while (lba_idx--) { + ID *id = lbarray[lba_idx]->first; + const short idcode = id ? GS(id->name) : 0; + + if (!id || !BKE_idcode_is_linkable(idcode)) { + /* No need to reload non-linkable datatypes, those will get relinked with their 'users ID'. */ + continue; + } + + for (; id; id = id->next) { + if (id->lib == library) { + WMLinkAppendDataItem *item; + + /* We remove it from current Main, and add it to items to link... */ + /* Note that non-linkable IDs (like e.g. shapekeys) are also explicitely linked here... */ + BLI_remlink(lbarray[lba_idx], id); + item = wm_link_append_data_item_add(lapp_data, id->name + 2, idcode, NULL, id); + BLI_BITMAP_SET_ALL(item->libraries, true, lapp_data->num_libraries); + +#ifdef PRINT_DEBUG + printf("\tdatablock to seek for: %s\n", id->name); +#endif + } + } + } + } + BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, true); /* We do not want any instanciation here! */ @@ -839,6 +873,43 @@ static void lib_relocate_do( } } } + + BKE_main_lib_objects_recalc_all(bmain); + IMB_colormanagement_check_file_config(bmain); + + /* important we unset, otherwise these object wont + * link into other scenes from this blend file */ + BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); + + /* recreate dependency graph to include new objects */ + DAG_scene_relations_rebuild(bmain, scene); + + /* free gpu materials, some materials depend on existing objects, such as lamps so freeing correctly refreshes */ + GPU_materials_free(); +} + +void WM_lib_reload(Library *lib, bContext *C, ReportList *reports) +{ + if (!BLO_has_bfile_extension(lib->filepath)) { + BKE_reportf(reports, RPT_ERROR, "'%s' is not a valid library filepath", lib->filepath); + return; + } + + if (!BLI_exists(lib->filepath)) { + BKE_reportf(reports, RPT_ERROR, + "Trying to reload library '%s' from invalid path '%s'", lib->id.name, lib->filepath); + return; + } + + WMLinkAppendData *lapp_data = wm_link_append_data_new(0); + + wm_link_append_data_library_add(lapp_data, lib->filepath); + + lib_relocate_do(CTX_data_main(C), CTX_data_scene(C), lib, lapp_data, reports, NULL, true); + + wm_link_append_data_free(lapp_data); + + WM_event_add_notifier(C, NC_WINDOW, NULL); } static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload) @@ -855,9 +926,6 @@ static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload) PropertyRNA *prop; WMLinkAppendData *lapp_data; - ListBase *lbarray[MAX_LIBARRAY]; - int lba_idx; - char path[FILE_MAX], root[FILE_MAXDIR], libname[FILE_MAX], relname[FILE_MAX]; short flag = 0; @@ -949,50 +1017,10 @@ static int wm_lib_relocate_exec_do(bContext *C, wmOperator *op, bool do_reload) } } - lba_idx = set_listbasepointers(bmain, lbarray); - while (lba_idx--) { - ID *id = lbarray[lba_idx]->first; - const short idcode = id ? GS(id->name) : 0; - - if (!id || !BKE_idcode_is_linkable(idcode)) { - /* No need to reload non-linkable datatypes, those will get relinked with their 'users ID'. */ - continue; - } - - for (; id; id = id->next) { - if (id->lib == lib) { - WMLinkAppendDataItem *item; - - /* We remove it from current Main, and add it to items to link... */ - /* Note that non-linkable IDs (like e.g. shapekeys) are also explicitely linked here... */ - BLI_remlink(lbarray[lba_idx], id); - item = wm_link_append_data_item_add(lapp_data, id->name + 2, idcode, NULL, id); - BLI_BITMAP_SET_ALL(item->libraries, true, lapp_data->num_libraries); - -#ifdef PRINT_DEBUG - printf("\tdatablock to seek for: %s\n", id->name); -#endif - } - } - } - - lib_relocate_do(bmain, lapp_data, op->reports, NULL, do_reload); + lib_relocate_do(bmain, scene, lib, lapp_data, op->reports, NULL, do_reload); wm_link_append_data_free(lapp_data); - BKE_main_lib_objects_recalc_all(bmain); - IMB_colormanagement_check_file_config(bmain); - - /* important we unset, otherwise these object wont - * link into other scenes from this blend file */ - BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); - - /* recreate dependency graph to include new objects */ - DAG_scene_relations_rebuild(bmain, scene); - - /* free gpu materials, some materials depend on existing objects, such as lamps so freeing correctly refreshes */ - GPU_materials_free(); - /* XXX TODO: align G.lib with other directory storage (like last opened image etc...) */ BLI_strncpy(G.lib, root, FILE_MAX); @@ -1066,9 +1094,10 @@ typedef struct AssetUpdateCheckEngine { AssetEngine *ae; /* Note: We cannot store IDs themselves in non-locking async task... so we'll have to check again for - * UUID/IDs mapping on each update call... Not ideal, but don't think it will be that big of an override + * UUID/IDs mapping on each update call... Not ideal, but don't think it will be that big of a bottleneck * in practice. */ AssetUUIDList uuids; + int allocated_uuids; int ae_job_id; short status; } AssetUpdateCheckEngine; @@ -1170,13 +1199,16 @@ static void asset_update_engines_uuids_fetch( id->uuid->tag = (id->tag & LIB_TAG_MISSING) ? UUID_TAG_ASSET_MISSING : 0; } - /* XXX horrible, need to use some mempool, stack or something :) */ auce->uuids.nbr_uuids++; - if (auce->uuids.uuids) { - auce->uuids.uuids = MEM_reallocN_id(auce->uuids.uuids, sizeof(*auce->uuids.uuids) * (size_t)auce->uuids.nbr_uuids, __func__); - } - else { - auce->uuids.uuids = MEM_mallocN(sizeof(*auce->uuids.uuids) * (size_t)auce->uuids.nbr_uuids, __func__); + BKE_asset_uuid_print(id->uuid); + if (auce->uuids.nbr_uuids > auce->allocated_uuids) { + auce->allocated_uuids += 16; + BLI_assert(auce->uuids.nbr_uuids < auce->allocated_uuids); + + const size_t allocsize = sizeof(*auce->uuids.uuids) * (size_t)auce->allocated_uuids; + auce->uuids.uuids = auce->uuids.uuids ? + MEM_reallocN_id(auce->uuids.uuids, allocsize, __func__) : + MEM_mallocN(allocsize, __func__); } auce->uuids.uuids[auce->uuids.nbr_uuids - 1] = *id->uuid; } @@ -1381,6 +1413,7 @@ static int wm_assets_reload_exec(bContext *C, wmOperator *op) * - cleanup indirect dependencies IDs with zero users. */ Main *bmain = CTX_data_main(C); + Scene *scene = CTX_data_scene(C); ListBase engines = {NULL}; @@ -1461,7 +1494,7 @@ static int wm_assets_reload_exec(bContext *C, wmOperator *op) } } - lib_relocate_do(bmain, lapp_data, op->reports, auce->ae->type, do_reload); + lib_relocate_do(bmain, scene, NULL, lapp_data, op->reports, auce->ae->type, do_reload); wm_link_append_data_free(lapp_data); BLI_ghash_free(libraries, MEM_freeN, NULL); @@ -1476,19 +1509,6 @@ static int wm_assets_reload_exec(bContext *C, wmOperator *op) } BLI_freelistN(&engines); - BKE_main_lib_objects_recalc_all(bmain); - IMB_colormanagement_check_file_config(bmain); - - /* important we unset, otherwise these object wont - * link into other scenes from this blend file */ - BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); - - /* recreate dependency graph to include new objects */ - DAG_scene_relations_rebuild(bmain, CTX_data_scene(C)); - - /* free gpu materials, some materials depend on existing objects, such as lamps so freeing correctly refreshes */ - GPU_materials_free(); - WM_event_add_notifier(C, NC_WINDOW, NULL); G.f &= ~G_ASSETS_NEED_RELOAD; diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 1de92c09af1..c96d0199d24 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -57,7 +57,7 @@ #include "BLO_writefile.h" -#include "BKE_asset.h" +#include "BKE_asset_engine.h" #include "BKE_blender.h" #include "BKE_blender_undo.h" #include "BKE_context.h" |