diff options
Diffstat (limited to 'source/blender/blenkernel')
99 files changed, 4437 insertions, 2409 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 229d2fc17cd..da4fcb4eca4 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -147,6 +147,7 @@ typedef int (*DMSetMaterial)(int mat_nr, void *attribs); typedef int (*DMCompareDrawOptions)(void *userData, int cur_index, int next_index); typedef void (*DMSetDrawInterpOptions)(void *userData, int index, float t); typedef DMDrawOption (*DMSetDrawOptions)(void *userData, int index); +typedef DMDrawOption (*DMSetDrawOptionsMappedTex)(void *userData, int origindex, int mat_nr); typedef DMDrawOption (*DMSetDrawOptionsTex)(struct MTFace *tface, const bool has_vcol, int matnr); typedef enum DMDrawFlag { @@ -423,7 +424,7 @@ struct DerivedMesh { * - Drawing options too complicated to enumerate, look at code. */ void (*drawMappedFacesTex)(DerivedMesh *dm, - DMSetDrawOptions setDrawOptions, + DMSetDrawOptionsMappedTex setDrawOptions, DMCompareDrawOptions compareDrawOptions, void *userData, DMDrawFlag uvflag); diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index e79822daa4d..a5109acfa56 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -106,7 +106,7 @@ void BKE_keyingsets_free(struct ListBase *list); /* ************************************* */ /* Path Fixing API */ -/* Fix all the paths for the the given ID + Action */ +/* Fix all the paths for the given ID + Action */ void BKE_action_fix_paths_rename(struct ID *owner_id, struct bAction *act, const char *prefix, const char *oldName, const char *newName, int oldSubscript, int newSubscript, bool verify_paths); diff --git a/source/blender/blenkernel/BKE_appdir.h b/source/blender/blenkernel/BKE_appdir.h new file mode 100644 index 00000000000..5e42f17be03 --- /dev/null +++ b/source/blender/blenkernel/BKE_appdir.h @@ -0,0 +1,80 @@ +/* + * ***** 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. + * + * ***** END GPL LICENSE BLOCK ***** + */ +#ifndef __BKE_APPDIR_H__ +#define __BKE_APPDIR_H__ + +/** \file BKE_appdir.h + * \ingroup bli + */ + +/* note on naming: typical _get() suffix is omitted here, + * since its the main purpose of the API. */ +const char *BKE_appdir_folder_default(void); +const char *BKE_appdir_folder_id(const int folder_id, const char *subfolder); +const char *BKE_appdir_folder_id_create(const int folder_id, const char *subfolder); +const char *BKE_appdir_folder_id_user_notest(const int folder_id, const char *subfolder); +const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, const bool do_check); + +/* Initialize path to program executable */ +void BKE_appdir_program_path_init(const char *argv0); + +const char *BKE_appdir_program_path(void); +const char *BKE_appdir_program_dir(void); + +/* Initialize path to temporary directory. */ +void BKE_tempdir_init(char *userdir); +void BKE_tempdir_system_init(char *dir); + +const char *BKE_tempdir_base(void); +const char *BKE_tempdir_session(void); +void BKE_tempdir_session_purge(void); + + +/* folder_id */ +enum { + /* general, will find based on user/local/system priority */ + BLENDER_DATAFILES = 2, + + /* user-specific */ + BLENDER_USER_CONFIG = 31, + BLENDER_USER_DATAFILES = 32, + BLENDER_USER_SCRIPTS = 33, + BLENDER_USER_AUTOSAVE = 34, + + /* system */ + BLENDER_SYSTEM_DATAFILES = 52, + BLENDER_SYSTEM_SCRIPTS = 53, + BLENDER_SYSTEM_PYTHON = 54, +}; + +/* for BKE_appdir_folder_id_version only */ +enum { + BLENDER_RESOURCE_PATH_USER = 0, + BLENDER_RESOURCE_PATH_LOCAL = 1, + BLENDER_RESOURCE_PATH_SYSTEM = 2, +}; + +#define BLENDER_STARTUP_FILE "startup.blend" +#define BLENDER_USERPREF_FILE "userpref.blend" +#define BLENDER_QUIT_FILE "quit.blend" +#define BLENDER_BOOKMARK_FILE "bookmarks.txt" +#define BLENDER_HISTORY_FILE "recent-files.txt" + +#endif /* __BKE_APPDIR_H__ */ diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 6c8f90c60ae..8cd4e2584c6 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 272 -#define BLENDER_SUBVERSION 1 +#define BLENDER_SUBVERSION 3 /* 262 was the last editmesh release but it has compatibility code for bmesh data */ #define BLENDER_MINVERSION 270 #define BLENDER_MINSUBVERSION 5 diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index 877e376b343..ae0ef9ce314 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -56,6 +56,9 @@ struct Text; struct ImBuf; struct EditBone; struct bPoseChannel; +struct bGPdata; +struct bGPDlayer; +struct bGPDframe; struct wmWindow; struct wmWindowManager; struct SpaceText; @@ -275,6 +278,14 @@ struct bPoseChannel *CTX_data_active_pose_bone(const bContext *C); int CTX_data_selected_pose_bones(const bContext *C, ListBase *list); int CTX_data_visible_pose_bones(const bContext *C, ListBase *list); +struct bGPdata *CTX_data_gpencil_data(const bContext *C); +struct bGPDlayer *CTX_data_active_gpencil_layer(const bContext *C); +struct bGPDframe *CTX_data_active_gpencil_frame(const bContext *C); +int CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list); +int CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list); +int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list); + + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 5de7d9936e6..13a1468aee8 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -49,6 +49,7 @@ struct rctf; typedef struct CurveCache { ListBase disp; ListBase bev; + ListBase deformed_nurbs; struct Path *path; } CurveCache; @@ -84,8 +85,8 @@ void BKE_curve_texspace_get(struct Curve *cu, float r_loc[3], float r_rot[3], fl bool BKE_curve_minmax(struct Curve *cu, bool use_radius, float min[3], float max[3]); bool BKE_curve_center_median(struct Curve *cu, float cent[3]); bool BKE_curve_center_bounds(struct Curve *cu, float cent[3]); -void BKE_curve_transform_ex(struct Curve *cu, float mat[4][4], bool do_keys, const float unit_scale); -void BKE_curve_transform(struct Curve *cu, float mat[4][4], bool do_keys); +void BKE_curve_transform_ex(struct Curve *cu, float mat[4][4], const bool do_keys, const float unit_scale); +void BKE_curve_transform(struct Curve *cu, float mat[4][4], const bool do_keys); void BKE_curve_translate(struct Curve *cu, float offset[3], const bool do_keys); void BKE_curve_material_index_remove(struct Curve *cu, int index); void BKE_curve_material_index_clear(struct Curve *cu); diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 9a6524cc9ab..30a58891bda 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -173,6 +173,7 @@ int CustomData_number_of_layers_typemask(const struct CustomData *data, CustomDa /* duplicate data of a layer with flag NOFREE, and remove that flag. * returns the layer data */ void *CustomData_duplicate_referenced_layer(struct CustomData *data, const int type, const int totelem); +void *CustomData_duplicate_referenced_layer_n(struct CustomData *data, const int type, const int n, const int totelem); void *CustomData_duplicate_referenced_layer_named(struct CustomData *data, const int type, const char *name, const int totelem); bool CustomData_is_referenced_layer(struct CustomData *data, int type); @@ -327,6 +328,7 @@ int CustomData_sizeof(int type); /* get the name of a layer type */ const char *CustomData_layertype_name(int type); bool CustomData_layertype_is_singleton(int type); +int CustomData_layertype_layers_max(const int type); /* make sure the name of layer at index is unique */ void CustomData_set_layer_unique_name(struct CustomData *data, int index); diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h index c377769b271..83783946d4f 100644 --- a/source/blender/blenkernel/BKE_fcurve.h +++ b/source/blender/blenkernel/BKE_fcurve.h @@ -44,6 +44,7 @@ struct DriverTarget; struct FCM_EnvelopeData; struct bContext; +struct AnimData; struct bAction; struct BezTriple; struct StructRNA; @@ -224,10 +225,10 @@ int list_find_data_fcurves(ListBase *dst, ListBase *src, const char *dataPrefix, /* find an f-curve based on an rna property. */ struct FCurve *rna_get_fcurve(struct PointerRNA *ptr, struct PropertyRNA *prop, int rnaindex, - struct bAction **action, bool *r_driven); + struct AnimData **adt, struct bAction **action, bool *r_driven); /* Same as above, but takes a context data, temp hack needed for complex paths like texture ones. */ struct FCurve *rna_get_fcurve_context_ui(struct bContext *C, struct PointerRNA *ptr, struct PropertyRNA *prop, - int rnaindex, struct bAction **action, bool *r_driven); + int rnaindex, struct AnimData **adt, struct bAction **action, bool *r_driven); /* Binary search algorithm for finding where to 'insert' BezTriple with given frame number. * Returns the index to insert at (data already at that index will be offset if replace is 0) diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h index 86c111653d1..084c5527f21 100644 --- a/source/blender/blenkernel/BKE_gpencil.h +++ b/source/blender/blenkernel/BKE_gpencil.h @@ -35,6 +35,7 @@ struct ListBase; struct bGPdata; struct bGPDlayer; struct bGPDframe; +struct bGPDstroke; /* ------------ Grease-Pencil API ------------------ */ @@ -43,17 +44,15 @@ void free_gpencil_frames(struct bGPDlayer *gpl); void free_gpencil_layers(struct ListBase *list); void BKE_gpencil_free(struct bGPdata *gpd); +void gpencil_stroke_sync_selection(struct bGPDstroke *gps); + struct bGPDframe *gpencil_frame_addnew(struct bGPDlayer *gpl, int cframe); struct bGPDlayer *gpencil_layer_addnew(struct bGPdata *gpd, const char *name, int setactive); struct bGPdata *gpencil_data_addnew(const char name[]); struct bGPDframe *gpencil_frame_duplicate(struct bGPDframe *src); struct bGPDlayer *gpencil_layer_duplicate(struct bGPDlayer *src); -struct bGPdata *gpencil_data_duplicate(struct bGPdata *gpd); - -//struct bGPdata *gpencil_data_getactive(struct ScrArea *sa); -//short gpencil_data_setactive(struct ScrArea *sa, struct bGPdata *gpd); -//struct ScrArea *gpencil_data_findowner(struct bGPdata *gpd); +struct bGPdata *gpencil_data_duplicate(struct bGPdata *gpd, bool internal_copy); void gpencil_frame_delete_laststroke(struct bGPDlayer *gpl, struct bGPDframe *gpf); diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h index 2ab3d84dea5..f33f3eba590 100644 --- a/source/blender/blenkernel/BKE_idprop.h +++ b/source/blender/blenkernel/BKE_idprop.h @@ -41,13 +41,13 @@ typedef union IDPropertyTemplate { double d; struct { char *str; - short len; + int len; char subtype; } string; struct ID *id; struct { - short type; - short len; + int len; + char type; } array; struct { int matvec_size; @@ -91,6 +91,7 @@ void IDP_SyncGroupValues(struct IDProperty *dest, const struct IDProperty *src) void IDP_SyncGroupTypes(struct IDProperty *dest, const struct IDProperty *src, const bool do_arraylen) ATTR_NONNULL(); void IDP_ReplaceGroupInGroup(struct IDProperty *dest, const struct IDProperty *src) ATTR_NONNULL(); void IDP_ReplaceInGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL(); +void IDP_ReplaceInGroup_ex(struct IDProperty *group, struct IDProperty *prop, struct IDProperty *prop_exist); void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, const bool do_overwrite) ATTR_NONNULL(); bool IDP_AddToGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL(); bool IDP_InsertToGroup(struct IDProperty *group, struct IDProperty *previous, @@ -100,9 +101,6 @@ void IDP_FreeFromGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_N IDProperty *IDP_GetPropertyFromGroup(struct IDProperty *prop, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); IDProperty *IDP_GetPropertyTypeFromGroup(struct IDProperty *prop, const char *name, const char type) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -void *IDP_GetGroupIterator(struct IDProperty *prop) ATTR_WARN_UNUSED_RESULT; -IDProperty *IDP_GroupIterNext(void *vself) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); -void IDP_FreeIterBeforeEnd(void *vself) ATTR_NONNULL(); /*-------- Main Functions --------*/ struct IDProperty *IDP_GetProperties(struct ID *id, const bool create_if_needed) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); @@ -112,7 +110,7 @@ bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is bool IDP_EqualsProperties(struct IDProperty *prop1, struct IDProperty *prop2) ATTR_WARN_UNUSED_RESULT; -struct IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +struct IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); void IDP_FreeProperty(struct IDProperty *prop); diff --git a/source/blender/blenkernel/BKE_image.h b/source/blender/blenkernel/BKE_image.h index dc3d9f38b21..a225a27a00b 100644 --- a/source/blender/blenkernel/BKE_image.h +++ b/source/blender/blenkernel/BKE_image.h @@ -162,6 +162,7 @@ void BKE_image_alpha_mode_from_extension(struct Image *image); /* returns a new image or NULL if it can't load */ struct Image *BKE_image_load(struct Main *bmain, const char *filepath); /* returns existing Image when filename/type is same (frame optional) */ +struct Image *BKE_image_load_exists_ex(const char *filepath, bool *r_exists); struct Image *BKE_image_load_exists(const char *filepath); /* adds image, adds ibuf, generates color or pattern */ diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index 6183df8666d..31b2c7dc2b9 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -87,15 +87,29 @@ void BKE_key_evaluate_relative(const int start, int end, const int tot, char *ba float **per_keyblock_weights, const int mode); /* conversion functions */ -void BKE_key_convert_to_mesh(struct KeyBlock *kb, struct Mesh *me); -void BKE_key_convert_from_mesh(struct Mesh *me, struct KeyBlock *kb); -void BKE_key_convert_to_lattice(struct KeyBlock *kb, struct Lattice *lt); -void BKE_key_convert_from_lattice(struct Lattice *lt, struct KeyBlock *kb); -void BKE_key_convert_to_curve(struct KeyBlock *kb, struct Curve *cu, struct ListBase *nurb); -void BKE_key_convert_from_curve(struct Curve *cu, struct KeyBlock *kb, struct ListBase *nurb); -float (*BKE_key_convert_to_vertcos(struct Object *ob, struct KeyBlock *kb))[3]; -void BKE_key_convert_from_vertcos(struct Object *ob, struct KeyBlock *kb, float (*vertCos)[3]); -void BKE_key_convert_from_offset(struct Object *ob, struct KeyBlock *kb, float (*ofs)[3]); +/* Note: 'update_from' versions do not (re)allocate mem in kb, while 'convert_from' do. */ +void BKE_keyblock_update_from_lattice(struct Lattice *lt, struct KeyBlock *kb); +void BKE_keyblock_convert_from_lattice(struct Lattice *lt, struct KeyBlock *kb); +void BKE_keyblock_convert_to_lattice(struct KeyBlock *kb, struct Lattice *lt); + +void BKE_keyblock_update_from_curve(struct Curve *cu, struct KeyBlock *kb, struct ListBase *nurb); +void BKE_keyblock_convert_from_curve(struct Curve *cu, struct KeyBlock *kb, struct ListBase *nurb); +void BKE_keyblock_convert_to_curve(struct KeyBlock *kb, struct Curve *cu, struct ListBase *nurb); + +void BKE_keyblock_update_from_mesh(struct Mesh *me, struct KeyBlock *kb); +void BKE_keyblock_convert_from_mesh(struct Mesh *me, struct KeyBlock *kb); +void BKE_keyblock_convert_to_mesh(struct KeyBlock *kb, struct Mesh *me); + +void BKE_keyblock_update_from_vertcos(struct Object *ob, struct KeyBlock *kb, float (*vertCos)[3]); +void BKE_keyblock_convert_from_vertcos(struct Object *ob, struct KeyBlock *kb, float (*vertCos)[3]); +float (*BKE_keyblock_convert_to_vertcos(struct Object *ob, struct KeyBlock *kb))[3]; + +void BKE_keyblock_update_from_offset(struct Object *ob, struct KeyBlock *kb, float (*ofs)[3]); + +/* other management */ +bool BKE_keyblock_move(struct Object *ob, int org_index, int new_index); + +bool BKE_keyblock_is_basis(struct Key *key, const int index); /* key.c */ extern int slurph_opt; diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h index 341105cfdf7..a4aa58e22f1 100644 --- a/source/blender/blenkernel/BKE_movieclip.h +++ b/source/blender/blenkernel/BKE_movieclip.h @@ -46,6 +46,7 @@ void BKE_movieclip_unlink(struct Main *bmain, struct MovieClip *clip); struct MovieClip *BKE_movieclip_file_add(struct Main *bmain, const char *name); void BKE_movieclip_reload(struct MovieClip *clip); void BKE_movieclip_clear_cache(struct MovieClip *clip); +void BKE_movieclip_clear_proxy_cache(struct MovieClip *clip); struct ImBuf *BKE_movieclip_get_ibuf(struct MovieClip *clip, struct MovieClipUser *user); struct ImBuf *BKE_movieclip_get_postprocessed_ibuf(struct MovieClip *clip, struct MovieClipUser *user, int postprocess_flag); diff --git a/source/blender/blenkernel/BKE_object_deform.h b/source/blender/blenkernel/BKE_object_deform.h index 6de7ff9bc1c..0e5ad2d51c8 100644 --- a/source/blender/blenkernel/BKE_object_deform.h +++ b/source/blender/blenkernel/BKE_object_deform.h @@ -29,10 +29,47 @@ * used by painting and tools. */ +#ifdef __cplusplus +extern "C" { +#endif + struct Object; +struct ID; +struct MDeformVert; +struct bDeformGroup; + +/* General vgroup operations */ +void BKE_object_defgroup_remap_update_users(struct Object *ob, int *map); + +bool BKE_object_defgroup_array_get(struct ID *id, struct MDeformVert **dvert_arr, int *dvert_tot); + +struct bDeformGroup *BKE_object_defgroup_add(struct Object *ob); +struct bDeformGroup *BKE_object_defgroup_add_name(struct Object *ob, const char *name); +struct MDeformVert *BKE_object_defgroup_data_create(struct ID *id); + +bool BKE_object_defgroup_clear(struct Object *ob, struct bDeformGroup *dg, const bool use_selection); +bool BKE_object_defgroup_clear_all(struct Object *ob, const bool use_selection); + +void BKE_object_defgroup_remove(struct Object *ob, struct bDeformGroup *defgroup); +void BKE_object_defgroup_remove_all(struct Object *ob); + + +/* Select helpers */ +enum eVGroupSelect; +bool *BKE_object_defgroup_subset_from_select_type( + struct Object *ob, enum eVGroupSelect subset_type, int *r_defgroup_tot, int *r_subset_count); +void BKE_object_defgroup_subset_to_index_array( + const bool *defgroup_validmap, const int defgroup_tot, int *r_defgroup_subset_map); + + +/* ********** */ + +bool *BKE_object_defgroup_lock_flags_get(struct Object *ob, const int defbase_tot); +bool *BKE_object_defgroup_validmap_get(struct Object *ob, const int defbase_tot); +bool *BKE_object_defgroup_selected_get(struct Object *ob, int defbase_tot, int *r_dg_flags_sel_tot); -bool *BKE_objdef_lock_flags_get(struct Object *ob, const int defbase_tot); -bool *BKE_objdef_validmap_get(struct Object *ob, const int defbase_tot); -bool *BKE_objdef_selected_get(struct Object *ob, int defbase_tot, int *r_dg_flags_sel_tot); +#ifdef __cplusplus +} +#endif #endif /* __BKE_OBJECT_DEFORM_H__ */ diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index f84a6378fb3..204fbbf5bfc 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -378,7 +378,7 @@ void free_keyed_keys(struct ParticleSystem *psys); void psys_free_particles(struct ParticleSystem *psys); void psys_free_children(struct ParticleSystem *psys); -void psys_interpolate_particle(short type, struct ParticleKey keys[4], float dt, struct ParticleKey *result, int velocity); +void psys_interpolate_particle(short type, struct ParticleKey keys[4], float dt, struct ParticleKey *result, bool velocity); void psys_vec_rot_to_face(struct DerivedMesh *dm, struct ParticleData *pa, float vec[3]); void psys_mat_hair_to_object(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[4][4]); void psys_mat_hair_to_global(struct Object *ob, struct DerivedMesh *dm, short from, struct ParticleData *pa, float hairmat[4][4]); diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 1bfe0eeea0b..eac4f6a56a5 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -110,7 +110,7 @@ char *BKE_scene_find_marker_name(struct Scene *scene, int frame); char *BKE_scene_find_last_marker_name(struct Scene *scene, int frame); /* checks for cycle, returns 1 if it's all OK */ -int BKE_scene_validate_setscene(struct Main *bmain, struct Scene *sce); +bool BKE_scene_validate_setscene(struct Main *bmain, struct Scene *sce); float BKE_scene_frame_get(struct Scene *scene); float BKE_scene_frame_get_from_ctime(struct Scene *scene, const float frame); @@ -131,7 +131,9 @@ int get_render_shadow_samples(struct RenderData *r, int samples); float get_render_aosss_error(struct RenderData *r, float error); bool BKE_scene_use_new_shading_nodes(struct Scene *scene); + bool BKE_scene_uses_blender_internal(struct Scene *scene); +bool BKE_scene_uses_blender_game(struct Scene *scene); void BKE_scene_disable_color_management(struct Scene *scene); bool BKE_scene_check_color_management_enabled(const struct Scene *scene); diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 13cc5d2e84f..5a0c7ac1ce1 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -217,6 +217,10 @@ void BKE_sequence_clipboard_pointers_free(struct Sequence *seq); void BKE_sequence_clipboard_pointers_store(struct Sequence *seq); void BKE_sequence_clipboard_pointers_restore(struct Sequence *seq, struct Main *bmain); +void BKE_sequencer_base_clipboard_pointers_free(struct ListBase *seqbase); +void BKE_sequencer_base_clipboard_pointers_store(struct ListBase *seqbase); +void BKE_sequencer_base_clipboard_pointers_restore(struct ListBase *seqbase, struct Main *bmain); + void BKE_sequence_free(struct Scene *scene, struct Sequence *seq); const char *BKE_sequence_give_name(struct Sequence *seq); void BKE_sequence_calc(struct Scene *scene, struct Sequence *seq); @@ -308,7 +312,7 @@ void BKE_sequencer_offset_animdata(struct Scene *scene, struct Sequence *seq, in void BKE_sequencer_dupe_animdata(struct Scene *scene, const char *name_src, const char *name_dst); bool BKE_sequence_base_shuffle(struct ListBase *seqbasep, struct Sequence *test, struct Scene *evil_scene); bool BKE_sequence_base_shuffle_time(ListBase *seqbasep, struct Scene *evil_scene); -bool BKE_sequence_base_isolated_sel_check(struct ListBase *seqbase, bool one_only); +bool BKE_sequence_base_isolated_sel_check(struct ListBase *seqbase); void BKE_sequencer_free_imbuf(struct Scene *scene, struct ListBase *seqbasep, bool for_render); struct Sequence *BKE_sequence_dupli_recursive(struct Scene *scene, struct Scene *scene_to, struct Sequence *seq, int dupe_flag); int BKE_sequence_swap(struct Sequence *seq_a, struct Sequence *seq_b, const char **error_str); @@ -326,7 +330,9 @@ void BKE_sequencer_update_sound(struct Scene *scene, struct bSound *sound); void BKE_sequencer_refresh_sound_length(struct Scene *scene); void BKE_sequence_base_unique_name_recursive(ListBase *seqbasep, struct Sequence *seq); -void BKE_sequence_base_dupli_recursive(struct Scene *scene, struct Scene *scene_to, ListBase *nseqbase, ListBase *seqbase, int dupe_flag); +void BKE_sequence_base_dupli_recursive( + struct Scene *scene, struct Scene *scene_to, ListBase *nseqbase, ListBase *seqbase, + int dupe_flag); bool BKE_sequence_is_valid_check(struct Sequence *seq); void BKE_sequencer_clear_scene_in_allseqs(struct Main *bmain, struct Scene *sce); @@ -371,12 +377,23 @@ struct Sequence *BKE_sequence_alloc(ListBase *lb, int cfra, int machine); void BKE_sequence_alpha_mode_from_extension(struct Sequence *seq); void BKE_sequence_init_colorspace(struct Sequence *seq); +/* RNA enums, just to be more readable */ +enum { + SEQ_SIDE_NONE = 0, + SEQ_SIDE_LEFT, + SEQ_SIDE_RIGHT, + SEQ_SIDE_BOTH +}; +int BKE_sequencer_find_next_prev_edit( + struct Scene *scene, int cfra, const short side, + const bool do_skip_mute, const bool do_center, const bool do_unselected); + struct Sequence *BKE_sequencer_add_image_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load); struct Sequence *BKE_sequencer_add_sound_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load); struct Sequence *BKE_sequencer_add_movie_strip(struct bContext *C, ListBase *seqbasep, struct SeqLoadInfo *seq_load); /* view3d draw callback, run when not in background view */ -typedef struct ImBuf *(*SequencerDrawView)(struct Scene *, struct Object *, int, int, unsigned int, int, bool, bool, int, char[256]); +typedef struct ImBuf *(*SequencerDrawView)(struct Scene *, struct Object *, int, int, unsigned int, int, bool, bool, bool, int, char[256]); extern SequencerDrawView sequencer_view3d_cb; /* copy/paste */ diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index 50ca5fcdf7b..f318c74258b 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -71,8 +71,6 @@ void sound_delete(struct Main *bmain, struct bSound *sound); void sound_cache(struct bSound *sound); -void sound_cache_notifying(struct Main *main, struct bSound *sound); - void sound_delete_cache(struct bSound *sound); void sound_load(struct Main *main, struct bSound *sound); @@ -132,7 +130,7 @@ int sound_scene_playing(struct Scene *scene); void sound_free_waveform(struct bSound *sound); -void sound_read_waveform(struct bSound *sound); +void sound_read_waveform(struct bSound *sound, bool locked, short *stop); void sound_update_scene(struct Main *bmain, struct Scene *scene); diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 8bc619c1b27..e5fb60cf1b5 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -145,6 +145,9 @@ void BKE_tracking_plane_marker_delete(struct MovieTrackingPlaneTrack *plane_trac struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get(struct MovieTrackingPlaneTrack *plane_track, int framenr); struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_get_exact(struct MovieTrackingPlaneTrack *plane_track, int framenr); struct MovieTrackingPlaneMarker *BKE_tracking_plane_marker_ensure(struct MovieTrackingPlaneTrack *plane_track, int framenr); +void BKE_tracking_plane_marker_get_subframe_corners(struct MovieTrackingPlaneTrack *plane_track, + float framenr, + float corners[4][2]); /* **** Object **** */ struct MovieTrackingObject *BKE_tracking_object_add(struct MovieTracking *tracking, const char *name); @@ -210,16 +213,18 @@ void BKE_tracking_disable_channels(struct ImBuf *ibuf, bool disable_red, bool di bool disable_blue, bool grayscale); /* **** 2D tracking **** */ -struct MovieTrackingContext *BKE_tracking_context_new(struct MovieClip *clip, struct MovieClipUser *user, - const bool backwards, const bool sequence); -void BKE_tracking_context_free(struct MovieTrackingContext *context); -void BKE_tracking_context_sync(struct MovieTrackingContext *context); -void BKE_tracking_context_sync_user(const struct MovieTrackingContext *context, struct MovieClipUser *user); -bool BKE_tracking_context_step(struct MovieTrackingContext *context); -void BKE_tracking_context_finish(struct MovieTrackingContext *context); - void BKE_tracking_refine_marker(struct MovieClip *clip, struct MovieTrackingTrack *track, struct MovieTrackingMarker *marker, bool backwards); +/* *** 2D auto track *** */ + +struct AutoTrackContext *BKE_autotrack_context_new(struct MovieClip *clip, struct MovieClipUser *user, + const bool backwards, const bool sequence); +bool BKE_autotrack_context_step(struct AutoTrackContext *context); +void BKE_autotrack_context_sync(struct AutoTrackContext *context); +void BKE_autotrack_context_sync_user(struct AutoTrackContext *context, struct MovieClipUser *user); +void BKE_autotrack_context_finish(struct AutoTrackContext *context); +void BKE_autotrack_context_free(struct AutoTrackContext *context); + /* **** Plane tracking **** */ void BKE_tracking_track_plane_from_existing_motion(struct MovieTrackingPlaneTrack *plane_track, int start_frame); diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index f4a3a0c10dd..5850b1614e7 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -37,6 +37,7 @@ set(INC ../modifiers ../nodes ../render/extern/include + ../../../intern/ghost ../../../intern/guardedalloc ../../../intern/glew-mx ../../../intern/iksolver/extern @@ -63,6 +64,7 @@ set(SRC intern/addon.c intern/anim.c intern/anim_sys.c + intern/appdir.c intern/armature.c intern/autoexec.c intern/blender.c @@ -158,6 +160,7 @@ set(SRC intern/text.c intern/texture.c intern/tracking.c + intern/tracking_auto.c intern/tracking_detect.c intern/tracking_plane_tracker.c intern/tracking_region_tracker.c @@ -175,6 +178,7 @@ set(SRC BKE_addon.h BKE_anim.h BKE_animsys.h + BKE_appdir.h BKE_armature.h BKE_autoexec.h BKE_blender.h @@ -273,8 +277,21 @@ set(SRC intern/pbvh_intern.h ) +if(WITH_BINRELOC) + list(APPEND INC_SYS + ${BINRELOC_INCLUDE_DIRS} + ) + add_definitions(-DWITH_BINRELOC) +endif() + add_definitions(${GL_DEFINITIONS}) +if(WIN32) + list(APPEND INC + ../../../intern/utfconv + ) +endif() + if(WITH_AUDASPACE) list(APPEND INC ../../../intern/audaspace/intern diff --git a/source/blender/blenkernel/SConscript b/source/blender/blenkernel/SConscript index 9243c85167b..3da3d647275 100644 --- a/source/blender/blenkernel/SConscript +++ b/source/blender/blenkernel/SConscript @@ -46,6 +46,7 @@ incs = [ '#/intern/rigidbody', '#/extern/bullet2/src', env['BF_GLEW_INC'], + '#/intern/ghost', '#/intern/glew-mx', '#/intern/audaspace/intern', '#/intern/elbeem/extern', @@ -167,7 +168,11 @@ if env['WITH_BF_FREESTYLE']: if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc', 'win64-mingw'): incs += ' ' + env['BF_PTHREADS_INC'] + incs += ' ../../../intern/utfconv' +if env['WITH_BF_BINRELOC']: + incs += ' #extern/binreloc/include' + defs.append('WITH_BINRELOC') if env['OURPLATFORM'] in ('win32-vc', 'win64-vc'): env.BlenderLib ( libname = 'bf_blenkernel', sources = sources, includes = Split(incs), defines = defs, libtype=['core','player'], priority = [166,25]) #, cc_compileflags = env['CCFLAGS'].append('/WX') ) diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c index 623fb50b62c..9e5d4afffe2 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -172,29 +172,19 @@ static void *_ehash_lookup(EHash *eh, void *key) /**/ -typedef struct _EHashIterator { - EHash *eh; - int curBucket; - EHEntry *curEntry; -} EHashIterator; - -static EHashIterator *_ehashIterator_new(EHash *eh) +static void _ehashIterator_init(EHash *eh, EHashIterator *ehi) { - EHashIterator *ehi = EHASH_alloc(eh, sizeof(*ehi)); + /* fill all members */ ehi->eh = eh; - ehi->curEntry = NULL; ehi->curBucket = -1; + ehi->curEntry = NULL; + while (!ehi->curEntry) { ehi->curBucket++; if (ehi->curBucket == ehi->eh->curSize) break; ehi->curEntry = ehi->eh->buckets[ehi->curBucket]; } - return ehi; -} -static void _ehashIterator_free(EHashIterator *ehi) -{ - EHASH_free(ehi->eh, ehi); } static void *_ehashIterator_getCurrent(EHashIterator *ehi) @@ -3051,17 +3041,17 @@ void *ccgSubSurf_getFaceGridData(CCGSubSurf *ss, CCGFace *f, int gridIndex, int /*** External API iterator functions ***/ -CCGVertIterator *ccgSubSurf_getVertIterator(CCGSubSurf *ss) +void ccgSubSurf_initVertIterator(CCGSubSurf *ss, CCGVertIterator *viter) { - return (CCGVertIterator *) _ehashIterator_new(ss->vMap); + _ehashIterator_init(ss->vMap, viter); } -CCGEdgeIterator *ccgSubSurf_getEdgeIterator(CCGSubSurf *ss) +void ccgSubSurf_initEdgeIterator(CCGSubSurf *ss, CCGEdgeIterator *eiter) { - return (CCGEdgeIterator *) _ehashIterator_new(ss->eMap); + _ehashIterator_init(ss->eMap, eiter); } -CCGFaceIterator *ccgSubSurf_getFaceIterator(CCGSubSurf *ss) +void ccgSubSurf_initFaceIterator(CCGSubSurf *ss, CCGFaceIterator *fiter) { - return (CCGFaceIterator *) _ehashIterator_new(ss->fMap); + _ehashIterator_init(ss->fMap, fiter); } CCGVert *ccgVertIterator_getCurrent(CCGVertIterator *vi) @@ -3076,10 +3066,6 @@ void ccgVertIterator_next(CCGVertIterator *vi) { _ehashIterator_next((EHashIterator *) vi); } -void ccgVertIterator_free(CCGVertIterator *vi) -{ - _ehashIterator_free((EHashIterator *) vi); -} CCGEdge *ccgEdgeIterator_getCurrent(CCGEdgeIterator *vi) { @@ -3093,10 +3079,6 @@ void ccgEdgeIterator_next(CCGEdgeIterator *vi) { _ehashIterator_next((EHashIterator *) vi); } -void ccgEdgeIterator_free(CCGEdgeIterator *vi) -{ - _ehashIterator_free((EHashIterator *) vi); -} CCGFace *ccgFaceIterator_getCurrent(CCGFaceIterator *vi) { @@ -3110,10 +3092,6 @@ void ccgFaceIterator_next(CCGFaceIterator *vi) { _ehashIterator_next((EHashIterator *) vi); } -void ccgFaceIterator_free(CCGFaceIterator *vi) -{ - _ehashIterator_free((EHashIterator *) vi); -} /*** Extern API final vert/edge/face interface ***/ diff --git a/source/blender/blenkernel/intern/CCGSubSurf.h b/source/blender/blenkernel/intern/CCGSubSurf.h index fdf6d2df99f..2b86a2a66b2 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.h +++ b/source/blender/blenkernel/intern/CCGSubSurf.h @@ -53,6 +53,13 @@ typedef struct CCGAllocatorIFC { void (*release) (CCGAllocatorHDL a); } CCGAllocatorIFC; +/* private, so we can allocate on the stack */ +typedef struct _EHashIterator { + struct _EHash *eh; + int curBucket; + struct _EHEntry *curEntry; +} EHashIterator; + /***/ typedef enum { @@ -163,27 +170,24 @@ int ccgSubSurf_getNumFinalFaces (const CCGSubSurf *ss); /***/ -typedef struct CCGVertIterator CCGVertIterator; -typedef struct CCGEdgeIterator CCGEdgeIterator; -typedef struct CCGFaceIterator CCGFaceIterator; +typedef struct _EHashIterator CCGVertIterator; +typedef struct _EHashIterator CCGEdgeIterator; +typedef struct _EHashIterator CCGFaceIterator; -CCGVertIterator* ccgSubSurf_getVertIterator (CCGSubSurf *ss); -CCGEdgeIterator* ccgSubSurf_getEdgeIterator (CCGSubSurf *ss); -CCGFaceIterator* ccgSubSurf_getFaceIterator (CCGSubSurf *ss); +void ccgSubSurf_initVertIterator(CCGSubSurf *ss, CCGVertIterator *viter); +void ccgSubSurf_initEdgeIterator(CCGSubSurf *ss, CCGEdgeIterator *eiter); +void ccgSubSurf_initFaceIterator(CCGSubSurf *ss, CCGFaceIterator *fiter); CCGVert* ccgVertIterator_getCurrent (CCGVertIterator *vi); int ccgVertIterator_isStopped (CCGVertIterator *vi); void ccgVertIterator_next (CCGVertIterator *vi); -void ccgVertIterator_free (CCGVertIterator *vi); CCGEdge* ccgEdgeIterator_getCurrent (CCGEdgeIterator *ei); int ccgEdgeIterator_isStopped (CCGEdgeIterator *ei); void ccgEdgeIterator_next (CCGEdgeIterator *ei); -void ccgEdgeIterator_free (CCGEdgeIterator *ei); CCGFace* ccgFaceIterator_getCurrent (CCGFaceIterator *fi); int ccgFaceIterator_isStopped (CCGFaceIterator *fi); void ccgFaceIterator_next (CCGFaceIterator *fi); -void ccgFaceIterator_free (CCGFaceIterator *fi); #endif /* __CCGSUBSURF_H__ */ diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 81c03d8081b..e8000a09d82 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -73,13 +73,11 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm); #include "BLI_sys_types.h" /* for intptr_t support */ #include "GPU_buffers.h" -#include "GPU_draw.h" #include "GPU_extensions.h" #include "GPU_glew.h" -#include "GPU_material.h" /* very slow! enable for testing only! */ -// #define USE_MODIFIER_VALIDATE +//#define USE_MODIFIER_VALIDATE #ifdef USE_MODIFIER_VALIDATE # define ASSERT_IS_VALID_DM(dm) (BLI_assert((dm == NULL) || (DM_is_valid(dm) == true))) @@ -914,7 +912,7 @@ DerivedMesh *mesh_create_derived_for_modifier(Scene *scene, Object *ob, if (mti->isDisabled && mti->isDisabled(md, 0)) return NULL; if (build_shapekey_layers && me->key && (kb = BLI_findlink(&me->key->block, ob->shapenr - 1))) { - BKE_key_convert_to_mesh(kb, me); + BKE_keyblock_convert_to_mesh(kb, me); } if (mti->type == eModifierTypeType_OnlyDeform) { @@ -1221,14 +1219,14 @@ static void calc_weightpaint_vert_array(Object *ob, DerivedMesh *dm, int const d unsigned int i; /* variables for multipaint */ - const int defbase_tot = BLI_countlist(&ob->defbase); + const int defbase_tot = BLI_listbase_count(&ob->defbase); const int defbase_act = ob->actdef - 1; int defbase_sel_tot = 0; bool *defbase_sel = NULL; if (draw_flag & CALC_WP_MULTIPAINT) { - defbase_sel = BKE_objdef_selected_get(ob, defbase_tot, &defbase_sel_tot); + defbase_sel = BKE_object_defgroup_selected_get(ob, defbase_tot, &defbase_sel_tot); } for (i = numVerts; i != 0; i--, wc++, dv++) { @@ -1486,8 +1484,8 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0); const bool has_multires = (mmd && mmd->sculptlvl != 0); bool multires_applied = false; - const bool sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt; - const bool sculpt_dyntopo = (sculpt_mode && ob->sculpt->bm); + const bool sculpt_mode = ob->mode & OB_MODE_SCULPT && ob->sculpt && !useRenderParams; + const bool sculpt_dyntopo = (sculpt_mode && ob->sculpt->bm) && !useRenderParams; const int draw_flag = dm_drawflag_calc(scene->toolsettings); /* Generic preview only in object mode! */ @@ -1977,10 +1975,10 @@ bool editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh * if (!modifier_isEnabled(scene, md, required_mode)) return 0; if ((mti->flags & eModifierTypeFlag_RequiresOriginalData) && dm) { modifier_setError(md, "Modifier requires original data, bad stack position"); - return 0; + return false; } - return 1; + return true; } static void editbmesh_calc_modifiers(Scene *scene, Object *ob, BMEditMesh *em, DerivedMesh **cage_r, @@ -2960,7 +2958,7 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, a = attribs->tottface++; if (layer != -1) { - attribs->tface[a].array = tfdata->layers[layer].data; + attribs->tface[a].array = NULL; attribs->tface[a].em_offset = ldata->layers[layer].offset; } else { @@ -3007,7 +3005,7 @@ void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, a = attribs->totmcol++; if (layer != -1) { - attribs->mcol[a].array = tfdata->layers[layer].data; + attribs->mcol[a].array = NULL; /* odd, store the offset for a different layer type here, but editmode draw code expects it */ attribs->mcol[a].em_offset = ldata->layers[layer].offset; } diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index c6dcca576fb..c1173cb2391 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -966,7 +966,7 @@ bActionGroup *BKE_pose_add_group(bPose *pose, const char *name) BLI_addtail(&pose->agroups, grp); BLI_uniquename(&pose->agroups, grp, name, '.', offsetof(bActionGroup, name), sizeof(grp->name)); - pose->active_group = BLI_countlist(&pose->agroups); + pose->active_group = BLI_listbase_count(&pose->agroups); return grp; } @@ -1028,12 +1028,12 @@ bool action_has_motion(const bAction *act) if (act) { for (fcu = act->curves.first; fcu; fcu = fcu->next) { if (fcu->totvert) - return 1; + return true; } } /* nothing found */ - return 0; + return false; } /* Calculate the extents of given action */ diff --git a/source/blender/blenkernel/intern/addon.c b/source/blender/blenkernel/intern/addon.c index 119fa266908..28667d458b8 100644 --- a/source/blender/blenkernel/intern/addon.c +++ b/source/blender/blenkernel/intern/addon.c @@ -29,15 +29,9 @@ #include "BLI_utildefines.h" #include "BLI_ghash.h" -#include "BLI_string.h" #include "BKE_addon.h" /* own include */ -#include "RNA_access.h" -#include "RNA_define.h" - -#include "BLF_translation.h" - #include "MEM_guardedalloc.h" static GHash *global_addonpreftype_hash = NULL; diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index aff99d3e1bf..b878dbe1f39 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -627,6 +627,9 @@ int where_on_path(Object *ob, float ctime, float vec[4], float dir[3], float qua if (!bl->nr) return 0; if (bl->poly > -1) cycl = 1; + /* values below zero for non-cyclic curves give strange results */ + BLI_assert(cycl || ctime >= 0.0f); + ctime *= (path->len - 1); s1 = (int)floor(ctime); diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 2fb832dc72d..8e36449f214 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -83,7 +83,7 @@ bool id_type_can_have_animdata(ID *id) { /* sanity check */ if (id == NULL) - return 0; + return false; /* Only some ID-blocks have this info for now */ /* TODO: finish adding this for the other blocktypes */ @@ -100,13 +100,14 @@ bool id_type_can_have_animdata(ID *id) case ID_SCE: case ID_MC: case ID_MSK: + case ID_GD: { - return 1; + return true; } /* no AnimData */ default: - return 0; + return false; } } @@ -193,20 +194,20 @@ bool BKE_animdata_set_action(ReportList *reports, ID *id, bAction *act) /* can set */ adt->action = act; id_us_plus((ID *)adt->action); - ok = 1; + ok = true; } else { /* cannot set */ BKE_reportf(reports, RPT_ERROR, "Could not set action '%s' onto ID '%s', as it does not have suitably rooted paths " "for this purpose", act->id.name + 2, id->name); - /* ok = 0; */ + /* ok = false; */ } } else { /* just clearing the action... */ adt->action = NULL; - ok = 1; + ok = true; } return ok; @@ -289,7 +290,7 @@ bool BKE_copy_animdata_id(ID *id_to, ID *id_from, const bool do_action) AnimData *adt; if ((id_to && id_from) && (GS(id_to->name) != GS(id_from->name))) - return 0; + return false; BKE_free_animdata(id_to); @@ -299,7 +300,7 @@ bool BKE_copy_animdata_id(ID *id_to, ID *id_from, const bool do_action) iat->adt = BKE_copy_animdata(adt, do_action); } - return 1; + return true; } void BKE_copy_animdata_id_action(ID *id) @@ -1031,6 +1032,9 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u /* line styles */ ANIMDATA_IDS_CB(mainptr->linestyle.first); + + /* grease pencil */ + ANIMDATA_IDS_CB(mainptr->gpencil.first); } /* Fix all RNA-Paths throughout the database (directly access the Global.main version) @@ -1119,6 +1123,9 @@ void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const cha /* linestyles */ RENAMEFIX_ANIM_IDS(mainptr->linestyle.first); + /* grease pencil */ + RENAMEFIX_ANIM_IDS(mainptr->gpencil.first); + /* scenes */ RENAMEFIX_ANIM_NODETREE_IDS(mainptr->scene.first, Scene); } @@ -1346,11 +1353,11 @@ static bool animsys_remap_path(AnimMapper *UNUSED(remap), char *path, char **dst /* nothing suitable found, so just set dst to look at path (i.e. no alloc/free needed) */ *dst = path; - return 0; + return false; } -/* less then 1.0 evaluates to false, use epsilon to avoid float error */ +/* less than 1.0 evaluates to false, use epsilon to avoid float error */ #define ANIMSYS_FLOAT_AS_BOOL(value) ((value) > ((1.0f - FLT_EPSILON))) /* Write the given value to a setting using RNA, and return success */ @@ -1375,7 +1382,7 @@ static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_ind path, array_index, array_len - 1); } - return 0; + return false; } switch (RNA_property_type(prop)) { @@ -1429,7 +1436,7 @@ static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_ind break; default: /* nothing can be done here... so it is unsuccessful? */ - return 0; + return false; } /* RNA property update disabled for now - [#28525] [#28690] [#28774] [#28777] */ @@ -1468,7 +1475,7 @@ static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_ind } /* successful */ - return 1; + return true; } else { /* failed to get path */ @@ -1479,7 +1486,7 @@ static bool animsys_write_rna_setting(PointerRNA *ptr, char *path, int array_ind (ptr->id.data) ? (((ID *)ptr->id.data)->name + 2) : "<No ID>", path, array_index); } - return 0; + return false; } } @@ -2680,6 +2687,9 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime) /* linestyles */ EVAL_ANIM_IDS(main->linestyle.first, ADT_RECALC_ANIM); + /* grease pencil */ + EVAL_ANIM_IDS(main->gpencil.first, ADT_RECALC_ANIM); + /* objects */ /* ADT_RECALC_ANIM doesn't need to be supplied here, since object AnimData gets * this tagged by Depsgraph on framechange. This optimization means that objects diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c new file mode 100644 index 00000000000..e2e6e828335 --- /dev/null +++ b/source/blender/blenkernel/intern/appdir.c @@ -0,0 +1,808 @@ +/* + * ***** 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. + * + */ + +/** \file blender/blenlib/intern/appdir.c + * \ingroup bke + * + * Access to application level directories. + */ + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> + +#include "BLI_utildefines.h" +#include "BLI_string.h" +#include "BLI_fileops.h" +#include "BLI_path_util.h" + +#include "BKE_appdir.h" /* own include */ + +#include "GHOST_Path-api.h" + +#include "../blenkernel/BKE_blender.h" /* BLENDER_VERSION, bad level include (no function call) */ + +#include "MEM_guardedalloc.h" + +#ifdef WIN32 +# include "utf_winfunc.h" +# include "utfconv.h" +# include <io.h> +# ifdef _WIN32_IE +# undef _WIN32_IE +# endif +# define _WIN32_IE 0x0501 +# include <windows.h> +# include <shlobj.h> +# include "BLI_winstuff.h" +#else /* non windows */ +# ifdef WITH_BINRELOC +# include "binreloc.h" +# endif +# include <unistd.h> /* mkdtemp on OSX (and probably all *BSD?), not worth making specific check for this OS. */ +#endif /* WIN32 */ + +/* local */ +static char bprogname[FILE_MAX]; /* full path to program executable */ +static char bprogdir[FILE_MAX]; /* full path to directory in which executable is located */ +static char btempdir_base[FILE_MAX]; /* persistent temporary directory */ +static char btempdir_session[FILE_MAX] = ""; /* volatile temporary directory */ + +/* This is now only used to really get the user's default document folder */ +/* On Windows I chose the 'Users/<MyUserName>/Documents' since it's used + * as default location to save documents */ +const char *BKE_appdir_folder_default(void) +{ +#ifndef WIN32 + const char * const xdg_documents_dir = getenv("XDG_DOCUMENTS_DIR"); + + if (xdg_documents_dir) + return xdg_documents_dir; + + return getenv("HOME"); +#else /* Windows */ + static char documentfolder[MAXPATHLEN]; + HRESULT hResult; + + /* Check for %HOME% env var */ + if (uput_getenv("HOME", documentfolder, MAXPATHLEN)) { + if (BLI_is_dir(documentfolder)) return documentfolder; + } + + /* add user profile support for WIN 2K / NT. + * This is %APPDATA%, which translates to either + * %USERPROFILE%\Application Data or since Vista + * to %USERPROFILE%\AppData\Roaming + */ + hResult = SHGetFolderPath(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, documentfolder); + + if (hResult == S_OK) { + if (BLI_is_dir(documentfolder)) return documentfolder; + } + + return NULL; +#endif /* WIN32 */ +} + + +// #define PATH_DEBUG + +/* returns a formatted representation of the specified version number. Non-reentrant! */ +static char *blender_version_decimal(const int ver) +{ + static char version_str[5]; + sprintf(version_str, "%d.%02d", ver / 100, ver % 100); + return version_str; +} + +/** + * Concatenates path_base, (optional) path_sep and (optional) folder_name into targetpath, + * returning true if result points to a directory. + */ +static bool test_path(char *targetpath, const char *path_base, const char *path_sep, const char *folder_name) +{ + char tmppath[FILE_MAX]; + + if (path_sep) BLI_join_dirfile(tmppath, sizeof(tmppath), path_base, path_sep); + else BLI_strncpy(tmppath, path_base, sizeof(tmppath)); + + /* rare cases folder_name is omitted (when looking for ~/.blender/2.xx dir only) */ + if (folder_name) + BLI_make_file_string("/", targetpath, tmppath, folder_name); + else + BLI_strncpy(targetpath, tmppath, sizeof(tmppath)); + /* FIXME: why is "//" on front of tmppath expanded to "/" (by BLI_join_dirfile) + * if folder_name is specified but not otherwise? */ + + if (BLI_is_dir(targetpath)) { +#ifdef PATH_DEBUG + printf("\t%s found: %s\n", __func__, targetpath); +#endif + return true; + } + else { +#ifdef PATH_DEBUG + printf("\t%s missing: %s\n", __func__, targetpath); +#endif + //targetpath[0] = '\0'; + return false; + } +} + +/** + * Puts the value of the specified environment variable into *path if it exists + * and points at a directory. Returns true if this was done. + */ +static bool test_env_path(char *path, const char *envvar) +{ + const char *env = envvar ? getenv(envvar) : NULL; + if (!env) return false; + + if (BLI_is_dir(env)) { + BLI_strncpy(path, env, FILE_MAX); +#ifdef PATH_DEBUG + printf("\t%s env %s found: %s\n", __func__, envvar, env); +#endif + return true; + } + else { + path[0] = '\0'; +#ifdef PATH_DEBUG + printf("\t%s env %s missing: %s\n", __func__, envvar, env); +#endif + return false; + } +} + +/** + * Constructs in \a targetpath the name of a directory relative to a version-specific + * subdirectory in the parent directory of the Blender executable. + * + * \param targetpath String to return path + * \param folder_name Optional folder name within version-specific directory + * \param subfolder_name Optional subfolder name within folder_name + * \param ver To construct name of version-specific directory within bprogdir + * \return true if such a directory exists. + */ +static bool get_path_local(char *targetpath, const char *folder_name, const char *subfolder_name, const int ver) +{ + char relfolder[FILE_MAX]; + +#ifdef PATH_DEBUG + printf("%s...\n", __func__); +#endif + + if (folder_name) { + if (subfolder_name) { + BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name); + } + else { + BLI_strncpy(relfolder, folder_name, sizeof(relfolder)); + } + } + else { + relfolder[0] = '\0'; + } + + /* try EXECUTABLE_DIR/2.5x/folder_name - new default directory for local blender installed files */ +#ifdef __APPLE__ + static char osx_resourses[FILE_MAX]; /* due new codesign situation in OSX > 10.9.5 we must move the blender_version dir with contents to Resources */ + sprintf(osx_resourses, "%s../Resources", bprogdir); + return test_path(targetpath, osx_resourses, blender_version_decimal(ver), relfolder); +#else + return test_path(targetpath, bprogdir, blender_version_decimal(ver), relfolder); +#endif +} + +/** + * Is this an install with user files kept together with the Blender executable and its + * installation files. + */ +static bool is_portable_install(void) +{ + /* detect portable install by the existence of config folder */ + const int ver = BLENDER_VERSION; + char path[FILE_MAX]; + + return get_path_local(path, "config", NULL, ver); +} + +/** + * Returns the path of a folder within the user-files area. + * + * + * \param targetpath String to return path + * \param folder_name default name of folder within user area + * \param subfolder_name optional name of subfolder within folder + * \param envvar name of environment variable which, if defined, overrides folder_name + * \param ver Blender version, used to construct a subdirectory name + * \return true if it was able to construct such a path. + */ +static bool get_path_user(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver) +{ + char user_path[FILE_MAX]; + const char *user_base_path; + + /* for portable install, user path is always local */ + if (is_portable_install()) + return get_path_local(targetpath, folder_name, subfolder_name, ver); + + user_path[0] = '\0'; + + if (test_env_path(user_path, envvar)) { + if (subfolder_name) { + return test_path(targetpath, user_path, NULL, subfolder_name); + } + else { + BLI_strncpy(targetpath, user_path, FILE_MAX); + return true; + } + } + + user_base_path = (const char *)GHOST_getUserDir(ver, blender_version_decimal(ver)); + if (user_base_path) + BLI_strncpy(user_path, user_base_path, FILE_MAX); + + if (!user_path[0]) + return false; + +#ifdef PATH_DEBUG + printf("%s: %s\n", __func__, user_path); +#endif + + if (subfolder_name) { + return test_path(targetpath, user_path, folder_name, subfolder_name); + } + else { + return test_path(targetpath, user_path, NULL, folder_name); + } +} + +/** + * Returns the path of a folder within the Blender installation directory. + * + * \param targetpath String to return path + * \param folder_name default name of folder within installation area + * \param subfolder_name optional name of subfolder within folder + * \param envvar name of environment variable which, if defined, overrides folder_name + * \param ver Blender version, used to construct a subdirectory name + * \return true if it was able to construct such a path. + */ +static bool get_path_system(char *targetpath, const char *folder_name, const char *subfolder_name, const char *envvar, const int ver) +{ + char system_path[FILE_MAX]; + const char *system_base_path; + char cwd[FILE_MAX]; + char relfolder[FILE_MAX]; + + if (folder_name) { + if (subfolder_name) { + BLI_join_dirfile(relfolder, sizeof(relfolder), folder_name, subfolder_name); + } + else { + BLI_strncpy(relfolder, folder_name, sizeof(relfolder)); + } + } + else { + relfolder[0] = '\0'; + } + + /* first allow developer only overrides to the system path + * these are only used when running blender from source */ + + /* try CWD/release/folder_name */ + if (BLI_current_working_dir(cwd, sizeof(cwd))) { + if (test_path(targetpath, cwd, "release", relfolder)) { + return true; + } + } + + /* try EXECUTABLE_DIR/release/folder_name */ + if (test_path(targetpath, bprogdir, "release", relfolder)) + return true; + + /* end developer overrides */ + + + + system_path[0] = '\0'; + + if (test_env_path(system_path, envvar)) { + if (subfolder_name) { + return test_path(targetpath, system_path, NULL, subfolder_name); + } + else { + BLI_strncpy(targetpath, system_path, FILE_MAX); + return true; + } + } + + system_base_path = (const char *)GHOST_getSystemDir(ver, blender_version_decimal(ver)); + if (system_base_path) + BLI_strncpy(system_path, system_base_path, FILE_MAX); + + if (!system_path[0]) + return false; + +#ifdef PATH_DEBUG + printf("%s: %s\n", __func__, system_path); +#endif + + if (subfolder_name) { + /* try $BLENDERPATH/folder_name/subfolder_name */ + return test_path(targetpath, system_path, folder_name, subfolder_name); + } + else { + /* try $BLENDERPATH/folder_name */ + return test_path(targetpath, system_path, NULL, folder_name); + } +} + +/* get a folder out of the 'folder_id' presets for paths */ +/* returns the path if found, NULL string if not */ +const char *BKE_appdir_folder_id(const int folder_id, const char *subfolder) +{ + const int ver = BLENDER_VERSION; + static char path[FILE_MAX] = ""; + + switch (folder_id) { + case BLENDER_DATAFILES: /* general case */ + if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break; + if (get_path_local(path, "datafiles", subfolder, ver)) break; + if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break; + return NULL; + + case BLENDER_USER_DATAFILES: + if (get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver)) break; + return NULL; + + case BLENDER_SYSTEM_DATAFILES: + if (get_path_local(path, "datafiles", subfolder, ver)) break; + if (get_path_system(path, "datafiles", subfolder, "BLENDER_SYSTEM_DATAFILES", ver)) break; + return NULL; + + case BLENDER_USER_AUTOSAVE: + if (get_path_user(path, "autosave", subfolder, "BLENDER_USER_DATAFILES", ver)) break; + return NULL; + + case BLENDER_USER_CONFIG: + if (get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver)) break; + return NULL; + + case BLENDER_USER_SCRIPTS: + if (get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver)) break; + return NULL; + + case BLENDER_SYSTEM_SCRIPTS: + if (get_path_local(path, "scripts", subfolder, ver)) break; + if (get_path_system(path, "scripts", subfolder, "BLENDER_SYSTEM_SCRIPTS", ver)) break; + return NULL; + + case BLENDER_SYSTEM_PYTHON: + if (get_path_local(path, "python", subfolder, ver)) break; + if (get_path_system(path, "python", subfolder, "BLENDER_SYSTEM_PYTHON", ver)) break; + return NULL; + + default: + BLI_assert(0); + break; + } + + return path; +} + +/** + * Returns the path to a folder in the user area without checking that it actually exists first. + */ +const char *BKE_appdir_folder_id_user_notest(const int folder_id, const char *subfolder) +{ + const int ver = BLENDER_VERSION; + static char path[FILE_MAX] = ""; + + switch (folder_id) { + case BLENDER_USER_DATAFILES: + get_path_user(path, "datafiles", subfolder, "BLENDER_USER_DATAFILES", ver); + break; + case BLENDER_USER_CONFIG: + get_path_user(path, "config", subfolder, "BLENDER_USER_CONFIG", ver); + break; + case BLENDER_USER_AUTOSAVE: + get_path_user(path, "autosave", subfolder, "BLENDER_USER_AUTOSAVE", ver); + break; + case BLENDER_USER_SCRIPTS: + get_path_user(path, "scripts", subfolder, "BLENDER_USER_SCRIPTS", ver); + break; + default: + BLI_assert(0); + break; + } + + if ('\0' == path[0]) { + return NULL; + } + return path; +} + +/** + * Returns the path to a folder in the user area, creating it if it doesn't exist. + */ +const char *BKE_appdir_folder_id_create(int folder_id, const char *subfolder) +{ + const char *path; + + /* only for user folders */ + if (!ELEM(folder_id, BLENDER_USER_DATAFILES, BLENDER_USER_CONFIG, BLENDER_USER_SCRIPTS, BLENDER_USER_AUTOSAVE)) + return NULL; + + path = BKE_appdir_folder_id(folder_id, subfolder); + + if (!path) { + path = BKE_appdir_folder_id_user_notest(folder_id, subfolder); + if (path) BLI_dir_create_recursive(path); + } + + return path; +} + +/** + * Returns the path of the top-level version-specific local, user or system directory. + * If do_check, then the result will be NULL if the directory doesn't exist. + */ +const char *BKE_appdir_folder_id_version(const int folder_id, const int ver, const bool do_check) +{ + static char path[FILE_MAX] = ""; + bool ok; + switch (folder_id) { + case BLENDER_RESOURCE_PATH_USER: + ok = get_path_user(path, NULL, NULL, NULL, ver); + break; + case BLENDER_RESOURCE_PATH_LOCAL: + ok = get_path_local(path, NULL, NULL, ver); + break; + case BLENDER_RESOURCE_PATH_SYSTEM: + ok = get_path_system(path, NULL, NULL, NULL, ver); + break; + default: + path[0] = '\0'; /* in case do_check is false */ + ok = false; + BLI_assert(!"incorrect ID"); + break; + } + + if (!ok && do_check) { + return NULL; + } + + return path; +} + +#ifdef PATH_DEBUG +# undef PATH_DEBUG +#endif + + +/* -------------------------------------------------------------------- */ +/* Preset paths */ + +/** + * Tries appending each of the semicolon-separated extensions in the PATHEXT + * environment variable (Windows-only) onto *name in turn until such a file is found. + * Returns success/failure. + */ +static int add_win32_extension(char *name) +{ + int retval = 0; + int type; + + type = BLI_exists(name); + if ((type == 0) || S_ISDIR(type)) { +#ifdef _WIN32 + char filename[FILE_MAX]; + char ext[FILE_MAX]; + const char *extensions = getenv("PATHEXT"); + if (extensions) { + char *temp; + do { + strcpy(filename, name); + temp = strstr(extensions, ";"); + if (temp) { + strncpy(ext, extensions, temp - extensions); + ext[temp - extensions] = 0; + extensions = temp + 1; + strcat(filename, ext); + } + else { + strcat(filename, extensions); + } + + type = BLI_exists(filename); + if (type && (!S_ISDIR(type))) { + retval = 1; + strcpy(name, filename); + break; + } + } while (temp); + } +#endif + } + else { + retval = 1; + } + + return (retval); +} + +/** + * Checks if name is a fully qualified filename to an executable. + * If not it searches $PATH for the file. On Windows it also + * adds the correct extension (.com .exe etc) from + * $PATHEXT if necessary. Also on Windows it translates + * the name to its 8.3 version to prevent problems with + * spaces and stuff. Final result is returned in fullname. + * + * \param fullname The full path and full name of the executable + * (must be FILE_MAX minimum) + * \param name The name of the executable (usually argv[0]) to be checked + */ +static void bli_where_am_i(char *fullname, const size_t maxlen, const char *name) +{ + char filename[FILE_MAX]; + const char *path = NULL, *temp; + +#ifdef _WIN32 + const char *separator = ";"; +#else + const char *separator = ":"; +#endif + + +#ifdef WITH_BINRELOC + /* linux uses binreloc since argv[0] is not reliable, call br_init( NULL ) first */ + path = br_find_exe(NULL); + if (path) { + BLI_strncpy(fullname, path, maxlen); + free((void *)path); + return; + } +#endif + +#ifdef _WIN32 + wchar_t *fullname_16 = MEM_mallocN(maxlen * sizeof(wchar_t), "ProgramPath"); + if (GetModuleFileNameW(0, fullname_16, maxlen)) { + conv_utf_16_to_8(fullname_16, fullname, maxlen); + if (!BLI_exists(fullname)) { + printf("path can't be found: \"%.*s\"\n", (int)maxlen, fullname); + MessageBox(NULL, "path contains invalid characters or is too long (see console)", "Error", MB_OK); + } + MEM_freeN(fullname_16); + return; + } + + MEM_freeN(fullname_16); +#endif + + /* unix and non linux */ + if (name && name[0]) { + + BLI_strncpy(fullname, name, maxlen); + if (name[0] == '.') { + char wdir[FILE_MAX] = ""; + BLI_current_working_dir(wdir, sizeof(wdir)); /* backup cwd to restore after */ + + // not needed but avoids annoying /./ in name + if (name[1] == SEP) + BLI_join_dirfile(fullname, maxlen, wdir, name + 2); + else + BLI_join_dirfile(fullname, maxlen, wdir, name); + + add_win32_extension(fullname); /* XXX, doesnt respect length */ + } + else if (BLI_last_slash(name)) { + // full path + BLI_strncpy(fullname, name, maxlen); + add_win32_extension(fullname); + } + else { + // search for binary in $PATH + path = getenv("PATH"); + if (path) { + do { + temp = strstr(path, separator); + if (temp) { + strncpy(filename, path, temp - path); + filename[temp - path] = 0; + path = temp + 1; + } + else { + strncpy(filename, path, sizeof(filename)); + } + BLI_path_append(fullname, maxlen, name); + if (add_win32_extension(filename)) { + BLI_strncpy(fullname, filename, maxlen); + break; + } + } while (temp); + } + } +#if defined(DEBUG) + if (strcmp(name, fullname)) { + printf("guessing '%s' == '%s'\n", name, fullname); + } +#endif + } +} + +void BKE_appdir_program_path_init(const char *argv0) +{ + bli_where_am_i(bprogname, sizeof(bprogname), argv0); + BLI_split_dir_part(bprogname, bprogdir, sizeof(bprogdir)); +} + +/** + * Path to executable + */ +const char *BKE_appdir_program_path(void) +{ + return bprogname; +} + +/** + * Path to directory of executable + */ +const char *BKE_appdir_program_dir(void) +{ + return bprogdir; +} + +/** + * Gets the temp directory when blender first runs. + * If the default path is not found, use try $TEMP + * + * Also make sure the temp dir has a trailing slash + * + * \param fullname The full path to the temporary temp directory + * \param basename The full path to the persistent temp directory (may be NULL) + * \param maxlen The size of the fullname buffer + * \param userdir Directory specified in user preferences + */ +static void BLI_where_is_temp(char *fullname, char *basename, const size_t maxlen, char *userdir) +{ + /* Clear existing temp dir, if needed. */ + BKE_tempdir_session_purge(); + + fullname[0] = '\0'; + if (basename) { + basename[0] = '\0'; + } + + if (userdir && BLI_is_dir(userdir)) { + BLI_strncpy(fullname, userdir, maxlen); + } + + +#ifdef WIN32 + if (fullname[0] == '\0') { + const char *tmp = getenv("TEMP"); /* Windows */ + if (tmp && BLI_is_dir(tmp)) { + BLI_strncpy(fullname, tmp, maxlen); + } + } +#else + /* Other OS's - Try TMP and TMPDIR */ + if (fullname[0] == '\0') { + const char *tmp = getenv("TMP"); + if (tmp && BLI_is_dir(tmp)) { + BLI_strncpy(fullname, tmp, maxlen); + } + } + + if (fullname[0] == '\0') { + const char *tmp = getenv("TMPDIR"); + if (tmp && BLI_is_dir(tmp)) { + BLI_strncpy(fullname, tmp, maxlen); + } + } +#endif + + if (fullname[0] == '\0') { + BLI_strncpy(fullname, "/tmp/", maxlen); + } + else { + /* add a trailing slash if needed */ + BLI_add_slash(fullname); +#ifdef WIN32 + if (userdir && userdir != fullname) { + BLI_strncpy(userdir, fullname, maxlen); /* also set user pref to show %TEMP%. /tmp/ is just plain confusing for Windows users. */ + } +#endif + } + + /* Now that we have a valid temp dir, add system-generated unique sub-dir. */ + if (basename) { + /* 'XXXXXX' is kind of tag to be replaced by mktemp-familly by an uuid. */ + char *tmp_name = BLI_strdupcat(fullname, "blender_XXXXXX"); + const size_t ln = strlen(tmp_name) + 1; + if (ln <= maxlen) { +#ifdef WIN32 + if (_mktemp_s(tmp_name, ln) == 0) { + BLI_dir_create_recursive(tmp_name); + } +#else + mkdtemp(tmp_name); +#endif + } + if (BLI_is_dir(tmp_name)) { + BLI_strncpy(basename, fullname, maxlen); + BLI_strncpy(fullname, tmp_name, maxlen); + BLI_add_slash(fullname); + } + else { + printf("Warning! Could not generate a temp file name for '%s', falling back to '%s'\n", tmp_name, fullname); + } + + MEM_freeN(tmp_name); + } +} + +/** + * Sets btempdir_base to userdir if specified and is a valid directory, otherwise + * chooses a suitable OS-specific temporary directory. + * Sets btempdir_session to a mkdtemp-generated sub-dir of btempdir_base. + * + * \note On Window userdir will be set to the temporary directory! + */ +void BKE_tempdir_init(char *userdir) +{ + BLI_where_is_temp(btempdir_session, btempdir_base, FILE_MAX, userdir); +; +} + +/** + * Path to temporary directory (with trailing slash) + */ +const char *BKE_tempdir_session(void) +{ + return btempdir_session[0] ? btempdir_session : BKE_tempdir_base(); +} + +/** + * Path to persistent temporary directory (with trailing slash) + */ +const char *BKE_tempdir_base(void) +{ + return btempdir_base; +} + +/** + * Path to the system temporary directory (with trailing slash) + */ +void BKE_tempdir_system_init(char *dir) +{ + BLI_where_is_temp(dir, NULL, FILE_MAX, NULL); +} + +/** + * Delete content of this instance's temp dir. + */ +void BKE_tempdir_session_purge(void) +{ + if (btempdir_session[0] && BLI_is_dir(btempdir_session)) { + BLI_delete(btempdir_session, true, true); + } +} diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index bb05b5de8a6..f4a5d33854a 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -840,7 +840,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float /* bone defmats are already in the channels, chan_mat */ /* initialize B_bone matrices and dual quaternions */ - totchan = BLI_countlist(&armOb->pose->chanbase); + totchan = BLI_listbase_count(&armOb->pose->chanbase); if (use_quaternion) { dualquats = MEM_callocN(sizeof(DualQuat) * totchan, "dualquats"); @@ -866,7 +866,7 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float armature_def_nr = defgroup_name_index(target, defgrp_name); if (ELEM(target->type, OB_MESH, OB_LATTICE)) { - defbase_tot = BLI_countlist(&target->defbase); + defbase_tot = BLI_listbase_count(&target->defbase); if (target->type == OB_MESH) { Mesh *me = target->data; @@ -1654,6 +1654,7 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected pchanw.next = pchan->next; pchanw.parent = pchan->parent; pchanw.child = pchan->child; + pchanw.custom_tx = pchan->custom_tx; pchanw.mpath = pchan->mpath; pchan->mpath = NULL; @@ -1662,7 +1663,7 @@ static void pose_proxy_synchronize(Object *ob, Object *from, int layer_protected if (pchanw.prop) { pchanw.prop = IDP_CopyProperty(pchanw.prop); - /* use the values from the the existing props */ + /* use the values from the existing props */ if (pchan->prop) { IDP_SyncGroupValues(pchanw.prop, pchan->prop); } @@ -1916,7 +1917,7 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos if (ikData->points) MEM_freeN(ikData->points); ikData->numpoints = ikData->chainlen + 1; - ikData->points = MEM_callocN(sizeof(float) * ikData->numpoints, "Spline IK Binding"); + ikData->points = MEM_mallocN(sizeof(float) * ikData->numpoints, "Spline IK Binding"); /* bind 'tip' of chain (i.e. first joint = tip of bone with the Spline IK Constraint) */ ikData->points[0] = 1.0f; @@ -1944,6 +1945,9 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos ikData->flag |= CONSTRAINT_SPLINEIK_BOUND; } + /* disallow negative values (happens with float precision) */ + CLAMP_MIN(ikData->points[segcount], 0.0f); + /* apply corrections for sensitivity to scaling on a copy of the bind points, * since it's easier to determine the positions of all the joints beforehand this way */ @@ -1989,7 +1993,7 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos tree->chainlen = segcount; /* copy over the array of links to bones in the chain (from tip to root) */ - tree->chain = MEM_callocN(sizeof(bPoseChannel *) * segcount, "SplineIK Chain"); + tree->chain = MEM_mallocN(sizeof(bPoseChannel *) * segcount, "SplineIK Chain"); memcpy(tree->chain, pchanChain, sizeof(bPoseChannel *) * segcount); /* store reference to joint position array */ diff --git a/source/blender/blenkernel/intern/autoexec.c b/source/blender/blenkernel/intern/autoexec.c index 872780bd50a..d9462cd0262 100644 --- a/source/blender/blenkernel/intern/autoexec.c +++ b/source/blender/blenkernel/intern/autoexec.c @@ -34,9 +34,12 @@ #include "BLI_utildefines.h" #include "BLI_fnmatch.h" -#include "BLI_string.h" #include "BLI_path_util.h" +#ifdef WIN32 +# include "BLI_string.h" +#endif + #include "BKE_autoexec.h" /* own include */ /** diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index adfe43cb2a3..96f769587d9 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -61,6 +61,7 @@ #include "IMB_imbuf.h" #include "IMB_moviecache.h" +#include "BKE_appdir.h" #include "BKE_blender.h" #include "BKE_bpath.h" #include "BKE_brush.h" @@ -493,10 +494,11 @@ bool BKE_read_file_from_memory( BLO_update_defaults_startup_blend(bfd->main); setup_app_data(C, bfd, "<memory2>"); } - else + else { BKE_reports_prepend(reports, "Loading failed: "); + } - return (bfd ? 1 : 0); + return (bfd != NULL); } /* memfile is the undo buffer */ @@ -516,10 +518,11 @@ bool BKE_read_file_from_memfile( setup_app_data(C, bfd, "<memory1>"); } - else + else { BKE_reports_prepend(reports, "Loading failed: "); + } - return (bfd ? 1 : 0); + return (bfd != NULL); } /* only read the userdef from a .blend */ @@ -687,7 +690,7 @@ void BKE_write_undo(bContext *C, const char *name) counter = counter % U.undosteps; BLI_snprintf(numstr, sizeof(numstr), "%d.blend", counter); - BLI_make_file_string("/", filepath, BLI_temp_dir_session(), numstr); + BLI_make_file_string("/", filepath, BKE_tempdir_session(), numstr); /* success = */ /* UNUSED */ BLO_write_file(CTX_data_main(C), filepath, fileflags, NULL, NULL); @@ -834,13 +837,13 @@ bool BKE_undo_save_file(const char *filename) int file, oflags; if ((U.uiflag & USER_GLOBALUNDO) == 0) { - return 0; + return false; } uel = curundo; if (uel == NULL) { fprintf(stderr, "No undo buffer to save recovery file\n"); - return 0; + return false; } /* note: This is currently used for autosave and 'quit.blend', where _not_ following symlinks is OK, @@ -862,7 +865,7 @@ bool BKE_undo_save_file(const char *filename) if (file == -1) { fprintf(stderr, "Unable to save '%s': %s\n", filename, errno ? strerror(errno) : "Unknown error opening file"); - return 0; + return false; } for (chunk = uel->memfile.chunks.first; chunk; chunk = chunk->next) { @@ -876,9 +879,9 @@ bool BKE_undo_save_file(const char *filename) if (chunk) { fprintf(stderr, "Unable to save '%s': %s\n", filename, errno ? strerror(errno) : "Unknown error writing file"); - return 0; + return false; } - return 1; + return true; } /* sets curscene */ diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index 5731455fc01..4a564614ff3 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -995,7 +995,7 @@ void boid_brain(BoidBrainData *bbd, int p, ParticleData *pa) case eBoidRulesetType_Random: { /* use random rule for each particle (allways same for same particle though) */ - rule = BLI_findlink(&state->rules, rand % BLI_countlist(&state->rules)); + rule = BLI_findlink(&state->rules, rand % BLI_listbase_count(&state->rules)); apply_boid_rule(bbd, rule, &val, pa, -1.0); break; diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c index ae6ae6087af..92f66cdde76 100644 --- a/source/blender/blenkernel/intern/brush.c +++ b/source/blender/blenkernel/intern/brush.c @@ -33,7 +33,6 @@ #include "BLI_math.h" #include "BLI_blenlib.h" #include "BLI_rand.h" -#include "BLI_rect.h" #include "BKE_brush.h" #include "BKE_colortools.h" @@ -49,7 +48,6 @@ #include "IMB_imbuf_types.h" #include "RE_render_ext.h" /* externtex */ -#include "RE_shader_ext.h" static RNG *brush_rng; @@ -1048,7 +1046,7 @@ struct ImBuf *BKE_brush_gen_radial_control_imbuf(Brush *br, bool secondary) for (i = 0; i < side; ++i) { for (j = 0; j < side; ++j) { - float magn = sqrtf(powf(i - half, 2) + powf(j - half, 2)); + float magn = sqrtf(pow2f(i - half) + pow2f(j - half)); im->rect_float[i * side + j] = BKE_brush_curve_strength_clamp(br, magn, half); } } diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index 1402f62291f..5454062ad1f 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -454,7 +454,7 @@ void BKE_camera_view_frame(Scene *scene, Camera *camera, float r_vec[4][3]) float dummy_drawsize; const float dummy_scale[3] = {1.0f, 1.0f, 1.0f}; - BKE_camera_view_frame_ex(scene, camera, false, 1.0, dummy_scale, + BKE_camera_view_frame_ex(scene, camera, 0.0, true, dummy_scale, dummy_asp, dummy_shift, &dummy_drawsize, r_vec); } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index bfc70c91181..6ac85695570 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -35,7 +35,6 @@ */ #include "BLI_math.h" -#include "BLI_blenlib.h" #include "BLI_edgehash.h" #include "BLI_utildefines.h" #include "BLI_stackdefines.h" @@ -49,7 +48,6 @@ #include "BKE_editmesh.h" #include "BKE_curve.h" -#include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_object_types.h" @@ -61,7 +59,6 @@ #include "GPU_draw.h" #include "GPU_extensions.h" #include "GPU_glew.h" -#include "GPU_material.h" #include <string.h> #include <limits.h> @@ -343,106 +340,64 @@ static void cdDM_update_normals_from_pbvh(DerivedMesh *dm) static void cdDM_drawVerts(DerivedMesh *dm) { - CDDerivedMesh *cddm = (CDDerivedMesh *) dm; - MVert *mv = cddm->mvert; - int i; - - if (GPU_buffer_legacy(dm)) { - glBegin(GL_POINTS); - for (i = 0; i < dm->numVertData; i++, mv++) - glVertex3fv(mv->co); - glEnd(); - } - else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */ - GPU_vertex_setup(dm); - if (!GPU_buffer_legacy(dm)) { - if (dm->drawObject->tot_triangle_point) - glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_triangle_point); - else - glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_loose_point); - } - GPU_buffer_unbind(); - } + GPU_vertex_setup(dm); + if (dm->drawObject->tot_triangle_point) + glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_triangle_point); + else + glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_loose_point); + GPU_buffer_unbind(); } static void cdDM_drawUVEdges(DerivedMesh *dm) { CDDerivedMesh *cddm = (CDDerivedMesh *) dm; MFace *mf = cddm->mface; - MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE); int i; if (mf) { - if (GPU_buffer_legacy(dm)) { - glBegin(GL_LINES); - for (i = 0; i < dm->numTessFaceData; i++, mf++, tf++) { - if (!(mf->flag & ME_HIDE)) { - glVertex2fv(tf->uv[0]); - glVertex2fv(tf->uv[1]); - - glVertex2fv(tf->uv[1]); - glVertex2fv(tf->uv[2]); - - if (!mf->v4) { - glVertex2fv(tf->uv[2]); - glVertex2fv(tf->uv[0]); - } - else { - glVertex2fv(tf->uv[2]); - glVertex2fv(tf->uv[3]); - - glVertex2fv(tf->uv[3]); - glVertex2fv(tf->uv[0]); - } - } + int prevstart = 0; + int prevdraw = 1; + int draw = 1; + int curpos = 0; + + GPU_uvedge_setup(dm); + for (i = 0; i < dm->numTessFaceData; i++, mf++) { + if (!(mf->flag & ME_HIDE)) { + draw = 1; } - glEnd(); - } - else { - int prevstart = 0; - int prevdraw = 1; - int draw = 1; - int curpos = 0; - - GPU_uvedge_setup(dm); - if (!GPU_buffer_legacy(dm)) { - for (i = 0; i < dm->numTessFaceData; i++, mf++) { - if (!(mf->flag & ME_HIDE)) { - draw = 1; - } - else { - draw = 0; - } - if (prevdraw != draw) { - if (prevdraw > 0 && (curpos - prevstart) > 0) { - glDrawArrays(GL_LINES, prevstart, curpos - prevstart); - } - prevstart = curpos; - } - if (mf->v4) { - curpos += 8; - } - else { - curpos += 6; - } - prevdraw = draw; - } + else { + draw = 0; + } + if (prevdraw != draw) { if (prevdraw > 0 && (curpos - prevstart) > 0) { glDrawArrays(GL_LINES, prevstart, curpos - prevstart); } + prevstart = curpos; + } + if (mf->v4) { + curpos += 8; } - GPU_buffer_unbind(); + else { + curpos += 6; + } + prevdraw = draw; + } + if (prevdraw > 0 && (curpos - prevstart) > 0) { + glDrawArrays(GL_LINES, prevstart, curpos - prevstart); } + GPU_buffer_unbind(); } } static void cdDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdges) { CDDerivedMesh *cddm = (CDDerivedMesh *) dm; - MVert *mvert = cddm->mvert; MEdge *medge = cddm->medge; int i; - + int prevstart = 0; + int prevdraw = 1; + bool draw = true; + if (cddm->pbvh && cddm->pbvh_draw && BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH) { @@ -451,97 +406,60 @@ static void cdDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdg return; } - if (GPU_buffer_legacy(dm)) { - DEBUG_VBO("Using legacy code. cdDM_drawEdges\n"); - glBegin(GL_LINES); - for (i = 0; i < dm->numEdgeData; i++, medge++) { - if ((drawAllEdges || (medge->flag & ME_EDGEDRAW)) && - (drawLooseEdges || !(medge->flag & ME_LOOSEEDGE))) - { - glVertex3fv(mvert[medge->v1].co); - glVertex3fv(mvert[medge->v2].co); - } + GPU_edge_setup(dm); + for (i = 0; i < dm->numEdgeData; i++, medge++) { + if ((drawAllEdges || (medge->flag & ME_EDGEDRAW)) && + (drawLooseEdges || !(medge->flag & ME_LOOSEEDGE))) + { + draw = true; } - glEnd(); - } - else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */ - int prevstart = 0; - int prevdraw = 1; - bool draw = true; - - GPU_edge_setup(dm); - if (!GPU_buffer_legacy(dm)) { - for (i = 0; i < dm->numEdgeData; i++, medge++) { - if ((drawAllEdges || (medge->flag & ME_EDGEDRAW)) && - (drawLooseEdges || !(medge->flag & ME_LOOSEEDGE))) - { - draw = true; - } - else { - draw = false; - } - if (prevdraw != draw) { - if (prevdraw > 0 && (i - prevstart) > 0) { - GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, prevstart * 2, (i - prevstart) * 2); - } - prevstart = i; - } - prevdraw = draw; - } + else { + draw = false; + } + if (prevdraw != draw) { if (prevdraw > 0 && (i - prevstart) > 0) { GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, prevstart * 2, (i - prevstart) * 2); } + prevstart = i; } - GPU_buffer_unbind(); + prevdraw = draw; } + if (prevdraw > 0 && (i - prevstart) > 0) { + GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, prevstart * 2, (i - prevstart) * 2); + } + GPU_buffer_unbind(); } static void cdDM_drawLooseEdges(DerivedMesh *dm) { CDDerivedMesh *cddm = (CDDerivedMesh *) dm; - MVert *mvert = cddm->mvert; MEdge *medge = cddm->medge; int i; - - if (GPU_buffer_legacy(dm)) { - DEBUG_VBO("Using legacy code. cdDM_drawLooseEdges\n"); - glBegin(GL_LINES); - for (i = 0; i < dm->numEdgeData; i++, medge++) { - if (medge->flag & ME_LOOSEEDGE) { - glVertex3fv(mvert[medge->v1].co); - glVertex3fv(mvert[medge->v2].co); - } + + int prevstart = 0; + int prevdraw = 1; + int draw = 1; + + GPU_edge_setup(dm); + for (i = 0; i < dm->numEdgeData; i++, medge++) { + if (medge->flag & ME_LOOSEEDGE) { + draw = 1; } - glEnd(); - } - else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */ - int prevstart = 0; - int prevdraw = 1; - int draw = 1; - - GPU_edge_setup(dm); - if (!GPU_buffer_legacy(dm)) { - for (i = 0; i < dm->numEdgeData; i++, medge++) { - if (medge->flag & ME_LOOSEEDGE) { - draw = 1; - } - else { - draw = 0; - } - if (prevdraw != draw) { - if (prevdraw > 0 && (i - prevstart) > 0) { - GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, prevstart * 2, (i - prevstart) * 2); - } - prevstart = i; - } - prevdraw = draw; - } + else { + draw = 0; + } + if (prevdraw != draw) { if (prevdraw > 0 && (i - prevstart) > 0) { GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, prevstart * 2, (i - prevstart) * 2); } + prevstart = i; } - GPU_buffer_unbind(); + prevdraw = draw; + } + if (prevdraw > 0 && (i - prevstart) > 0) { + GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, prevstart * 2, (i - prevstart) * 2); } + GPU_buffer_unbind(); } static void cdDM_drawFacesSolid(DerivedMesh *dm, @@ -549,11 +467,7 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, bool UNUSED(fast), DMSetMaterial setMaterial) { CDDerivedMesh *cddm = (CDDerivedMesh *) dm; - MVert *mvert = cddm->mvert; - MFace *mface = cddm->mface; - const float *nors = dm->getTessFaceDataArray(dm, CD_NORMAL); - const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); - int a, glmode = -1, shademodel = -1, matnr = -1, drawCurrentMat = 1; + int a; if (cddm->pbvh && cddm->pbvh_draw) { if (dm->numTessFaceData) { @@ -566,121 +480,37 @@ static void cdDM_drawFacesSolid(DerivedMesh *dm, return; } - - if (GPU_buffer_legacy(dm)) { - DEBUG_VBO("Using legacy code. cdDM_drawFacesSolid\n"); - glBegin(glmode = GL_QUADS); - for (a = 0; a < dm->numTessFaceData; a++, mface++) { - int new_glmode, new_matnr, new_shademodel; - - new_glmode = mface->v4 ? GL_QUADS : GL_TRIANGLES; - new_matnr = mface->mat_nr + 1; - new_shademodel = (lnors || (mface->flag & ME_SMOOTH)) ? GL_SMOOTH : GL_FLAT; - - - if ((new_glmode != glmode) || (new_shademodel != shademodel) || - (setMaterial && (new_matnr != matnr))) - { - glEnd(); - - if (setMaterial) { - drawCurrentMat = setMaterial(matnr = new_matnr, NULL); - } - - glShadeModel(shademodel = new_shademodel); - glBegin(glmode = new_glmode); - } - - if (drawCurrentMat) { - if (lnors) { - glNormal3sv((const GLshort *)lnors[0][0]); - glVertex3fv(mvert[mface->v1].co); - glNormal3sv((const GLshort *)lnors[0][1]); - glVertex3fv(mvert[mface->v2].co); - glNormal3sv((const GLshort *)lnors[0][2]); - glVertex3fv(mvert[mface->v3].co); - if (mface->v4) { - glNormal3sv((const GLshort *)lnors[0][3]); - glVertex3fv(mvert[mface->v4].co); - } - } - else if (shademodel == GL_FLAT) { - if (nors) { - glNormal3fv(nors); - } - else { - /* TODO make this better (cache facenormals as layer?) */ - float nor[3]; - if (mface->v4) { - normal_quad_v3(nor, mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co, mvert[mface->v4].co); - } - else { - normal_tri_v3(nor, mvert[mface->v1].co, mvert[mface->v2].co, mvert[mface->v3].co); - } - glNormal3fv(nor); - } - glVertex3fv(mvert[mface->v1].co); - glVertex3fv(mvert[mface->v2].co); - glVertex3fv(mvert[mface->v3].co); - if (mface->v4) { - glVertex3fv(mvert[mface->v4].co); - } - } - else { /* shademodel == GL_SMOOTH */ - glNormal3sv(mvert[mface->v1].no); - glVertex3fv(mvert[mface->v1].co); - glNormal3sv(mvert[mface->v2].no); - glVertex3fv(mvert[mface->v2].co); - glNormal3sv(mvert[mface->v3].no); - glVertex3fv(mvert[mface->v3].co); - if (mface->v4) { - glNormal3sv(mvert[mface->v4].no); - glVertex3fv(mvert[mface->v4].co); - } - } - } - - if (nors) - nors += 3; - if (lnors) - lnors++; - } - glEnd(); - } - else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */ - GPU_vertex_setup(dm); - GPU_normal_setup(dm); - if (!GPU_buffer_legacy(dm)) { - glShadeModel(GL_SMOOTH); - for (a = 0; a < dm->drawObject->totmaterial; a++) { - if (!setMaterial || setMaterial(dm->drawObject->materials[a].mat_nr + 1, NULL)) { - glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start, - dm->drawObject->materials[a].totpoint); - } - } + + GPU_vertex_setup(dm); + GPU_normal_setup(dm); + glShadeModel(GL_SMOOTH); + for (a = 0; a < dm->drawObject->totmaterial; a++) { + if (!setMaterial || setMaterial(dm->drawObject->materials[a].mat_nr + 1, NULL)) { + glDrawArrays(GL_TRIANGLES, dm->drawObject->materials[a].start, + dm->drawObject->materials[a].totpoint); } - GPU_buffer_unbind(); } + GPU_buffer_unbind(); glShadeModel(GL_FLAT); } static void cdDM_drawFacesTex_common(DerivedMesh *dm, DMSetDrawOptionsTex drawParams, - DMSetDrawOptions drawParamsMapped, + DMSetDrawOptionsMappedTex drawParamsMapped, DMCompareDrawOptions compareDrawOptions, void *userData, DMDrawFlag uvflag) { CDDerivedMesh *cddm = (CDDerivedMesh *) dm; - MVert *mv = cddm->mvert; const MFace *mf = DM_get_tessface_data_layer(dm, CD_MFACE); - const float *nors = dm->getTessFaceDataArray(dm, CD_NORMAL); - const short (*lnors)[4][3] = dm->getTessFaceDataArray(dm, CD_TESSLOOPNORMAL); MTFace *tf = DM_get_tessface_data_layer(dm, CD_MTFACE); MCol *mcol; int i, orig; int colType, startFace = 0; bool use_tface = (uvflag & DM_DRAW_USE_ACTIVE_UV) != 0; + int tottri; + int next_actualFace; + /* double lookup */ const int *index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); @@ -717,208 +547,81 @@ static void cdDM_drawFacesTex_common(DerivedMesh *dm, } cdDM_update_normals_from_pbvh(dm); - - if (GPU_buffer_legacy(dm)) { - int mat_nr_cache = -1; - MTFace *tf_base = DM_get_tessface_data_layer(dm, CD_MTFACE); - MTFace *tf_stencil_base = NULL; - MTFace *tf_stencil = NULL; - - if (uvflag & DM_DRAW_USE_TEXPAINT_UV) { - int stencil = CustomData_get_stencil_layer(&dm->faceData, CD_MTFACE); - tf_stencil_base = CustomData_get_layer_n(&dm->faceData, CD_MTFACE, stencil); + + GPU_vertex_setup(dm); + GPU_normal_setup(dm); + if (uvflag & DM_DRAW_USE_TEXPAINT_UV) + GPU_texpaint_uv_setup(dm); + else + GPU_uv_setup(dm); + if (mcol) { + GPU_color_setup(dm, colType); + } + + tottri = dm->drawObject->tot_triangle_point / 3; + next_actualFace = dm->drawObject->triangle_to_mface[0]; + + glShadeModel(GL_SMOOTH); + /* lastFlag = 0; */ /* UNUSED */ + for (i = 0; i < tottri; i++) { + int actualFace = next_actualFace; + DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL; + int flush = 0; + + if (i != tottri - 1) + next_actualFace = dm->drawObject->triangle_to_mface[i + 1]; + + if (drawParams) { + draw_option = drawParams(use_tface && tf ? &tf[actualFace] : NULL, (mcol != NULL), mf[actualFace].mat_nr); } - - DEBUG_VBO("Using legacy code. cdDM_drawFacesTex_common\n"); - for (i = 0; i < dm->numTessFaceData; i++, mf++) { - MVert *mvert; - DMDrawOption draw_option; - unsigned char *cp = NULL; - - if (uvflag & DM_DRAW_USE_TEXPAINT_UV) { - if (mf->mat_nr != mat_nr_cache) { - tf_base = DM_paint_uvlayer_active_get(dm, mf->mat_nr); - - mat_nr_cache = mf->mat_nr; - } - } - - tf = tf_base ? tf_base + i : NULL; - tf_stencil = tf_stencil_base ? tf_stencil_base + i : NULL; - - if (drawParams) { - draw_option = drawParams(use_tface ? tf : NULL, (mcol != NULL), mf->mat_nr); - } - else { - if (index_mf_to_mpoly) { - orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, i); - if (orig == ORIGINDEX_NONE) { - /* XXX, this is not really correct - * it will draw the previous faces context for this one when we don't know its settings. - * but better then skipping it altogether. - campbell */ - draw_option = DM_DRAW_OPTION_NORMAL; - } - else if (drawParamsMapped) { - draw_option = drawParamsMapped(userData, orig); - } - else { - if (nors) { - nors += 3; - } - continue; - } + else { + if (index_mf_to_mpoly) { + orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace); + if (orig == ORIGINDEX_NONE) { + /* XXX, this is not really correct + * it will draw the previous faces context for this one when we don't know its settings. + * but better then skipping it altogether. - campbell */ + draw_option = DM_DRAW_OPTION_NORMAL; } else if (drawParamsMapped) { - draw_option = drawParamsMapped(userData, i); - } - else { - if (nors) { - nors += 3; - } - continue; + draw_option = drawParamsMapped(userData, orig, mf[actualFace].mat_nr); } } - - if (draw_option != DM_DRAW_OPTION_SKIP) { - if (draw_option != DM_DRAW_OPTION_NO_MCOL && mcol) - cp = (unsigned char *) &mcol[i * 4]; - - if (!(lnors || (mf->flag & ME_SMOOTH))) { - if (nors) { - glNormal3fv(nors); - } - else { - float nor[3]; - if (mf->v4) { - normal_quad_v3(nor, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co, mv[mf->v4].co); - } - else { - normal_tri_v3(nor, mv[mf->v1].co, mv[mf->v2].co, mv[mf->v3].co); - } - glNormal3fv(nor); - } - } - - glBegin(mf->v4 ? GL_QUADS : GL_TRIANGLES); - if (tf) glTexCoord2fv(tf->uv[0]); - if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[0]); - if (cp) glColor3ub(cp[3], cp[2], cp[1]); - mvert = &mv[mf->v1]; - if (lnors) glNormal3sv((const GLshort *)lnors[0][0]); - else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no); - glVertex3fv(mvert->co); - - if (tf) glTexCoord2fv(tf->uv[1]); - if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[1]); - if (cp) glColor3ub(cp[7], cp[6], cp[5]); - mvert = &mv[mf->v2]; - if (lnors) glNormal3sv((const GLshort *)lnors[0][1]); - else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no); - glVertex3fv(mvert->co); - - if (tf) glTexCoord2fv(tf->uv[2]); - if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[2]); - if (cp) glColor3ub(cp[11], cp[10], cp[9]); - mvert = &mv[mf->v3]; - if (lnors) glNormal3sv((const GLshort *)lnors[0][2]); - else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no); - glVertex3fv(mvert->co); - - if (mf->v4) { - if (tf) glTexCoord2fv(tf->uv[3]); - if (tf_stencil) glMultiTexCoord2fv(GL_TEXTURE2, tf->uv[3]); - if (cp) glColor3ub(cp[15], cp[14], cp[13]); - mvert = &mv[mf->v4]; - if (lnors) glNormal3sv((const GLshort *)lnors[0][3]); - else if (mf->flag & ME_SMOOTH) glNormal3sv(mvert->no); - glVertex3fv(mvert->co); - } - glEnd(); + else if (drawParamsMapped) { + draw_option = drawParamsMapped(userData, actualFace, mf[actualFace].mat_nr); } - - if (nors) - nors += 3; - if (lnors) - lnors++; - } - } - else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */ - GPU_vertex_setup(dm); - GPU_normal_setup(dm); - if (uvflag & DM_DRAW_USE_TEXPAINT_UV) - GPU_texpaint_uv_setup(dm); - else - GPU_uv_setup(dm); - if (mcol) { - GPU_color_setup(dm, colType); } - - if (!GPU_buffer_legacy(dm)) { - int tottri = dm->drawObject->tot_triangle_point / 3; - int next_actualFace = dm->drawObject->triangle_to_mface[0]; - - glShadeModel(GL_SMOOTH); - /* lastFlag = 0; */ /* UNUSED */ - for (i = 0; i < tottri; i++) { - int actualFace = next_actualFace; - DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL; - int flush = 0; - - if (i != tottri - 1) - next_actualFace = dm->drawObject->triangle_to_mface[i + 1]; - - if (drawParams) { - draw_option = drawParams(use_tface && tf ? &tf[actualFace] : NULL, (mcol != NULL), mf[actualFace].mat_nr); - } - else { - if (index_mf_to_mpoly) { - orig = DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace); - if (orig == ORIGINDEX_NONE) { - /* XXX, this is not really correct - * it will draw the previous faces context for this one when we don't know its settings. - * but better then skipping it altogether. - campbell */ - draw_option = DM_DRAW_OPTION_NORMAL; - } - else if (drawParamsMapped) { - draw_option = drawParamsMapped(userData, orig); - } - } - else if (drawParamsMapped) { - draw_option = drawParamsMapped(userData, actualFace); - } - } - - /* flush buffer if current triangle isn't drawable or it's last triangle */ - flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == tottri - 1); - - if (!flush && compareDrawOptions) { - /* also compare draw options and flush buffer if they're different + + /* flush buffer if current triangle isn't drawable or it's last triangle */ + flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == tottri - 1); + + if (!flush && compareDrawOptions) { + /* also compare draw options and flush buffer if they're different * need for face selection highlight in edit mode */ - flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0; - } - - if (flush) { - int first = startFace * 3; - /* Add one to the length if we're drawing at the end of the array */ - int count = (i - startFace + (draw_option != DM_DRAW_OPTION_SKIP ? 1 : 0)) * 3; - - if (count) { - if (mcol && draw_option != DM_DRAW_OPTION_NO_MCOL) - GPU_color_switch(1); - else - GPU_color_switch(0); - - glDrawArrays(GL_TRIANGLES, first, count); - } - - startFace = i + 1; - } + flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0; + } + + if (flush) { + int first = startFace * 3; + /* Add one to the length if we're drawing at the end of the array */ + int count = (i - startFace + (draw_option != DM_DRAW_OPTION_SKIP ? 1 : 0)) * 3; + + if (count) { + if (mcol && draw_option != DM_DRAW_OPTION_NO_MCOL) + GPU_color_switch(1); + else + GPU_color_switch(0); + + glDrawArrays(GL_TRIANGLES, first, count); } + + startFace = i + 1; } - - GPU_buffer_unbind(); - glShadeModel(GL_FLAT); } + + GPU_buffer_unbind(); + glShadeModel(GL_FLAT); + } static void cdDM_drawFacesTex(DerivedMesh *dm, @@ -968,7 +671,7 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, /* back-buffer always uses legacy since VBO's would need the * color array temporarily overwritten for drawing, then reset. */ - if (GPU_buffer_legacy(dm) || G.f & G_BACKBUFSEL) { + if (G.f & G_BACKBUFSEL) { DEBUG_VBO("Using legacy code. cdDM_drawMappedFaces\n"); for (i = 0; i < dm->numTessFaceData; i++, mf++) { int drawSmooth = ((flag & DM_DRAW_ALWAYS_SMOOTH) || lnors) ? 1 : (mf->flag & ME_SMOOTH); @@ -1070,79 +773,85 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, } else { /* use OpenGL VBOs or Vertex Arrays instead for better, faster rendering */ int prevstart = 0; + int tottri; + GPU_vertex_setup(dm); GPU_normal_setup(dm); if (useColors && mcol) { GPU_color_setup(dm, colType); } - if (!GPU_buffer_legacy(dm)) { - int tottri = dm->drawObject->tot_triangle_point / 3; - glShadeModel(GL_SMOOTH); + tottri = dm->drawObject->tot_triangle_point / 3; + glShadeModel(GL_SMOOTH); + + if (tottri == 0) { + /* avoid buffer problems in following code */ + } + if (setDrawOptions == NULL) { + /* just draw the entire face array */ + glDrawArrays(GL_TRIANGLES, 0, (tottri) * 3); + } + else { + /* we need to check if the next material changes */ + int next_actualFace = dm->drawObject->triangle_to_mface[0]; + int prev_mat_nr = -1; - if (tottri == 0) { - /* avoid buffer problems in following code */ - } - if (setDrawOptions == NULL) { - /* just draw the entire face array */ - glDrawArrays(GL_TRIANGLES, 0, (tottri) * 3); - } - else { - /* we need to check if the next material changes */ - int next_actualFace = dm->drawObject->triangle_to_mface[0]; + for (i = 0; i < tottri; i++) { + //int actualFace = dm->drawObject->triangle_to_mface[i]; + int actualFace = next_actualFace; + MFace *mface = mf + actualFace; + /*int drawSmooth = (flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : (mface->flag & ME_SMOOTH);*/ /* UNUSED */ + DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL; + int flush = 0; - for (i = 0; i < tottri; i++) { - //int actualFace = dm->drawObject->triangle_to_mface[i]; - int actualFace = next_actualFace; - MFace *mface = mf + actualFace; - /*int drawSmooth = (flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : (mface->flag & ME_SMOOTH);*/ /* UNUSED */ - DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL; - int flush = 0; - - if (i != tottri - 1) - next_actualFace = dm->drawObject->triangle_to_mface[i + 1]; - - orig = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace) : actualFace; - - if (orig == ORIGINDEX_NONE) + if (i != tottri - 1) + next_actualFace = dm->drawObject->triangle_to_mface[i + 1]; + + orig = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, actualFace) : actualFace; + + if (mface->mat_nr != prev_mat_nr) { + if (setMaterial) draw_option = setMaterial(mface->mat_nr + 1, NULL); - else if (setDrawOptions != NULL) - draw_option = setDrawOptions(userData, orig); - - if (draw_option == DM_DRAW_OPTION_STIPPLE) { - glEnable(GL_POLYGON_STIPPLE); - glPolygonStipple(stipple_quarttone); - } - - /* Goal is to draw as long of a contiguous triangle + + prev_mat_nr = mface->mat_nr; + } + + if (setDrawOptions != NULL && (orig != ORIGINDEX_NONE)) + draw_option = setDrawOptions(userData, orig); + + if (draw_option == DM_DRAW_OPTION_STIPPLE) { + glEnable(GL_POLYGON_STIPPLE); + glPolygonStipple(stipple_quarttone); + } + + /* Goal is to draw as long of a contiguous triangle * array as possible, so draw when we hit either an * invisible triangle or at the end of the array */ - - /* flush buffer if current triangle isn't drawable or it's last triangle... */ - flush = (ELEM(draw_option, DM_DRAW_OPTION_SKIP, DM_DRAW_OPTION_STIPPLE)) || (i == tottri - 1); - - /* ... or when material setting is dissferent */ - flush |= mf[actualFace].mat_nr != mf[next_actualFace].mat_nr; - - if (!flush && compareDrawOptions) { - flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0; - } - - if (flush) { - int first = prevstart * 3; - /* Add one to the length if we're drawing at the end of the array */ - int count = (i - prevstart + (draw_option != DM_DRAW_OPTION_SKIP ? 1 : 0)) * 3; - - if (count) - glDrawArrays(GL_TRIANGLES, first, count); - - prevstart = i + 1; - - if (draw_option == DM_DRAW_OPTION_STIPPLE) - glDisable(GL_POLYGON_STIPPLE); - } + + /* flush buffer if current triangle isn't drawable or it's last triangle... */ + flush = (ELEM(draw_option, DM_DRAW_OPTION_SKIP, DM_DRAW_OPTION_STIPPLE)) || (i == tottri - 1); + + /* ... or when material setting is dissferent */ + flush |= mf[actualFace].mat_nr != mf[next_actualFace].mat_nr; + + if (!flush && compareDrawOptions) { + flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0; + } + + if (flush) { + int first = prevstart * 3; + /* Add one to the length if we're drawing at the end of the array */ + int count = (i - prevstart + (draw_option != DM_DRAW_OPTION_SKIP ? 1 : 0)) * 3; + + if (count) + glDrawArrays(GL_TRIANGLES, first, count); + + prevstart = i + 1; + + if (draw_option == DM_DRAW_OPTION_STIPPLE) + glDisable(GL_POLYGON_STIPPLE); } } - + glShadeModel(GL_FLAT); } GPU_buffer_unbind(); @@ -1150,7 +859,7 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, } static void cdDM_drawMappedFacesTex(DerivedMesh *dm, - DMSetDrawOptions setDrawOptions, + DMSetDrawOptionsMappedTex setDrawOptions, DMCompareDrawOptions compareDrawOptions, void *userData, DMDrawFlag flag) { @@ -1270,7 +979,7 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, glShadeModel(GL_SMOOTH); - if (GPU_buffer_legacy(dm) || setDrawOptions != NULL) { + if (setDrawOptions != NULL) { DEBUG_VBO("Using legacy code. cdDM_drawMappedFacesGLSL\n"); memset(&attribs, 0, sizeof(attribs)); @@ -1329,11 +1038,11 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, ln3 = &lnors[a][2]; ln4 = &lnors[a][3]; } - + cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v1, 0, ln1, smoothnormal); cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v2, 1, ln2, smoothnormal); cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v3, 2, ln3, smoothnormal); - + if (mface->v4) cddm_draw_attrib_vertex(&attribs, mvert, a, mface->v4, 3, ln4, smoothnormal); else @@ -1347,214 +1056,213 @@ static void cdDM_drawMappedFacesGLSL(DerivedMesh *dm, int numdata = 0, elementsize = 0, offset; int start = 0, numfaces = 0 /* , prevdraw = 0 */ /* UNUSED */, curface = 0; int i; - + const MFace *mf = mface; GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/ memset(&attribs, 0, sizeof(attribs)); - + GPU_vertex_setup(dm); GPU_normal_setup(dm); - - if (!GPU_buffer_legacy(dm)) { - for (i = 0; i < dm->drawObject->tot_triangle_point / 3; i++) { - - a = dm->drawObject->triangle_to_mface[i]; - - mface = mf + a; - new_matnr = mface->mat_nr + 1; - - if (new_matnr != matnr) { - numfaces = curface - start; - if (numfaces > 0) { - - if (do_draw) { - - if (numdata != 0) { - - GPU_buffer_unlock(buffer); - - GPU_interleaved_attrib_setup(buffer, datatypes, numdata); - } - - glDrawArrays(GL_TRIANGLES, start * 3, numfaces * 3); - - if (numdata != 0) { - - GPU_buffer_free(buffer); - - buffer = NULL; - } - + + for (i = 0; i < dm->drawObject->tot_triangle_point / 3; i++) { + + a = dm->drawObject->triangle_to_mface[i]; + + mface = mf + a; + new_matnr = mface->mat_nr + 1; + + if (new_matnr != matnr) { + numfaces = curface - start; + if (numfaces > 0) { + + if (do_draw) { + + if (numdata != 0) { + + GPU_buffer_unlock(buffer); + + GPU_interleaved_attrib_setup(buffer, datatypes, numdata); + } + + glDrawArrays(GL_TRIANGLES, start * 3, numfaces * 3); + + if (numdata != 0) { + + GPU_buffer_free(buffer); + + buffer = NULL; } + } - numdata = 0; - start = curface; - /* prevdraw = do_draw; */ /* UNUSED */ - do_draw = setMaterial(matnr = new_matnr, &gattribs); - if (do_draw) { - DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); - - if (attribs.totorco && attribs.orco.array) { - datatypes[numdata].index = attribs.orco.gl_index; - datatypes[numdata].size = 3; + } + numdata = 0; + start = curface; + /* prevdraw = do_draw; */ /* UNUSED */ + do_draw = setMaterial(matnr = new_matnr, &gattribs); + if (do_draw) { + DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); + + if (attribs.totorco && attribs.orco.array) { + datatypes[numdata].index = attribs.orco.gl_index; + datatypes[numdata].size = 3; + datatypes[numdata].type = GL_FLOAT; + numdata++; + } + for (b = 0; b < attribs.tottface; b++) { + if (attribs.tface[b].array) { + datatypes[numdata].index = attribs.tface[b].gl_index; + datatypes[numdata].size = 2; datatypes[numdata].type = GL_FLOAT; numdata++; } - for (b = 0; b < attribs.tottface; b++) { - if (attribs.tface[b].array) { - datatypes[numdata].index = attribs.tface[b].gl_index; - datatypes[numdata].size = 2; - datatypes[numdata].type = GL_FLOAT; - numdata++; - } - } - for (b = 0; b < attribs.totmcol; b++) { - if (attribs.mcol[b].array) { - datatypes[numdata].index = attribs.mcol[b].gl_index; - datatypes[numdata].size = 4; - datatypes[numdata].type = GL_UNSIGNED_BYTE; - numdata++; - } - } - if (attribs.tottang && attribs.tang.array) { - datatypes[numdata].index = attribs.tang.gl_index; + } + for (b = 0; b < attribs.totmcol; b++) { + if (attribs.mcol[b].array) { + datatypes[numdata].index = attribs.mcol[b].gl_index; datatypes[numdata].size = 4; - datatypes[numdata].type = GL_FLOAT; + datatypes[numdata].type = GL_UNSIGNED_BYTE; numdata++; } - if (numdata != 0) { - elementsize = GPU_attrib_element_size(datatypes, numdata); - buffer = GPU_buffer_alloc(elementsize * dm->drawObject->tot_triangle_point); - if (buffer == NULL) { - GPU_buffer_unbind(); - dm->drawObject->legacy = 1; - return; - } - varray = GPU_buffer_lock_stream(buffer); - if (varray == NULL) { - GPU_buffer_unbind(); - GPU_buffer_free(buffer); - dm->drawObject->legacy = 1; - return; - } + } + if (attribs.tottang && attribs.tang.array) { + datatypes[numdata].index = attribs.tang.gl_index; + datatypes[numdata].size = 4; + datatypes[numdata].type = GL_FLOAT; + numdata++; + } + if (numdata != 0) { + elementsize = GPU_attrib_element_size(datatypes, numdata); + buffer = GPU_buffer_alloc(elementsize * dm->drawObject->tot_triangle_point, false); + if (buffer == NULL) { + GPU_buffer_unbind(); + buffer = GPU_buffer_alloc(elementsize * dm->drawObject->tot_triangle_point, true); + return; } - else { - /* if the buffer was set, don't use it again. - * prevdraw was assumed true but didnt run so set to false - [#21036] */ - /* prevdraw = 0; */ /* UNUSED */ - buffer = NULL; + varray = GPU_buffer_lock_stream(buffer); + if (varray == NULL) { + GPU_buffer_unbind(); + GPU_buffer_free(buffer); + fprintf(stderr, "Out of memory, can't draw object\n"); + return; } } + else { + /* if the buffer was set, don't use it again. + * prevdraw was assumed true but didnt run so set to false - [#21036] */ + /* prevdraw = 0; */ /* UNUSED */ + buffer = NULL; + } } - + } + + if (do_draw && numdata != 0) { + offset = 0; + if (attribs.totorco && attribs.orco.array) { + copy_v3_v3((float *)&varray[elementsize * curface * 3], (float *)attribs.orco.array[mface->v1]); + copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize], (float *)attribs.orco.array[mface->v2]); + copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize * 2], (float *)attribs.orco.array[mface->v3]); + offset += sizeof(float) * 3; + } + for (b = 0; b < attribs.tottface; b++) { + if (attribs.tface[b].array) { + MTFace *tf = &attribs.tface[b].array[a]; + copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset], tf->uv[0]); + copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize], tf->uv[1]); + + copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize * 2], tf->uv[2]); + offset += sizeof(float) * 2; + } + } + for (b = 0; b < attribs.totmcol; b++) { + if (attribs.mcol[b].array) { + MCol *cp = &attribs.mcol[b].array[a * 4 + 0]; + GLubyte col[4]; + col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a; + copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset], (char *)col); + cp = &attribs.mcol[b].array[a * 4 + 1]; + col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a; + copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset + elementsize], (char *)col); + cp = &attribs.mcol[b].array[a * 4 + 2]; + col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a; + copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset + elementsize * 2], (char *)col); + offset += sizeof(unsigned char) * 4; + } + } + if (attribs.tottang && attribs.tang.array) { + const float *tang = attribs.tang.array[a * 4 + 0]; + copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset], tang); + tang = attribs.tang.array[a * 4 + 1]; + copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset + elementsize], tang); + tang = attribs.tang.array[a * 4 + 2]; + copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset + elementsize * 2], tang); + offset += sizeof(float) * 4; + } + (void)offset; + } + curface++; + if (mface->v4) { if (do_draw && numdata != 0) { offset = 0; if (attribs.totorco && attribs.orco.array) { - copy_v3_v3((float *)&varray[elementsize * curface * 3], (float *)attribs.orco.array[mface->v1]); - copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize], (float *)attribs.orco.array[mface->v2]); - copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize * 2], (float *)attribs.orco.array[mface->v3]); + copy_v3_v3((float *)&varray[elementsize * curface * 3], (float *)attribs.orco.array[mface->v3]); + copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize], (float *)attribs.orco.array[mface->v4]); + copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize * 2], (float *)attribs.orco.array[mface->v1]); offset += sizeof(float) * 3; } for (b = 0; b < attribs.tottface; b++) { if (attribs.tface[b].array) { MTFace *tf = &attribs.tface[b].array[a]; - copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset], tf->uv[0]); - copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize], tf->uv[1]); - - copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize * 2], tf->uv[2]); + copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset], tf->uv[2]); + copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize], tf->uv[3]); + copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize * 2], tf->uv[0]); offset += sizeof(float) * 2; } } for (b = 0; b < attribs.totmcol; b++) { if (attribs.mcol[b].array) { - MCol *cp = &attribs.mcol[b].array[a * 4 + 0]; + MCol *cp = &attribs.mcol[b].array[a * 4 + 2]; GLubyte col[4]; col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a; copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset], (char *)col); - cp = &attribs.mcol[b].array[a * 4 + 1]; + cp = &attribs.mcol[b].array[a * 4 + 3]; col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a; copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset + elementsize], (char *)col); - cp = &attribs.mcol[b].array[a * 4 + 2]; + cp = &attribs.mcol[b].array[a * 4 + 0]; col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a; copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset + elementsize * 2], (char *)col); offset += sizeof(unsigned char) * 4; } } if (attribs.tottang && attribs.tang.array) { - const float *tang = attribs.tang.array[a * 4 + 0]; + const float *tang = attribs.tang.array[a * 4 + 2]; copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset], tang); - tang = attribs.tang.array[a * 4 + 1]; + tang = attribs.tang.array[a * 4 + 3]; copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset + elementsize], tang); - tang = attribs.tang.array[a * 4 + 2]; + tang = attribs.tang.array[a * 4 + 0]; copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset + elementsize * 2], tang); offset += sizeof(float) * 4; } (void)offset; } curface++; - if (mface->v4) { - if (do_draw && numdata != 0) { - offset = 0; - if (attribs.totorco && attribs.orco.array) { - copy_v3_v3((float *)&varray[elementsize * curface * 3], (float *)attribs.orco.array[mface->v3]); - copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize], (float *)attribs.orco.array[mface->v4]); - copy_v3_v3((float *)&varray[elementsize * curface * 3 + elementsize * 2], (float *)attribs.orco.array[mface->v1]); - offset += sizeof(float) * 3; - } - for (b = 0; b < attribs.tottface; b++) { - if (attribs.tface[b].array) { - MTFace *tf = &attribs.tface[b].array[a]; - copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset], tf->uv[2]); - copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize], tf->uv[3]); - copy_v2_v2((float *)&varray[elementsize * curface * 3 + offset + elementsize * 2], tf->uv[0]); - offset += sizeof(float) * 2; - } - } - for (b = 0; b < attribs.totmcol; b++) { - if (attribs.mcol[b].array) { - MCol *cp = &attribs.mcol[b].array[a * 4 + 2]; - GLubyte col[4]; - col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a; - copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset], (char *)col); - cp = &attribs.mcol[b].array[a * 4 + 3]; - col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a; - copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset + elementsize], (char *)col); - cp = &attribs.mcol[b].array[a * 4 + 0]; - col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a; - copy_v4_v4_char((char *)&varray[elementsize * curface * 3 + offset + elementsize * 2], (char *)col); - offset += sizeof(unsigned char) * 4; - } - } - if (attribs.tottang && attribs.tang.array) { - const float *tang = attribs.tang.array[a * 4 + 2]; - copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset], tang); - tang = attribs.tang.array[a * 4 + 3]; - copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset + elementsize], tang); - tang = attribs.tang.array[a * 4 + 0]; - copy_v4_v4((float *)&varray[elementsize * curface * 3 + offset + elementsize * 2], tang); - offset += sizeof(float) * 4; - } - (void)offset; - } - curface++; - i++; - } + i++; } - numfaces = curface - start; - if (numfaces > 0) { - if (do_draw) { - if (numdata != 0) { - GPU_buffer_unlock(buffer); - GPU_interleaved_attrib_setup(buffer, datatypes, numdata); - } - glDrawArrays(GL_TRIANGLES, start * 3, (curface - start) * 3); + } + numfaces = curface - start; + if (numfaces > 0) { + if (do_draw) { + if (numdata != 0) { + GPU_buffer_unlock(buffer); + GPU_interleaved_attrib_setup(buffer, datatypes, numdata); } + glDrawArrays(GL_TRIANGLES, start * 3, (curface - start) * 3); } - GPU_buffer_unbind(); } + GPU_buffer_unbind(); + GPU_buffer_free(buffer); } - + glShadeModel(GL_FLAT); } @@ -2725,10 +2433,10 @@ static bool poly_gset_compare_fn(const void *k1, const void *k2) (pk1->totloops == pk2->totloops)) { /* Equality - note that this does not mean equality of polys */ - return 0; + return false; } else { - return 1; + return true; } } diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index aacf02555d4..3932a8ead2f 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -789,7 +789,7 @@ static void cloth_apply_vgroup ( ClothModifierData *clmd, DerivedMesh *dm ) // Kicking goal factor to simplify things...who uses that anyway? // ABS ( clmd->sim_parms->maxgoal - clmd->sim_parms->mingoal ); - verts->goal = powf(verts->goal, 4.0f); + verts->goal = pow4f(verts->goal); if ( verts->goal >= SOFTGOALSNAP ) verts->flags |= CLOTH_VERT_FLAG_PINNED; } diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index 2f600935b1e..3030ee4b4a4 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -648,7 +648,7 @@ static void cloth_bvh_objcollisions_nearcheck ( ClothModifierData * clmd, Collis { int i; - *collisions = (CollPair *) MEM_mallocN(sizeof(CollPair) * numresult * 64, "collision array" ); // * 4 since cloth_collision_static can return more than 1 collision + *collisions = (CollPair *) MEM_mallocN(sizeof(CollPair) * numresult * 4, "collision array" ); // * 4 since cloth_collision_static can return more than 1 collision *collisions_index = *collisions; for ( i = 0; i < numresult; i++ ) { diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index a63e06c7cb8..89c3e4b0cfc 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -50,7 +50,6 @@ #include "IMB_colormanagement.h" -#include "IMB_imbuf.h" #include "IMB_imbuf_types.h" /* ********************************* color curve ********************* */ diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index e4b60c12d64..8fedf37fb95 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -185,6 +185,10 @@ void BKE_constraints_clear_evalob(bConstraintOb *cob) /* calculate delta of constraints evaluation */ invert_m4_m4(imat, cob->startmat); + /* XXX This would seem to be in wrong order. However, it does not work in 'right' order - would be nice to + * understand why premul is needed here instead of usual postmul? + * In any case, we **do not get a delta** here (e.g. startmat & matrix having same location, still gives + * a 'delta' with non-null translation component :/ ).*/ mul_m4_m4m4(delta, cob->matrix, imat); /* copy matrices back to source */ @@ -1967,7 +1971,7 @@ static void pycon_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTa static void pycon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets) { #ifndef WITH_PYTHON - (void)con; (void)cob; (void)targets; /* unused */ + UNUSED_VARS(con, cob, targets); return; #else bPythonConstraint *data = con->data; @@ -2613,6 +2617,8 @@ static void stretchto_new_data(void *cdata) data->plane = 0; data->orglength = 0.0; data->bulge = 1.0; + data->bulge_max = 1.0f; + data->bulge_min = 1.0f; } static void stretchto_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata) @@ -2689,39 +2695,28 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t bulge = powf(data->orglength / dist, data->bulge); - if (data->flag & STRETCHTOCON_USE_BULGE_MAX) { - const float bulge_median = ((data->flag & STRETCHTOCON_USE_BULGE_MIN) ? - 0.5f * (data->bulge_min + data->bulge_max) : 0.0f); - const float bulge_range = data->bulge_max - bulge_median; - float x, bulge_smoothed; - - x = bulge_range != 0.0f ? (bulge - bulge_median) / bulge_range : 0.0f; - CLAMP(x, -1.0f, 1.0f); - bulge_smoothed = bulge_median + bulge_range * sinf(0.5f*M_PI * x); - - if (data->flag & STRETCHTOCON_USE_BULGE_MIN) { - CLAMP_MIN(bulge, data->bulge_min); + if (bulge > 1.0f) { + if (data->flag & STRETCHTOCON_USE_BULGE_MAX) { + float bulge_max = max_ff(data->bulge_max, 1.0f); + float hard = min_ff(bulge, bulge_max); + + float range = bulge_max - 1.0f; + float scale = (range > 0.0f) ? 1.0f / range : 0.0f; + float soft = 1.0f + range * atanf((bulge - 1.0f) * scale) / (0.5f * M_PI); + + bulge = interpf(soft, hard, data->bulge_smooth); } - CLAMP_MAX(bulge, data->bulge_max); - - bulge = interpf(bulge_smoothed, bulge, data->bulge_smooth); } - else if (data->flag & STRETCHTOCON_USE_BULGE_MIN) { - /* The quadratic formula below creates a smooth asymptote - * of the clamped bulge value. By scaling x with the inverse smooth factor - * the smoothed area becomes smaller ("less smoothing"). - * For very small smoothing factor below epsilon it is replaced - * by the clamped version to avoid floating point precision issues. - */ - const float epsilon = 0.000001f; - if (data->bulge_smooth < epsilon) { - CLAMP_MIN(bulge, data->bulge_min); - } - else { - float scale = data->bulge_smooth; - float inv_scale = 1.0f / scale; - float x = (bulge - data->bulge_min) * 0.5f * inv_scale; - bulge = scale * (x + sqrtf((x * x) + 1.0f)) + data->bulge_min; + if (bulge < 1.0f) { + if (data->flag & STRETCHTOCON_USE_BULGE_MIN) { + float bulge_min = CLAMPIS(data->bulge_max, 0.0f, 1.0f); + float hard = max_ff(bulge, bulge_min); + + float range = 1.0f - bulge_min; + float scale = (range > 0.0f) ? 1.0f / range : 0.0f; + float soft = 1.0f - range * atanf((1.0f - bulge) * scale) / (0.5f * M_PI); + + bulge = interpf(soft, hard, data->bulge_smooth); } } @@ -3466,10 +3461,16 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra } /* transform normal into requested space */ - unit_m4(mat); - BKE_constraint_mat_convertspace(cob->ob, cob->pchan, mat, CONSTRAINT_SPACE_LOCAL, scon->projAxisSpace); - invert_m4(mat); - mul_mat3_m4_v3(mat, no); + /* We cannot use BKE_constraint_mat_convertspace here, it does not take into account scaling... + * In theory we would not need it, but in this case we'd have to tweak SpaceTransform to also + * optionally ignore scaling when handling normals - simpler to directly call BKE_object_to_mat4 + * if needed! See T42447. */ + if (scon->projAxisSpace == CONSTRAINT_SPACE_WORLD) { + BKE_object_to_mat4(cob->ob, mat); + invert_m4(mat); + mul_mat3_m4_v3(mat, no); + } + /* Else, we remain in local space, nothing to do. */ if (normalize_v3(no) < FLT_EPSILON) { fail = true; @@ -4394,10 +4395,10 @@ bool BKE_constraint_remove(ListBase *list, bConstraint *con) if (con) { BKE_constraint_free_data(con); BLI_freelinkN(list, con); - return 1; + return true; } else - return 0; + return false; } /* ......... */ @@ -4661,15 +4662,15 @@ bool BKE_constraints_proxylocked_owner(Object *ob, bPoseChannel *pchan) /* On bone-level, check if bone is on proxy-protected layer */ if ((pchan->bone) && (pchan->bone->layer & arm->layer_protected)) - return 1; + return true; } else { /* FIXME: constraints on object-level are not handled well yet */ - return 1; + return true; } } - return 0; + return false; } /* -------- Target-Matrix Stuff ------- */ diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index de285f87444..8f6c9735aaf 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -37,6 +37,7 @@ #include "DNA_windowmanager_types.h" #include "DNA_object_types.h" #include "DNA_linestyle_types.h" +#include "DNA_gpencil_types.h" #include "BLI_listbase.h" #include "BLI_string.h" @@ -257,7 +258,7 @@ static void *ctx_wm_python_context_get( } } #else - (void)C, (void)member, (void)member_type; + UNUSED_VARS(C, member, member_type); #endif /* don't allow UI context access from non-main threads */ @@ -588,7 +589,7 @@ int ctx_data_list_count(const bContext *C, int (*func)(const bContext *, ListBas ListBase list; if (func(C, &list)) { - int tot = BLI_countlist(&list); + int tot = BLI_listbase_count(&list); BLI_freelistN(&list); return tot; } @@ -1090,3 +1091,34 @@ int CTX_data_visible_pose_bones(const bContext *C, ListBase *list) { return ctx_data_collection_get(C, "visible_pose_bones", list); } + +bGPdata *CTX_data_gpencil_data(const bContext *C) +{ + return ctx_data_pointer_get(C, "gpencil_data"); +} + +bGPDlayer *CTX_data_active_gpencil_layer(const bContext *C) +{ + return ctx_data_pointer_get(C, "active_gpencil_layer"); +} + +bGPDframe *CTX_data_active_gpencil_frame(const bContext *C) +{ + return ctx_data_pointer_get(C, "active_gpencil_frame"); +} + +int CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, "visible_gpencil_layers", list); +} + +int CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, "editable_gpencil_layers", list); +} + +int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list) +{ + return ctx_data_collection_get(C, "editable_gpencil_strokes", list); +} + diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index ca58035d638..937ceffc765 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -4312,7 +4312,7 @@ bool BKE_curve_center_bounds(Curve *cu, float cent[3]) } -void BKE_curve_transform_ex(Curve *cu, float mat[4][4], bool do_keys, float unit_scale) +void BKE_curve_transform_ex(Curve *cu, float mat[4][4], const bool do_keys, const float unit_scale) { Nurb *nu; BPoint *bp; @@ -4348,13 +4348,13 @@ void BKE_curve_transform_ex(Curve *cu, float mat[4][4], bool do_keys, float unit } } -void BKE_curve_transform(Curve *cu, float mat[4][4], bool do_keys) +void BKE_curve_transform(Curve *cu, float mat[4][4], const bool do_keys) { float unit_scale = mat4_to_scale(mat); BKE_curve_transform_ex(cu, mat, do_keys, unit_scale); } -void BKE_curve_translate(Curve *cu, float offset[3], bool do_keys) +void BKE_curve_translate(Curve *cu, float offset[3], const bool do_keys) { ListBase *nurb_lb = BKE_curve_nurbs_get(cu); Nurb *nu; diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index 63eb3b397b0..5e86ca596cf 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -144,6 +144,9 @@ typedef struct LayerTypeInfo { /** a function to determine file size */ size_t (*filesize)(CDataFile *cdf, const void *data, int count); + + /** a function to determine max allowed number of layers, should be NULL or return -1 if no limit */ + int (*layers_max)(void); } LayerTypeInfo; static void layerCopy_mdeformvert(const void *source, void *dest, @@ -379,6 +382,11 @@ static void layerDefault_tface(void *data, int count) tf[i] = default_tf; } +static int layerMaxNum_tface(void) +{ + return MAX_MTFACE; +} + static void layerCopy_propFloat(const void *source, void *dest, int count) { @@ -745,6 +753,11 @@ static void layerInterp_mloopcol(void **sources, const float *weights, mc->a = (int)col.a; } +static int layerMaxNum_mloopcol(void) +{ + return MAX_MCOL; +} + static void layerCopyValue_mloopuv(const void *source, void *dest) { const MLoopUV *luv1 = source; @@ -1093,12 +1106,12 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { /* 4: CD_MFACE */ {sizeof(MFace), "MFace", 1, NULL, NULL, NULL, NULL, NULL, NULL}, /* 5: CD_MTFACE */ - {sizeof(MTFace), "MTFace", 1, N_("UVMap"), layerCopy_tface, NULL, - layerInterp_tface, layerSwap_tface, layerDefault_tface}, + {sizeof(MTFace), "MTFace", 1, N_("UVMap"), layerCopy_tface, NULL, layerInterp_tface, layerSwap_tface, + layerDefault_tface, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, layerMaxNum_tface}, /* 6: CD_MCOL */ /* 4 MCol structs per face */ {sizeof(MCol) * 4, "MCol", 4, N_("Col"), NULL, NULL, layerInterp_mcol, - layerSwap_mcol, layerDefault_mcol}, + layerSwap_mcol, layerDefault_mcol, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, layerMaxNum_mloopcol}, /* 7: CD_ORIGINDEX */ {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, layerDefault_origindex}, /* 8: CD_NORMAL */ @@ -1119,15 +1132,16 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { {sizeof(float) * 3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, /* 15: CD_MTEXPOLY */ /* note, when we expose the UV Map / TexFace split to the user, change this back to face Texture */ - {sizeof(MTexPoly), "MTexPoly", 1, N_("UVMap") /* "Face Texture" */, NULL, NULL, NULL, NULL, NULL}, + {sizeof(MTexPoly), "MTexPoly", 1, N_("UVMap") /* "Face Texture" */, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, layerMaxNum_tface}, /* 16: CD_MLOOPUV */ {sizeof(MLoopUV), "MLoopUV", 1, N_("UVMap"), NULL, NULL, layerInterp_mloopuv, NULL, NULL, layerEqual_mloopuv, layerMultiply_mloopuv, layerInitMinMax_mloopuv, - layerAdd_mloopuv, layerDoMinMax_mloopuv, layerCopyValue_mloopuv}, + layerAdd_mloopuv, layerDoMinMax_mloopuv, layerCopyValue_mloopuv, NULL, NULL, NULL, layerMaxNum_tface}, /* 17: CD_MLOOPCOL */ {sizeof(MLoopCol), "MLoopCol", 1, N_("Col"), NULL, NULL, layerInterp_mloopcol, NULL, layerDefault_mloopcol, layerEqual_mloopcol, layerMultiply_mloopcol, layerInitMinMax_mloopcol, - layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol}, + layerAdd_mloopcol, layerDoMinMax_mloopcol, layerCopyValue_mloopcol, NULL, NULL, NULL, layerMaxNum_mloopcol}, /* 18: CD_TANGENT */ {sizeof(float) * 4 * 4, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, /* 19: CD_MDISPS */ @@ -1319,7 +1333,8 @@ bool CustomData_merge(const struct CustomData *source, struct CustomData *dest, /*const LayerTypeInfo *typeInfo;*/ CustomDataLayer *layer, *newlayer; void *data; - int i, type, number = 0, lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0, lastflag = 0; + int i, type, lasttype = -1, lastactive = 0, lastrender = 0, lastclone = 0, lastmask = 0, lastflag = 0; + int number = 0, maxnumber = -1; bool changed = false; for (i = 0; i < source->totlayer; ++i) { @@ -1330,6 +1345,7 @@ bool CustomData_merge(const struct CustomData *source, struct CustomData *dest, if (type != lasttype) { number = 0; + maxnumber = CustomData_layertype_layers_max(type); lastactive = layer->active; lastrender = layer->active_rnd; lastclone = layer->active_clone; @@ -1342,6 +1358,7 @@ bool CustomData_merge(const struct CustomData *source, struct CustomData *dest, if (lastflag & CD_FLAG_NOCOPY) continue; else if (!(mask & CD_TYPE_AS_MASK(type))) continue; + else if ((maxnumber != -1) && (number >= maxnumber)) continue; else if (CustomData_get_layer_named(dest, type, layer->name)) continue; switch (alloctype) { @@ -1781,7 +1798,8 @@ bool CustomData_free_layer(CustomData *data, int type, int totelem, int index) const int n = index - CustomData_get_layer_index(data, type); int i; - if (index < 0) return 0; + if (index < 0) + return false; customData_free_layer__internal(&data->layers[index], totelem); @@ -1811,14 +1829,15 @@ bool CustomData_free_layer(CustomData *data, int type, int totelem, int index) customData_update_offsets(data); - return 1; + return true; } bool CustomData_free_layer_active(CustomData *data, int type, int totelem) { int index = 0; index = CustomData_get_active_layer_index(data, type); - if (index == -1) return 0; + if (index == -1) + return false; return CustomData_free_layer(data, type, totelem, index); } @@ -1856,14 +1875,13 @@ int CustomData_number_of_layers_typemask(const CustomData *data, CustomDataMask return number; } -void *CustomData_duplicate_referenced_layer(struct CustomData *data, const int type, const int totelem) +static void *customData_duplicate_referenced_layer_index(CustomData *data, const int layer_index, const int totelem) { CustomDataLayer *layer; - int layer_index; - /* get the layer index of the first layer of type */ - layer_index = CustomData_get_active_layer_index(data, type); - if (layer_index == -1) return NULL; + if (layer_index == -1) { + return NULL; + } layer = &data->layers[layer_index]; @@ -1879,8 +1897,9 @@ void *CustomData_duplicate_referenced_layer(struct CustomData *data, const int t typeInfo->copy(layer->data, dest_data, totelem); layer->data = dest_data; } - else + else { layer->data = MEM_dupallocN(layer->data); + } layer->flag &= ~CD_FLAG_NOFREE; } @@ -1888,37 +1907,34 @@ void *CustomData_duplicate_referenced_layer(struct CustomData *data, const int t return layer->data; } -void *CustomData_duplicate_referenced_layer_named(struct CustomData *data, - const int type, const char *name, const int totelem) +void *CustomData_duplicate_referenced_layer(CustomData *data, const int type, const int totelem) { - CustomDataLayer *layer; int layer_index; - /* get the layer index of the desired layer */ - layer_index = CustomData_get_named_layer_index(data, type, name); - if (layer_index == -1) return NULL; + /* get the layer index of the first layer of type */ + layer_index = CustomData_get_active_layer_index(data, type); - layer = &data->layers[layer_index]; + return customData_duplicate_referenced_layer_index(data, layer_index, totelem); +} - if (layer->flag & CD_FLAG_NOFREE) { - /* MEM_dupallocN won't work in case of complex layers, like e.g. - * CD_MDEFORMVERT, which has pointers to allocated data... - * So in case a custom copy function is defined, use it! - */ - const LayerTypeInfo *typeInfo = layerType_getInfo(layer->type); +void *CustomData_duplicate_referenced_layer_n(CustomData *data, const int type, const int n, const int totelem) +{ + int layer_index; - if (typeInfo->copy) { - char *dest_data = MEM_mallocN(typeInfo->size * totelem, "CD duplicate ref layer"); - typeInfo->copy(layer->data, dest_data, totelem); - layer->data = dest_data; - } - else - layer->data = MEM_dupallocN(layer->data); + /* get the layer index of the desired layer */ + layer_index = CustomData_get_layer_index_n(data, type, n); - layer->flag &= ~CD_FLAG_NOFREE; - } + return customData_duplicate_referenced_layer_index(data, layer_index, totelem); +} - return layer->data; +void *CustomData_duplicate_referenced_layer_named(CustomData *data, const int type, const char *name, const int totelem) +{ + int layer_index; + + /* get the layer index of the desired layer */ + layer_index = CustomData_get_named_layer_index(data, type, name); + + return customData_duplicate_referenced_layer_index(data, layer_index, totelem); } bool CustomData_is_referenced_layer(struct CustomData *data, int type) @@ -1928,7 +1944,8 @@ bool CustomData_is_referenced_layer(struct CustomData *data, int type) /* get the layer index of the first layer of type */ layer_index = CustomData_get_active_layer_index(data, type); - if (layer_index == -1) return 0; + if (layer_index == -1) + return false; layer = &data->layers[layer_index]; @@ -2246,8 +2263,8 @@ bool CustomData_set_layer_name(const CustomData *data, int type, int n, const ch /* get the layer index of the first layer of type */ int layer_index = CustomData_get_layer_index_n(data, type, n); - if (layer_index == -1) return false; - if (!name) return false; + if ((layer_index == -1) || !name) + return false; BLI_strncpy(data->layers[layer_index].name, name, sizeof(data->layers[layer_index].name)); @@ -3039,6 +3056,24 @@ bool CustomData_layertype_is_singleton(int type) return typeInfo->defaultname == NULL; } +/** + * \return Maximum number of layers of given \a type, -1 means 'no limit'. + */ +int CustomData_layertype_layers_max(const int type) +{ + const LayerTypeInfo *typeInfo = layerType_getInfo(type); + + /* Same test as for singleton above. */ + if (typeInfo->defaultname == NULL) { + return 1; + } + else if (typeInfo->layers_max == NULL) { + return -1; + } + + return typeInfo->layers_max(); +} + static bool CustomData_is_property_layer(int type) { if ((type == CD_PROP_FLT) || (type == CD_PROP_INT) || (type == CD_PROP_STR)) diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 528ff2d7b19..d3148dbc8e9 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -441,7 +441,7 @@ int defgroup_name_index(Object *ob, const char *name) /* note, must be freed */ int *defgroup_flip_map(Object *ob, int *flip_map_len, const bool use_default) { - int defbase_tot = *flip_map_len = BLI_countlist(&ob->defbase); + int defbase_tot = *flip_map_len = BLI_listbase_count(&ob->defbase); if (defbase_tot == 0) { return NULL; @@ -480,7 +480,7 @@ int *defgroup_flip_map(Object *ob, int *flip_map_len, const bool use_default) /* note, must be freed */ int *defgroup_flip_map_single(Object *ob, int *flip_map_len, const bool use_default, int defgroup) { - int defbase_tot = *flip_map_len = BLI_countlist(&ob->defbase); + int defbase_tot = *flip_map_len = BLI_listbase_count(&ob->defbase); if (defbase_tot == 0) { return NULL; diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 44a0b93fc01..566aa6657b9 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -2357,6 +2357,15 @@ void DAG_on_visible_update(Main *bmain, const bool do_time) ob->recalc |= OB_RECALC_DATA; lib_id_recalc_tag(bmain, &ob->id); } + /* This should not be needed here, but in some cases, like after a redo, we can end up with + * a wrong final matrix (see T42472). + * Quoting Sergey, this comes from BKE_object_handle_update_ex, which is calling + * BKE_object_where_is_calc_ex when it shouldn't, but that issue is not easily fixable. + */ + else { + ob->recalc |= OB_RECALC_OB; + lib_id_recalc_tag(bmain, &ob->id); + } if (ob->proxy && (ob->proxy_group == NULL)) { ob->proxy->recalc |= OB_RECALC_DATA; lib_id_recalc_tag(bmain, &ob->id); diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 98f0025921d..80a8d373220 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -37,7 +37,6 @@ #include "MEM_guardedalloc.h" #include "DNA_curve_types.h" -#include "DNA_meshdata_types.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" #include "DNA_vfont_types.h" @@ -1271,6 +1270,7 @@ void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase, } if (!for_orco) { + BKE_nurbList_duplicate(&ob->curve_cache->deformed_nurbs, &nubase); curve_calc_modifiers_post(scene, ob, &nubase, dispbase, r_dm_final, for_render, use_render_resolution); } @@ -1729,8 +1729,10 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba } } - if (!for_orco) + if (!for_orco) { + BKE_nurbList_duplicate(&ob->curve_cache->deformed_nurbs, &nubase); curve_calc_modifiers_post(scene, ob, &nubase, dispbase, r_dm_final, for_render, use_render_resolution); + } if (cu->flag & CU_DEFORM_FILL && !ob->derivedFinal) { curve_to_filledpoly(cu, &nubase, dispbase); diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 4719013e2f8..e3fa4733e6c 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -71,10 +71,6 @@ #include "BKE_scene.h" #include "BKE_texture.h" -#include "RNA_access.h" -#include "RNA_define.h" -#include "RNA_enum_types.h" - /* for image output */ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -257,20 +253,20 @@ static int dynamicPaint_surfaceNumOfPoints(DynamicPaintSurface *surface) bool dynamicPaint_surfaceHasColorPreview(DynamicPaintSurface *surface) { if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) { - return 0; + return false; } else if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) { if (surface->type == MOD_DPAINT_SURFACE_T_DISPLACE || surface->type == MOD_DPAINT_SURFACE_T_WAVE) { - return 0; + return false; } else { - return 1; + return true; } } else { - return 1; + return true; } } @@ -325,7 +321,7 @@ bool dynamicPaint_outputLayerExists(struct DynamicPaintSurface *surface, Object else if (output == 1) name = surface->output_name2; else - return 0; + return false; if (surface->format == MOD_DPAINT_SURFACE_F_VERTEX) { if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) { @@ -336,7 +332,7 @@ bool dynamicPaint_outputLayerExists(struct DynamicPaintSurface *surface, Object return (defgroup_name_index(ob, surface->output_name) != -1); } - return 0; + return false; } static bool surface_duplicateOutputExists(void *arg, const char *name) @@ -1106,13 +1102,13 @@ bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, str canvas = pmd->canvas = MEM_callocN(sizeof(DynamicPaintCanvasSettings), "DynamicPaint Canvas"); if (!canvas) - return 0; + return false; canvas->pmd = pmd; canvas->dm = NULL; /* Create one surface */ if (!dynamicPaint_createNewSurface(canvas, scene)) - return 0; + return false; } else if (type == MOD_DYNAMICPAINT_TYPE_BRUSH) { @@ -1122,7 +1118,7 @@ bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, str brush = pmd->brush = MEM_callocN(sizeof(DynamicPaintBrushSettings), "DynamicPaint Paint"); if (!brush) - return 0; + return false; brush->pmd = pmd; brush->psys = NULL; @@ -1157,7 +1153,7 @@ bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, str brush->paint_ramp = add_colorband(false); if (!brush->paint_ramp) - return 0; + return false; ramp = brush->paint_ramp->data; /* Add default smooth-falloff ramp. */ ramp[0].r = ramp[0].g = ramp[0].b = ramp[0].a = 1.0f; @@ -1173,7 +1169,7 @@ bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, str brush->vel_ramp = add_colorband(false); if (!brush->vel_ramp) - return 0; + return false; ramp = brush->vel_ramp->data; ramp[0].r = ramp[0].g = ramp[0].b = ramp[0].a = ramp[0].pos = 0.0f; ramp[1].r = ramp[1].g = ramp[1].b = ramp[1].a = ramp[1].pos = 1.0f; @@ -1181,10 +1177,11 @@ bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, str } } } - else - return 0; + else { + return false; + } - return 1; + return true; } void dynamicPaint_Modifier_copy(struct DynamicPaintModifierData *pmd, struct DynamicPaintModifierData *tpmd) @@ -1630,12 +1627,12 @@ bool dynamicPaint_resetSurface(Scene *scene, DynamicPaintSurface *surface) if (surface->data) dynamicPaint_freeSurfaceData(surface); /* don't reallocate for image sequence types. they get handled only on bake */ - if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return 1; - if (numOfPoints < 1) return 0; + if (surface->format == MOD_DPAINT_SURFACE_F_IMAGESEQ) return true; + if (numOfPoints < 1) return false; /* allocate memory */ surface->data = MEM_callocN(sizeof(PaintSurfaceData), "PaintSurfaceData"); - if (!surface->data) return 0; + if (!surface->data) return false; /* allocate data depending on surface type and format */ surface->data->total_points = numOfPoints; @@ -1646,7 +1643,7 @@ bool dynamicPaint_resetSurface(Scene *scene, DynamicPaintSurface *surface) if (surface->type == MOD_DPAINT_SURFACE_T_PAINT) dynamicPaint_setInitialColor(scene, surface); - return 1; + return true; } /* make sure allocated surface size matches current requirements */ @@ -1655,7 +1652,7 @@ static bool dynamicPaint_checkSurfaceData(Scene *scene, DynamicPaintSurface *sur if (!surface->data || ((dynamicPaint_surfaceNumOfPoints(surface) != surface->data->total_points))) { return dynamicPaint_resetSurface(scene, surface); } - return 1; + return true; } diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index ce7804d9878..559eefc834e 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -56,6 +56,7 @@ #include "MEM_guardedalloc.h" #include "GPU_extensions.h" +#include "GPU_draw.h" #include "GPU_glew.h" extern GLubyte stipple_quarttone[128]; /* glutil.c, bad level data */ @@ -607,13 +608,17 @@ static void emDM_drawMappedFaces(DerivedMesh *dm, int drawSmooth; efa = ltri[0]->f; - drawSmooth = lnors || ((flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH)); - + drawSmooth = lnors || ((flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH)); + draw_option = (!setDrawOptions ? DM_DRAW_OPTION_NORMAL : setDrawOptions(userData, BM_elem_index_get(efa))); + if (draw_option != DM_DRAW_OPTION_SKIP) { const GLenum poly_type = GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */ + + GPU_enable_material(efa->mat_nr + 1, NULL); + if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */ if (poly_prev != GL_ZERO) glEnd(); @@ -717,7 +722,7 @@ static void bmdm_get_tri_colpreview(BMLoop *ls[3], MLoopCol *lcol[3], unsigned c static void emDM_drawFacesTex_common(DerivedMesh *dm, DMSetDrawOptionsTex drawParams, - DMSetDrawOptions drawParamsMapped, + DMSetDrawOptionsMappedTex drawParamsMapped, DMCompareDrawOptions compareDrawOptions, void *userData) { @@ -785,7 +790,7 @@ static void emDM_drawFacesTex_common(DerivedMesh *dm, if (drawParams) draw_option = drawParams(&mtf, has_vcol, efa->mat_nr); else if (drawParamsMapped) - draw_option = drawParamsMapped(userData, BM_elem_index_get(efa)); + draw_option = drawParamsMapped(userData, BM_elem_index_get(efa), BM_elem_index_get(efa)); else draw_option = DM_DRAW_OPTION_NORMAL; @@ -854,7 +859,7 @@ static void emDM_drawFacesTex_common(DerivedMesh *dm, if (drawParams) draw_option = drawParams(&mtf, has_vcol, efa->mat_nr); else if (drawParamsMapped) - draw_option = drawParamsMapped(userData, BM_elem_index_get(efa)); + draw_option = drawParamsMapped(userData, BM_elem_index_get(efa), BM_elem_index_get(efa)); else draw_option = DM_DRAW_OPTION_NORMAL; @@ -916,7 +921,7 @@ static void emDM_drawFacesTex(DerivedMesh *dm, } static void emDM_drawMappedFacesTex(DerivedMesh *dm, - DMSetDrawOptions setDrawOptions, + DMSetDrawOptionsMappedTex setDrawOptions, DMCompareDrawOptions compareDrawOptions, void *userData, DMDrawFlag UNUSED(flag)) { @@ -970,7 +975,7 @@ static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const B GLubyte col[4]; if (attribs->mcol[i].em_offset != -1) { const MLoopCol *cp = BM_ELEM_CD_GET_VOID_P(loop, attribs->mcol[i].em_offset); - col[0] = cp->b; col[1] = cp->g; col[2] = cp->r; col[3] = cp->a; + copy_v4_v4_char((char *)col, &cp->r); } else { col[0] = 0; col[1] = 0; col[2] = 0; col[3] = 0; diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c index e90a0891436..64300ad6f52 100644 --- a/source/blender/blenkernel/intern/fcurve.c +++ b/source/blender/blenkernel/intern/fcurve.c @@ -309,17 +309,18 @@ int list_find_data_fcurves(ListBase *dst, ListBase *src, const char *dataPrefix, return matches; } -FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, bAction **action, bool *r_driven) +FCurve *rna_get_fcurve(PointerRNA *ptr, PropertyRNA *prop, int rnaindex, AnimData **adt, bAction **action, bool *r_driven) { - return rna_get_fcurve_context_ui(NULL, ptr, prop, rnaindex, action, r_driven); + return rna_get_fcurve_context_ui(NULL, ptr, prop, rnaindex, adt, action, r_driven); } FCurve *rna_get_fcurve_context_ui(bContext *C, PointerRNA *ptr, PropertyRNA *prop, int rnaindex, - bAction **action, bool *r_driven) + AnimData **animdata, bAction **action, bool *r_driven) { FCurve *fcu = NULL; PointerRNA tptr = *ptr; + if (animdata) *animdata = NULL; *r_driven = false; /* there must be some RNA-pointer + property combon */ @@ -350,11 +351,14 @@ FCurve *rna_get_fcurve_context_ui(bContext *C, PointerRNA *ptr, PropertyRNA *pro if (!fcu && (adt->drivers.first)) { fcu = list_find_fcurve(&adt->drivers, path, rnaindex); - if (fcu) + if (fcu) { + if (animdata) *animdata = adt; *r_driven = true; + } } if (fcu && action) { + if (animdata) *animdata = adt; *action = adt->action; break; } @@ -683,11 +687,11 @@ bool fcurve_are_keyframes_usable(FCurve *fcu) { /* F-Curve must exist */ if (fcu == NULL) - return 0; + return false; /* F-Curve must not have samples - samples are mutually exclusive of keyframes */ if (fcu->fpt) - return 0; + return false; /* if it has modifiers, none of these should "drastically" alter the curve */ if (fcu->modifiers.first) { @@ -714,7 +718,7 @@ bool fcurve_are_keyframes_usable(FCurve *fcu) FMod_Generator *data = (FMod_Generator *)fcm->data; if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) - return 0; + return false; break; } case FMODIFIER_TYPE_FN_GENERATOR: @@ -722,18 +726,18 @@ bool fcurve_are_keyframes_usable(FCurve *fcu) FMod_FunctionGenerator *data = (FMod_FunctionGenerator *)fcm->data; if ((data->flag & FCM_GENERATOR_ADDITIVE) == 0) - return 0; + return false; break; } /* always harmful - cannot allow */ default: - return 0; + return false; } } } /* keyframes are usable */ - return 1; + return true; } bool BKE_fcurve_is_protected(FCurve *fcu) @@ -2153,18 +2157,29 @@ static float fcurve_eval_keyframes(FCurve *fcu, BezTriple *bezts, float evaltime v4[0] = bezt->vec[1][0]; v4[1] = bezt->vec[1][1]; - /* adjust handles so that they don't overlap (forming a loop) */ - correct_bezpart(v1, v2, v3, v4); - - /* try to get a value for this position - if failure, try another set of points */ - b = findzero(evaltime, v1[0], v2[0], v3[0], v4[0], opl); - if (b) { - berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1); - cvalue = opl[0]; - /* break; */ + if (fabsf(v1[1] - v4[1]) < FLT_EPSILON && + fabsf(v2[1] - v3[1]) < FLT_EPSILON && + fabsf(v3[1] - v4[1]) < FLT_EPSILON) + { + /* Optimisation: If all the handles are flat/at the same values, + * the value is simply the shared value (see T40372 -> F91346) + */ + cvalue = v1[1]; } else { - if (G.debug & G_DEBUG) printf(" ERROR: findzero() failed at %f with %f %f %f %f\n", evaltime, v1[0], v2[0], v3[0], v4[0]); + /* adjust handles so that they don't overlap (forming a loop) */ + correct_bezpart(v1, v2, v3, v4); + + /* try to get a value for this position - if failure, try another set of points */ + b = findzero(evaltime, v1[0], v2[0], v3[0], v4[0], opl); + if (b) { + berekeny(v1[1], v2[1], v3[1], v4[1], opl, 1); + cvalue = opl[0]; + /* break; */ + } + else { + if (G.debug & G_DEBUG) printf(" ERROR: findzero() failed at %f with %f %f %f %f\n", evaltime, v1[0], v2[0], v3[0], v4[0]); + } } break; diff --git a/source/blender/blenkernel/intern/fmodifier.c b/source/blender/blenkernel/intern/fmodifier.c index 56b087e7eb6..af0db5e1c47 100644 --- a/source/blender/blenkernel/intern/fmodifier.c +++ b/source/blender/blenkernel/intern/fmodifier.c @@ -27,8 +27,6 @@ * \ingroup bke */ - - #include <math.h> #include <stdio.h> #include <stddef.h> @@ -1173,7 +1171,7 @@ bool remove_fmodifier(ListBase *modifiers, FModifier *fcm) /* sanity check */ if (fcm == NULL) - return 0; + return false; /* free modifier's special data (stored inside fcm->data) */ if (fcm->data) { @@ -1187,13 +1185,13 @@ bool remove_fmodifier(ListBase *modifiers, FModifier *fcm) /* remove modifier from stack */ if (modifiers) { BLI_freelinkN(modifiers, fcm); - return 1; + return true; } else { /* XXX this case can probably be removed some day, as it shouldn't happen... */ printf("remove_fmodifier() - no modifier stack given\n"); MEM_freeN(fcm); - return 0; + return false; } } @@ -1264,7 +1262,7 @@ bool list_has_suitable_fmodifier(ListBase *modifiers, int mtype, short acttype) /* sanity checks */ if (ELEM(NULL, modifiers, modifiers->first)) - return 0; + return false; /* find the first mdifier fitting these criteria */ for (fcm = modifiers->first; fcm; fcm = fcm->next) { @@ -1279,11 +1277,11 @@ bool list_has_suitable_fmodifier(ListBase *modifiers, int mtype, short acttype) /* if both are ok, we've found a hit */ if (mOk && aOk) - return 1; + return true; } /* no matches */ - return 0; + return false; } /* Evaluation API --------------------------- */ diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c index 4aa1b49ea13..cc9ad63d451 100644 --- a/source/blender/blenkernel/intern/freestyle.c +++ b/source/blender/blenkernel/intern/freestyle.c @@ -181,7 +181,7 @@ static FreestyleLineSet *alloc_lineset(void) FreestyleLineSet *BKE_freestyle_lineset_add(FreestyleConfig *config, const char *name) { - int lineset_index = BLI_countlist(&config->linesets); + int lineset_index = BLI_listbase_count(&config->linesets); FreestyleLineSet *lineset = alloc_lineset(); BLI_addtail(&config->linesets, (void *)lineset); diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c index e226e9d9797..dd2155505fb 100644 --- a/source/blender/blenkernel/intern/gpencil.c +++ b/source/blender/blenkernel/intern/gpencil.c @@ -45,6 +45,7 @@ #include "DNA_gpencil_types.h" #include "DNA_userdef_types.h" +#include "BKE_animsys.h" #include "BKE_global.h" #include "BKE_gpencil.h" #include "BKE_library.h" @@ -115,6 +116,12 @@ void BKE_gpencil_free(bGPdata *gpd) { /* free layers */ free_gpencil_layers(&gpd->layers); + + /* free animation data */ + if (gpd->adt) { + BKE_free_animdata(&gpd->id); + gpd->adt = NULL; + } } /* -------- Container Creation ---------- */ @@ -276,7 +283,7 @@ bGPDlayer *gpencil_layer_duplicate(bGPDlayer *src) } /* make a copy of a given gpencil datablock */ -bGPdata *gpencil_data_duplicate(bGPdata *src) +bGPdata *gpencil_data_duplicate(bGPdata *src, bool internal_copy) { bGPDlayer *gpl, *gpld; bGPdata *dst; @@ -286,7 +293,14 @@ bGPdata *gpencil_data_duplicate(bGPdata *src) return NULL; /* make a copy of the base-data */ - dst = MEM_dupallocN(src); + if (internal_copy) { + /* make a straight copy for undo buffers used during stroke drawing */ + dst = MEM_dupallocN(src); + } + else { + /* make a copy when others use this */ + dst = BKE_libblock_copy(&src->id); + } /* copy layers */ BLI_listbase_clear(&dst->layers); @@ -300,6 +314,31 @@ bGPdata *gpencil_data_duplicate(bGPdata *src) return dst; } +/* -------- GP-Stroke API --------- */ + +/* ensure selection status of stroke is in sync with its points */ +void gpencil_stroke_sync_selection(bGPDstroke *gps) +{ + bGPDspoint *pt; + int i; + + /* error checking */ + if (gps == NULL) + return; + + /* we'll stop when we find the first selected point, + * so initially, we must deselect + */ + gps->flag &= ~GP_STROKE_SELECT; + + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + if (pt->flag & GP_SPOINT_SELECT) { + gps->flag |= GP_STROKE_SELECT; + break; + } + } +} + /* -------- GP-Frame API ---------- */ /* delete the last stroke of the given frame */ @@ -359,7 +398,7 @@ bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, short addnew) /* do not allow any changes to layer's active frame if layer is locked from changes * or if the layer has been set to stay on the current frame */ - if (gpl->flag & (GP_LAYER_LOCKED | GP_LAYER_FRAMELOCK)) + if (gpl->flag & GP_LAYER_FRAMELOCK) return gpf; /* do not allow any changes to actframe if frame has painting tag attached to it */ if (gpf->flag & GP_FRAME_PAINT) @@ -468,16 +507,23 @@ bGPDframe *gpencil_layer_getframe(bGPDlayer *gpl, int cframe, short addnew) bool gpencil_layer_delframe(bGPDlayer *gpl, bGPDframe *gpf) { bool changed = false; - + /* error checking */ if (ELEM(NULL, gpl, gpf)) return false; - + + /* if this frame was active, make the previous frame active instead + * since it's tricky to set active frame otherwise + */ + if (gpl->actframe == gpf) + gpl->actframe = gpf->prev; + else + gpl->actframe = NULL; + /* free the frame and its data */ changed = free_gpencil_strokes(gpf); BLI_freelinkN(&gpl->frames, gpf); - gpl->actframe = NULL; - + return changed; } diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 4dbd15a3774..2b99b5f4620 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -42,10 +42,18 @@ #include "MEM_guardedalloc.h" +#include "BLI_strict_flags.h" + /* IDPropertyTemplate is a union in DNA_ID.h */ +/** + * if the new is 'IDP_ARRAY_REALLOC_LIMIT' items less, + * than #IDProperty.totallen, reallocate anyway. + */ +#define IDP_ARRAY_REALLOC_LIMIT 200 + /*local size table.*/ -static char idp_size_table[] = { +static size_t idp_size_table[] = { 1, /*strings*/ sizeof(int), sizeof(float), @@ -158,9 +166,8 @@ void IDP_ResizeIDPArray(IDProperty *prop, int newlen) BLI_assert(prop->type == IDP_IDPARRAY); /* first check if the array buffer size has room */ - /* if newlen is 200 items less then totallen, reallocate anyway */ if (newlen <= prop->totallen) { - if (newlen < prop->len && prop->totallen - newlen < 200) { + if (newlen < prop->len && prop->totallen - newlen < IDP_ARRAY_REALLOC_LIMIT) { int i; for (i = newlen; i < prop->len; i++) @@ -194,7 +201,7 @@ void IDP_ResizeIDPArray(IDProperty *prop, int newlen) */ newsize = newlen; newsize = (newsize >> 3) + (newsize < 9 ? 3 : 6) + newsize; - prop->data.pointer = MEM_recallocN(prop->data.pointer, sizeof(IDProperty) * newsize); + prop->data.pointer = MEM_recallocN(prop->data.pointer, sizeof(IDProperty) * (size_t)newsize); prop->len = newlen; prop->totallen = newsize; } @@ -235,8 +242,7 @@ void IDP_ResizeArray(IDProperty *prop, int newlen) const bool is_grow = newlen >= prop->len; /* first check if the array buffer size has room */ - /* if newlen is 200 chars less then totallen, reallocate anyway */ - if (newlen <= prop->totallen && prop->totallen - newlen < 200) { + if (newlen <= prop->totallen && prop->totallen - newlen < IDP_ARRAY_REALLOC_LIMIT) { idp_resize_group_array(prop, newlen, prop->data.pointer); prop->len = newlen; return; @@ -256,7 +262,8 @@ void IDP_ResizeArray(IDProperty *prop, int newlen) if (is_grow == false) idp_resize_group_array(prop, newlen, prop->data.pointer); - prop->data.pointer = MEM_recallocN(prop->data.pointer, idp_size_table[(int)prop->subtype] * newsize); + prop->data.pointer = MEM_recallocN( + prop->data.pointer, idp_size_table[(int)prop->subtype] * (size_t)newsize); if (is_grow == true) idp_resize_group_array(prop, newlen, prop->data.pointer); @@ -321,8 +328,8 @@ static IDProperty *IDP_CopyArray(const IDProperty *prop) * * \param st The string to assign. * \param name The property name. - * \param maxlen The size of the new string (including the \0 terminator) - * \return + * \param maxlen The size of the new string (including the \0 terminator). + * \return The new string property. */ IDProperty *IDP_NewString(const char *st, const char *name, int maxlen) { @@ -336,14 +343,14 @@ IDProperty *IDP_NewString(const char *st, const char *name, int maxlen) } else { /* include null terminator '\0' */ - int stlen = strlen(st) + 1; + int stlen = (int)strlen(st) + 1; if (maxlen > 0 && maxlen < stlen) stlen = maxlen; - prop->data.pointer = MEM_mallocN(stlen, "id property string 2"); + prop->data.pointer = MEM_mallocN((size_t)stlen, "id property string 2"); prop->len = prop->totallen = stlen; - BLI_strncpy(prop->data.pointer, st, stlen); + BLI_strncpy(prop->data.pointer, st, (size_t)stlen); } prop->type = IDP_STRING; @@ -374,18 +381,18 @@ void IDP_AssignString(IDProperty *prop, const char *st, int maxlen) int stlen; BLI_assert(prop->type == IDP_STRING); - stlen = strlen(st); + stlen = (int)strlen(st); if (maxlen > 0 && maxlen < stlen) stlen = maxlen; if (prop->subtype == IDP_STRING_SUB_BYTE) { IDP_ResizeArray(prop, stlen); - memcpy(prop->data.pointer, st, stlen); + memcpy(prop->data.pointer, st, (size_t)stlen); } else { stlen++; IDP_ResizeArray(prop, stlen); - BLI_strncpy(prop->data.pointer, st, stlen); + BLI_strncpy(prop->data.pointer, st, (size_t)stlen); } } @@ -395,7 +402,7 @@ void IDP_ConcatStringC(IDProperty *prop, const char *st) BLI_assert(prop->type == IDP_STRING); - newlen = prop->len + strlen(st); + newlen = prop->len + (int)strlen(st); /* we have to remember that prop->len includes the null byte for strings. * so there's no need to add +1 to the resize function.*/ IDP_ResizeArray(prop, newlen); @@ -571,18 +578,18 @@ void IDP_ReplaceGroupInGroup(IDProperty *dest, const IDProperty *src) * Checks if a property with the same name as prop exists, and if so replaces it. * Use this to preserve order! */ -void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop) +void IDP_ReplaceInGroup_ex(IDProperty *group, IDProperty *prop, IDProperty *prop_exist) { - IDProperty *loop; - BLI_assert(group->type == IDP_GROUP); - if ((loop = IDP_GetPropertyFromGroup(group, prop->name))) { - BLI_insertlinkafter(&group->data.group, loop, prop); + BLI_assert(prop_exist == IDP_GetPropertyFromGroup(group, prop->name)); + + if ((prop_exist = IDP_GetPropertyFromGroup(group, prop->name))) { + BLI_insertlinkafter(&group->data.group, prop_exist, prop); - BLI_remlink(&group->data.group, loop); - IDP_FreeProperty(loop); - MEM_freeN(loop); + BLI_remlink(&group->data.group, prop_exist); + IDP_FreeProperty(prop_exist); + MEM_freeN(prop_exist); } else { group->len++; @@ -590,6 +597,13 @@ void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop) } } +void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop) +{ + IDProperty *prop_exist = IDP_GetPropertyFromGroup(group, prop->name); + + IDP_ReplaceInGroup_ex(group, prop, prop_exist); +} + /** * If a property is missing in \a dest, add it. */ @@ -623,8 +637,8 @@ void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, const bool do_overw * * The sanity check just means the property is not added to the group if another property * exists with the same name; the client code using ID properties then needs to detect this - * (the function that adds new properties to groups, IDP_AddToGroup,returns 0 if a property can't - * be added to the group, and 1 if it can) and free the property. + * (the function that adds new properties to groups, IDP_AddToGroup, returns false if a property can't + * be added to the group, and true if it can) and free the property. * * Currently the code to free ID properties is designed to leave the actual struct * you pass it un-freed, this is needed for how the system works. This means @@ -639,10 +653,10 @@ bool IDP_AddToGroup(IDProperty *group, IDProperty *prop) if (IDP_GetPropertyFromGroup(group, prop->name) == NULL) { group->len++; BLI_addtail(&group->data.group, prop); - return 1; + return true; } - return 0; + return false; } /** @@ -656,10 +670,10 @@ bool IDP_InsertToGroup(IDProperty *group, IDProperty *previous, IDProperty *pnew if (IDP_GetPropertyFromGroup(group, pnew->name) == NULL) { group->len++; BLI_insertlinkafter(&group->data.group, previous, pnew); - return 1; + return true; } - return 0; + return false; } /** @@ -700,56 +714,6 @@ IDProperty *IDP_GetPropertyTypeFromGroup(IDProperty *prop, const char *name, con return (idprop && idprop->type == type) ? idprop : NULL; } -typedef struct IDPIter { - void *next; - IDProperty *parent; -} IDPIter; - -/** - * Get an iterator to iterate over the members of an id property group. - * Note that this will automatically free the iterator once iteration is complete; - * if you stop the iteration before hitting the end, make sure to call - * IDP_FreeIterBeforeEnd(). - */ -void *IDP_GetGroupIterator(IDProperty *prop) -{ - IDPIter *iter; - - BLI_assert(prop->type == IDP_GROUP); - iter = MEM_mallocN(sizeof(IDPIter), "IDPIter"); - iter->next = prop->data.group.first; - iter->parent = prop; - return (void *) iter; -} - -/** - * Returns the next item in the iteration. To use, simple for a loop like the following: - * while (IDP_GroupIterNext(iter) != NULL) { - * ... - * } - */ -IDProperty *IDP_GroupIterNext(void *vself) -{ - IDPIter *self = (IDPIter *) vself; - Link *next = (Link *) self->next; - if (self->next == NULL) { - MEM_freeN(self); - return NULL; - } - - self->next = next->next; - return (void *) next; -} - -/** - * Frees the iterator pointed to at vself, only use this if iteration is stopped early; - * when the iterator hits the end of the list it'll automatically free itself.\ - */ -void IDP_FreeIterBeforeEnd(void *vself) -{ - MEM_freeN(vself); -} - /* Ok, the way things work, Groups free the ID Property structs of their children. * This is because all ID Property freeing functions free only direct data (not the ID Property * struct itself), but for Groups the child properties *are* considered @@ -811,11 +775,11 @@ IDProperty *IDP_GetProperties(ID *id, const bool create_if_needed) bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is_strict) { if (prop1 == NULL && prop2 == NULL) - return 1; + return true; else if (prop1 == NULL || prop2 == NULL) - return is_strict ? 0 : 1; + return is_strict ? false : true; else if (prop1->type != prop2->type) - return 0; + return false; switch (prop1->type) { case IDP_INT: @@ -838,27 +802,32 @@ bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is case IDP_DOUBLE: return (IDP_Double(prop1) == IDP_Double(prop2)); case IDP_STRING: - return ((prop1->len == prop2->len) && strncmp(IDP_String(prop1), IDP_String(prop2), prop1->len) == 0); + { + return (((prop1->len == prop2->len) && + strncmp(IDP_String(prop1), IDP_String(prop2), (size_t)prop1->len) == 0)); + } case IDP_ARRAY: if (prop1->len == prop2->len && prop1->subtype == prop2->subtype) { - return memcmp(IDP_Array(prop1), IDP_Array(prop2), idp_size_table[(int)prop1->subtype] * prop1->len); + return (memcmp(IDP_Array(prop1), + IDP_Array(prop2), + idp_size_table[(int)prop1->subtype] * (size_t)prop1->len) == 0); } - return 0; + return false; case IDP_GROUP: { IDProperty *link1, *link2; if (is_strict && prop1->len != prop2->len) - return 0; + return false; for (link1 = prop1->data.group.first; link1; link1 = link1->next) { link2 = IDP_GetPropertyFromGroup(prop2, link1->name); if (!IDP_EqualsProperties_ex(link1, link2, is_strict)) - return 0; + return false; } - return 1; + return true; } case IDP_IDPARRAY: { @@ -867,12 +836,12 @@ bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is int i; if (prop1->len != prop2->len) - return 0; + return false; for (i = 0; i < prop1->len; i++) if (!IDP_EqualsProperties(&array1[i], &array2[i])) - return 0; - return 1; + return false; + return true; } default: /* should never get here */ @@ -880,7 +849,7 @@ bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is break; } - return 1; + return true; } bool IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2) @@ -913,7 +882,7 @@ bool IDP_EqualsProperties(IDProperty *prop1, IDProperty *prop2) * IDP_AddToGroup or MEM_freeN the property, doing anything else might result in * a memory leak. */ -IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *name) +IDProperty *IDP_New(const char type, const IDPropertyTemplate *val, const char *name) { IDProperty *prop = NULL; @@ -940,8 +909,10 @@ IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *n { prop = MEM_callocN(sizeof(IDProperty), "IDProperty array"); prop->subtype = val->array.type; - if (val->array.len) - prop->data.pointer = MEM_callocN(idp_size_table[val->array.type] * val->array.len, "id property array"); + if (val->array.len) { + prop->data.pointer = MEM_callocN( + idp_size_table[val->array.type] * (size_t)val->array.len, "id property array"); + } prop->len = prop->totallen = val->array.len; break; } @@ -961,9 +932,9 @@ IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *n prop->len = 0; } else { - prop->data.pointer = MEM_mallocN(val->string.len, "id property string 2"); + prop->data.pointer = MEM_mallocN((size_t)val->string.len, "id property string 2"); prop->len = prop->totallen = val->string.len; - memcpy(prop->data.pointer, st, val->string.len); + memcpy(prop->data.pointer, st, (size_t)val->string.len); } prop->subtype = IDP_STRING_SUB_BYTE; } @@ -975,10 +946,10 @@ IDProperty *IDP_New(const int type, const IDPropertyTemplate *val, const char *n prop->len = 1; /*NULL string, has len of 1 to account for null byte.*/ } else { - int stlen = strlen(st) + 1; - prop->data.pointer = MEM_mallocN(stlen, "id property string 3"); + int stlen = (int)strlen(st) + 1; + prop->data.pointer = MEM_mallocN((size_t)stlen, "id property string 3"); prop->len = prop->totallen = stlen; - memcpy(prop->data.pointer, st, stlen); + memcpy(prop->data.pointer, st, (size_t)stlen); } prop->subtype = IDP_STRING_SUB_UTF8; } diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index 5c673eeef3f..36cd7e69601 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -249,7 +249,7 @@ void BKE_image_de_interlace(Image *ima, int odd) /* ***************** ALLOC & FREE, DATA MANAGING *************** */ -static void image_free_cahced_frames(Image *image) +static void image_free_cached_frames(Image *image) { if (image->cache) { IMB_moviecache_free(image->cache); @@ -263,7 +263,7 @@ static void image_free_cahced_frames(Image *image) */ void BKE_image_free_buffers(Image *ima) { - image_free_cahced_frames(ima); + image_free_cached_frames(ima); if (ima->anim) IMB_free_anim(ima->anim); ima->anim = NULL; @@ -273,7 +273,13 @@ void BKE_image_free_buffers(Image *ima) ima->rr = NULL; } - GPU_free_image(ima); + if (!G.background) { + /* Background mode doesn't use opnegl, + * so we can avoid freeing GPU images and save some + * time by skipping mutex lock. + */ + GPU_free_image(ima); + } ima->ok = IMA_OK; } @@ -661,7 +667,7 @@ Image *BKE_image_load(Main *bmain, const char *filepath) /* otherwise creates new. */ /* does not load ibuf itself */ /* pass on optional frame for #name images */ -Image *BKE_image_load_exists(const char *filepath) +Image *BKE_image_load_exists_ex(const char *filepath, bool *r_exists) { Image *ima; char str[FILE_MAX], strtest[FILE_MAX]; @@ -681,16 +687,24 @@ Image *BKE_image_load_exists(const char *filepath) ima->id.us++; /* officially should not, it doesn't link here! */ if (ima->ok == 0) ima->ok = IMA_OK; - /* RETURN! */ + if (r_exists) + *r_exists = true; return ima; } } } } + if (r_exists) + *r_exists = false; return BKE_image_load(G.main, filepath); } +Image *BKE_image_load_exists(const char *filepath) +{ + return BKE_image_load_exists_ex(filepath, NULL); +} + static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char *name, int depth, int floatbuf, short gen_type, const float color[4], ColorManagedColorspaceSettings *colorspace_settings) { @@ -2529,7 +2543,7 @@ static ImBuf *image_load_sequence_multilayer(Image *ima, ImageUser *iuser, int f * need to ensure there's no image buffers are hanging around * with dead links after freeing the render result. */ - image_free_cahced_frames(ima); + image_free_cached_frames(ima); RE_FreeRenderResult(ima->rr); ima->rr = NULL; } @@ -3393,9 +3407,9 @@ bool BKE_image_has_alpha(struct Image *image) BKE_image_release_ibuf(image, ibuf, lock); if (planes == 32) - return 1; + return true; else - return 0; + return false; } void BKE_image_get_size(Image *image, ImageUser *iuser, int *width, int *height) diff --git a/source/blender/blenkernel/intern/implicit.c b/source/blender/blenkernel/intern/implicit.c index 4cf9d52989f..fe64af184a9 100644 --- a/source/blender/blenkernel/intern/implicit.c +++ b/source/blender/blenkernel/intern/implicit.c @@ -144,14 +144,6 @@ DO_INLINE void mul_fvector_S(float to[3], float from[3], float scalar) to[1] = from[1] * scalar; to[2] = from[2] * scalar; } -/* simple cross product */ -/* STATUS: verified */ -DO_INLINE void cross_fvector(float to[3], float vectorA[3], float vectorB[3]) -{ - to[0] = vectorA[1] * vectorB[2] - vectorA[2] * vectorB[1]; - to[1] = vectorA[2] * vectorB[0] - vectorA[0] * vectorB[2]; - to[2] = vectorA[0] * vectorB[1] - vectorA[1] * vectorB[0]; -} /* simple v^T * v product ("outer product") */ /* STATUS: HAS TO BE verified (*should* work) */ DO_INLINE void mul_fvectorT_fvector(float to[3][3], float vectorA[3], float vectorB[3]) @@ -337,6 +329,7 @@ DO_INLINE void initdiag_fmatrixS(float to[3][3], float aS) to[2][2] = aS; } +#if 0 /* calculate determinant of 3x3 matrix */ DO_INLINE float det_fmatrix(float m[3][3]) { @@ -371,6 +364,7 @@ DO_INLINE void inverse_fmatrix(float to[3][3], float from[3][3]) } } +#endif /* 3x3 matrix multiplied by a scalar */ /* STATUS: verified */ @@ -398,14 +392,6 @@ DO_INLINE void mul_fmatrix_fvector(float *to, float matrix[3][3], float from[3]) to[1] = dot_v3v3(matrix[1], from); to[2] = dot_v3v3(matrix[2], from); } -/* 3x3 matrix multiplied by a 3x3 matrix */ -/* STATUS: verified */ -DO_INLINE void mul_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) -{ - mul_fvector_fmatrix(to[0], matrixA[0], matrixB); - mul_fvector_fmatrix(to[1], matrixA[1], matrixB); - mul_fvector_fmatrix(to[2], matrixA[2], matrixB); -} /* 3x3 matrix addition with 3x3 matrix */ DO_INLINE void add_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) { @@ -413,27 +399,6 @@ DO_INLINE void add_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float ma VECADD(to[1], matrixA[1], matrixB[1]); VECADD(to[2], matrixA[2], matrixB[2]); } -/* 3x3 matrix add-addition with 3x3 matrix */ -DO_INLINE void addadd_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) -{ - VECADDADD(to[0], matrixA[0], matrixB[0]); - VECADDADD(to[1], matrixA[1], matrixB[1]); - VECADDADD(to[2], matrixA[2], matrixB[2]); -} -/* 3x3 matrix sub-addition with 3x3 matrix */ -DO_INLINE void addsub_fmatrixS_fmatrixS(float to[3][3], float matrixA[3][3], float aS, float matrixB[3][3], float bS) -{ - VECADDSUBSS(to[0], matrixA[0], aS, matrixB[0], bS); - VECADDSUBSS(to[1], matrixA[1], aS, matrixB[1], bS); - VECADDSUBSS(to[2], matrixA[2], aS, matrixB[2], bS); -} -/* A -= B + C (3x3 matrix sub-addition with 3x3 matrix) */ -DO_INLINE void subadd_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) -{ - VECSUBADD(to[0], matrixA[0], matrixB[0]); - VECSUBADD(to[1], matrixA[1], matrixB[1]); - VECSUBADD(to[2], matrixA[2], matrixB[2]); -} /* A -= B*x + C*y (3x3 matrix sub-addition with 3x3 matrix) */ DO_INLINE void subadd_fmatrixS_fmatrixS(float to[3][3], float matrixA[3][3], float aS, float matrixB[3][3], float bS) { @@ -448,44 +413,9 @@ DO_INLINE void sub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float ma sub_v3_v3v3(to[1], matrixA[1], matrixB[1]); sub_v3_v3v3(to[2], matrixA[2], matrixB[2]); } -/* A += B - C (3x3 matrix add-subtraction with 3x3 matrix) */ -DO_INLINE void addsub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) -{ - VECADDSUB(to[0], matrixA[0], matrixB[0]); - VECADDSUB(to[1], matrixA[1], matrixB[1]); - VECADDSUB(to[2], matrixA[2], matrixB[2]); -} ///////////////////////////////////////////////////////////////// // special functions ///////////////////////////////////////////////////////////////// -/* a vector multiplied and added to/by a 3x3 matrix */ -DO_INLINE void muladd_fvector_fmatrix(float to[3], float from[3], float matrix[3][3]) -{ - to[0] += matrix[0][0]*from[0] + matrix[1][0]*from[1] + matrix[2][0]*from[2]; - to[1] += matrix[0][1]*from[0] + matrix[1][1]*from[1] + matrix[2][1]*from[2]; - to[2] += matrix[0][2]*from[0] + matrix[1][2]*from[1] + matrix[2][2]*from[2]; -} -/* 3x3 matrix multiplied and added to/by a 3x3 matrix and added to another 3x3 matrix */ -DO_INLINE void muladd_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) -{ - muladd_fvector_fmatrix(to[0], matrixA[0], matrixB); - muladd_fvector_fmatrix(to[1], matrixA[1], matrixB); - muladd_fvector_fmatrix(to[2], matrixA[2], matrixB); -} -/* a vector multiplied and sub'd to/by a 3x3 matrix */ -DO_INLINE void mulsub_fvector_fmatrix(float to[3], float from[3], float matrix[3][3]) -{ - to[0] -= matrix[0][0]*from[0] + matrix[1][0]*from[1] + matrix[2][0]*from[2]; - to[1] -= matrix[0][1]*from[0] + matrix[1][1]*from[1] + matrix[2][1]*from[2]; - to[2] -= matrix[0][2]*from[0] + matrix[1][2]*from[1] + matrix[2][2]*from[2]; -} -/* 3x3 matrix multiplied and sub'd to/by a 3x3 matrix and added to another 3x3 matrix */ -DO_INLINE void mulsub_fmatrix_fmatrix(float to[3][3], float matrixA[3][3], float matrixB[3][3]) -{ - mulsub_fvector_fmatrix(to[0], matrixA[0], matrixB); - mulsub_fvector_fmatrix(to[1], matrixA[1], matrixB); - mulsub_fvector_fmatrix(to[2], matrixA[2], matrixB); -} /* 3x3 matrix multiplied+added by a vector */ /* STATUS: verified */ DO_INLINE void muladd_fmatrix_fvector(float to[3], float matrix[3][3], float from[3]) @@ -494,13 +424,6 @@ DO_INLINE void muladd_fmatrix_fvector(float to[3], float matrix[3][3], float fro to[1] += dot_v3v3(matrix[1], from); to[2] += dot_v3v3(matrix[2], from); } -/* 3x3 matrix multiplied+sub'ed by a vector */ -DO_INLINE void mulsub_fmatrix_fvector(float to[3], float matrix[3][3], float from[3]) -{ - to[0] -= dot_v3v3(matrix[0], from); - to[1] -= dot_v3v3(matrix[1], from); - to[2] -= dot_v3v3(matrix[2], from); -} ///////////////////////////////////////////////////////////////// /////////////////////////// @@ -569,15 +492,6 @@ DO_INLINE void initdiag_bfmatrix(fmatrix3x3 *matrix, float m3[3][3]) } } -/* multiply big matrix with scalar*/ -DO_INLINE void mul_bfmatrix_S(fmatrix3x3 *matrix, float scalar) -{ - unsigned int i = 0; - for (i = 0; i < matrix[0].vcount+matrix[0].scount; i++) { - mul_fmatrix_S(matrix[i].m, scalar); - } -} - /* SPARSE SYMMETRIC multiply big matrix with long vector*/ /* STATUS: verified */ DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, lfVector *fLongVector) @@ -610,83 +524,6 @@ DO_INLINE void mul_bfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, lfVector } -/* SPARSE SYMMETRIC multiply big matrix with long vector (for diagonal preconditioner) */ -/* STATUS: verified */ -DO_INLINE void mul_prevfmatrix_lfvector( float (*to)[3], fmatrix3x3 *from, lfVector *fLongVector) -{ - unsigned int i = 0; - - for (i = 0; i < from[0].vcount; i++) { - mul_fmatrix_fvector(to[from[i].r], from[i].m, fLongVector[from[i].c]); - } -} - -/* SPARSE SYMMETRIC add big matrix with big matrix: A = B + C*/ -DO_INLINE void add_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix) -{ - unsigned int i = 0; - - /* process diagonal elements */ - for (i = 0; i < matrix[0].vcount+matrix[0].scount; i++) { - add_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m); - } - -} -/* SPARSE SYMMETRIC add big matrix with big matrix: A += B + C */ -DO_INLINE void addadd_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix) -{ - unsigned int i = 0; - - /* process diagonal elements */ - for (i = 0; i < matrix[0].vcount+matrix[0].scount; i++) { - addadd_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m); - } - -} -/* SPARSE SYMMETRIC subadd big matrix with big matrix: A -= B + C */ -DO_INLINE void subadd_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix) -{ - unsigned int i = 0; - - /* process diagonal elements */ - for (i = 0; i < matrix[0].vcount+matrix[0].scount; i++) { - subadd_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m); - } - -} -/* A = B - C (SPARSE SYMMETRIC sub big matrix with big matrix) */ -DO_INLINE void sub_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix) -{ - unsigned int i = 0; - - /* process diagonal elements */ - for (i = 0; i < matrix[0].vcount+matrix[0].scount; i++) { - sub_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m); - } - -} -/* SPARSE SYMMETRIC sub big matrix with big matrix S (special constraint matrix with limited entries) */ -DO_INLINE void sub_bfmatrix_Smatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix) -{ - unsigned int i = 0; - - /* process diagonal elements */ - for (i = 0; i < matrix[0].vcount; i++) { - sub_fmatrix_fmatrix(to[matrix[i].c].m, from[matrix[i].c].m, matrix[i].m); - } - -} -/* A += B - C (SPARSE SYMMETRIC addsub big matrix with big matrix) */ -DO_INLINE void addsub_bfmatrix_bfmatrix( fmatrix3x3 *to, fmatrix3x3 *from, fmatrix3x3 *matrix) -{ - unsigned int i = 0; - - /* process diagonal elements */ - for (i = 0; i < matrix[0].vcount+matrix[0].scount; i++) { - addsub_fmatrix_fmatrix(to[i].m, from[i].m, matrix[i].m); - } - -} /* SPARSE SYMMETRIC sub big matrix with big matrix*/ /* A -= B * float + C * float --> for big matrix */ /* VERIFIED */ @@ -849,14 +686,18 @@ int implicit_free(ClothModifierData *clmd) DO_INLINE float fb(float length, float L) { float x = length / L; - return (-11.541f * powf(x, 4) + 34.193f * powf(x, 3) - 39.083f * powf(x, 2) + 23.116f * x - 9.713f); + float xx = x * x; + float xxx = xx * x; + float xxxx = xxx * x; + return (-11.541f * xxxx + 34.193f * xxx - 39.083f * xx + 23.116f * x - 9.713f); } DO_INLINE float fbderiv(float length, float L) { float x = length/L; - - return (-46.164f * powf(x, 3) + 102.579f * powf(x, 2) - 78.166f * x + 23.116f); + float xx = x * x; + float xxx = xx * x; + return (-46.164f * xxx + 102.579f * xx - 78.166f * x + 23.116f); } DO_INLINE float fbstar(float length, float L, float kb, float cb) @@ -958,6 +799,7 @@ static int cg_filtered(lfVector *ldV, fmatrix3x3 *lA, lfVector *lB, lfVector *z return conjgrad_loopcount<conjgrad_looplimit; // true means we reached desired accuracy in given time - ie stable } +#if 0 // block diagonalizer DO_INLINE void BuildPPinv(fmatrix3x3 *lA, fmatrix3x3 *P, fmatrix3x3 *Pinv) { @@ -972,7 +814,6 @@ DO_INLINE void BuildPPinv(fmatrix3x3 *lA, fmatrix3x3 *P, fmatrix3x3 *Pinv) } } -#if 0 /* // version 1.3 static int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector *z, fmatrix3x3 *S, fmatrix3x3 *P, fmatrix3x3 *Pinv) @@ -1146,30 +987,6 @@ static int cg_filtered_pre(lfVector *dv, fmatrix3x3 *lA, lfVector *lB, lfVector } #endif -// outer product is NOT cross product!!! -DO_INLINE void dfdx_spring_type1(float to[3][3], float extent[3], float length, float L, float dot, float k) -{ - // dir is unit length direction, rest is spring's restlength, k is spring constant. - // return (outerprod(dir, dir)*k + (I - outerprod(dir, dir))*(k - ((k*L)/length))); - float temp[3][3]; - float temp1 = k * (1.0f - (L / length)); - - mul_fvectorT_fvectorS(temp, extent, extent, 1.0f / dot); - sub_fmatrix_fmatrix(to, I, temp); - mul_fmatrix_S(to, temp1); - - mul_fvectorT_fvectorS(temp, extent, extent, k/ dot); - add_fmatrix_fmatrix(to, to, temp); - - /* - mul_fvectorT_fvector(temp, dir, dir); - sub_fmatrix_fmatrix(to, I, temp); - mul_fmatrix_S(to, k* (1.0f-(L/length))); - mul_fmatrix_S(temp, k); - add_fmatrix_fmatrix(to, temp, to); - */ -} - DO_INLINE void dfdx_spring_type2(float to[3][3], float dir[3], float length, float L, float k, float cb) { // return outerprod(dir, dir)*fbstar_jacobi(length, L, k, cb); @@ -1195,17 +1012,6 @@ DO_INLINE void dfdx_spring(float to[3][3], float dir[3], float length, float L, mul_fmatrix_S(to, -k); } -// unused atm -DO_INLINE void dfdx_damp(float to[3][3], float dir[3], float length, const float vel[3], float rest, float damping) -{ - // inner spring damping vel is the relative velocity of the endpoints. - // return (I-outerprod(dir, dir)) * (-damping * -(dot(dir, vel)/Max(length, rest))); - mul_fvectorT_fvector(to, dir, dir); - sub_fmatrix_fmatrix(to, I, to); - mul_fmatrix_S(to, (-damping * -(dot_v3v3(dir, vel)/MAX2(length, rest)))); - -} - DO_INLINE void cloth_calc_spring_force(ClothModifierData *clmd, ClothSpring *s, lfVector *UNUSED(lF), lfVector *X, lfVector *V, fmatrix3x3 *UNUSED(dFdV), fmatrix3x3 *UNUSED(dFdX), float time) { Cloth *cloth = clmd->clothObject; diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c index 51cf26063c7..34877c7559c 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -1523,7 +1523,7 @@ static void ipo_to_animdata(ID *id, Ipo *ipo, char actname[], char constname[], if (G.debug & G_DEBUG) { printf("ipo to animdata - ID:%s, IPO:%s, actname:%s constname:%s seqname:%s curves:%d\n", id->name + 2, ipo->id.name + 2, (actname) ? actname : "<None>", (constname) ? constname : "<None>", (seq) ? (seq->name + 2) : "<None>", - BLI_countlist(&ipo->curve)); + BLI_listbase_count(&ipo->curve)); } /* Convert curves to animato system (separated into separate lists of F-Curves for animation and drivers), diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index 2dc615c19f9..3ba0c6e5ffa 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -1086,7 +1086,7 @@ static float *get_weights_array(Object *ob, char *vgroup, WeightsArrayCache *cac if (cache) { if (cache->defgroup_weights == NULL) { - int num_defgroup = BLI_countlist(&ob->defbase); + int num_defgroup = BLI_listbase_count(&ob->defbase); cache->defgroup_weights = MEM_callocN(sizeof(*cache->defgroup_weights) * num_defgroup, "cached defgroup weights"); @@ -1518,7 +1518,7 @@ KeyBlock *BKE_keyblock_add(Key *key, const char *name) BLI_addtail(&key->block, kb); kb->type = KEY_CARDINAL; - tot = BLI_countlist(&key->block); + tot = BLI_listbase_count(&key->block); if (name) { BLI_strncpy(kb->name, name, sizeof(kb->name)); } @@ -1669,31 +1669,43 @@ char *BKE_keyblock_curval_rnapath_get(Key *key, KeyBlock *kb) /* conversion functions */ /************************* Lattice ************************/ -void BKE_key_convert_from_lattice(Lattice *lt, KeyBlock *kb) +void BKE_keyblock_update_from_lattice(Lattice *lt, KeyBlock *kb) { BPoint *bp; - float *fp; + float (*fp)[3]; int a, tot; + BLI_assert(kb->totelem == lt->pntsu * lt->pntsv * lt->pntsw); + + tot = kb->totelem; + if (tot == 0) return; + + bp = lt->def; + fp = kb->data; + for (a = 0; a < kb->totelem; a++, fp++, bp++) { + copy_v3_v3(*fp, bp->vec); + } +} + +void BKE_keyblock_convert_from_lattice(Lattice *lt, KeyBlock *kb) +{ + int tot; + tot = lt->pntsu * lt->pntsv * lt->pntsw; if (tot == 0) return; - if (kb->data) MEM_freeN(kb->data); + MEM_SAFE_FREE(kb->data); - kb->data = MEM_mallocN(lt->key->elemsize * tot, "kb->data"); + kb->data = MEM_mallocN(lt->key->elemsize * tot, __func__); kb->totelem = tot; - bp = lt->def; - fp = kb->data; - for (a = 0; a < kb->totelem; a++, fp += 3, bp++) { - copy_v3_v3(fp, bp->vec); - } + BKE_keyblock_update_from_lattice(lt, kb); } -void BKE_key_convert_to_lattice(KeyBlock *kb, Lattice *lt) +void BKE_keyblock_convert_to_lattice(KeyBlock *kb, Lattice *lt) { BPoint *bp; - const float *fp; + const float (*fp)[3]; int a, tot; bp = lt->def; @@ -1702,13 +1714,13 @@ void BKE_key_convert_to_lattice(KeyBlock *kb, Lattice *lt) tot = lt->pntsu * lt->pntsv * lt->pntsw; tot = min_ii(kb->totelem, tot); - for (a = 0; a < tot; a++, fp += 3, bp++) { - copy_v3_v3(bp->vec, fp); + for (a = 0; a < tot; a++, fp++, bp++) { + copy_v3_v3(bp->vec, *fp); } } /************************* Curve ************************/ -void BKE_key_convert_from_curve(Curve *cu, KeyBlock *kb, ListBase *nurb) +void BKE_keyblock_update_from_curve(Curve *UNUSED(cu), KeyBlock *kb, ListBase *nurb) { Nurb *nu; BezTriple *bezt; @@ -1717,49 +1729,52 @@ void BKE_key_convert_from_curve(Curve *cu, KeyBlock *kb, ListBase *nurb) int a, tot; /* count */ - tot = BKE_nurbList_verts_count(nurb); - if (tot == 0) return; - - if (kb->data) MEM_freeN(kb->data); + BLI_assert(BKE_nurbList_verts_count(nurb) == kb->totelem); - kb->data = MEM_mallocN(cu->key->elemsize * tot, "kb->data"); - kb->totelem = tot; + tot = kb->totelem; + if (tot == 0) return; - nu = nurb->first; fp = kb->data; - while (nu) { - + for (nu = nurb->first; nu; nu = nu->next) { if (nu->bezt) { - bezt = nu->bezt; - a = nu->pntsu; - while (a--) { - copy_v3_v3(fp, bezt->vec[0]); - fp += 3; - copy_v3_v3(fp, bezt->vec[1]); - fp += 3; - copy_v3_v3(fp, bezt->vec[2]); - fp += 3; + for (a = nu->pntsu, bezt = nu->bezt; a; a--, bezt++) { + int i; + + for (i = 0; i < 3; i++, fp += 3) { + copy_v3_v3(fp, bezt->vec[i]); + } fp[0] = bezt->alfa; fp += 3; /* alphas */ - bezt++; } } else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - while (a--) { + + ; + for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a; a--, fp += 4, bp++) { copy_v3_v3(fp, bp->vec); fp[3] = bp->alfa; - - fp += 4; - bp++; } } - nu = nu->next; } } -void BKE_key_convert_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb) +void BKE_keyblock_convert_from_curve(Curve *cu, KeyBlock *kb, ListBase *nurb) +{ + int tot; + + /* count */ + tot = BKE_nurbList_verts_count(nurb); + if (tot == 0) return; + + MEM_SAFE_FREE(kb->data); + + kb->data = MEM_mallocN(cu->key->elemsize * tot, __func__); + kb->totelem = tot; + + BKE_keyblock_update_from_curve(cu, kb, nurb); +} + +void BKE_keyblock_convert_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb) { Nurb *nu; BezTriple *bezt; @@ -1767,74 +1782,68 @@ void BKE_key_convert_to_curve(KeyBlock *kb, Curve *UNUSED(cu), ListBase *nurb) const float *fp; int a, tot; - nu = nurb->first; - fp = kb->data; - tot = BKE_nurbList_verts_count(nurb); - tot = min_ii(kb->totelem, tot); - while (nu && tot > 0) { - + fp = kb->data; + for (nu = nurb->first; nu && tot > 0; nu = nu->next) { if (nu->bezt) { - bezt = nu->bezt; - a = nu->pntsu; - while (a-- && tot > 0) { - copy_v3_v3(bezt->vec[0], fp); - fp += 3; - copy_v3_v3(bezt->vec[1], fp); - fp += 3; - copy_v3_v3(bezt->vec[2], fp); - fp += 3; + for (a = nu->pntsu, bezt = nu->bezt; a && tot > 0; a--, tot -= 3, bezt++) { + int i; + + for (i = 0; i < 3; i++, fp += 3) { + copy_v3_v3(bezt->vec[i], fp); + } bezt->alfa = fp[0]; fp += 3; /* alphas */ - - tot -= 3; - bezt++; } } else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - while (a-- && tot > 0) { + for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a && tot; a--, tot--, fp += 4, bp++) { copy_v3_v3(bp->vec, fp); bp->alfa = fp[3]; - - fp += 4; - tot--; - bp++; } } - nu = nu->next; } } /************************* Mesh ************************/ -void BKE_key_convert_from_mesh(Mesh *me, KeyBlock *kb) +void BKE_keyblock_update_from_mesh(Mesh *me, KeyBlock *kb) { MVert *mvert; - float *fp; - int a; - - if (me->totvert == 0) return; + float (*fp)[3]; + int a, tot; - if (kb->data) MEM_freeN(kb->data); + BLI_assert(me->totvert == kb->totelem); - kb->data = MEM_mallocN(me->key->elemsize * me->totvert, "kb->data"); - kb->totelem = me->totvert; + tot = me->totvert; + if (tot == 0) return; mvert = me->mvert; fp = kb->data; - for (a = 0; a < kb->totelem; a++, fp += 3, mvert++) { - copy_v3_v3(fp, mvert->co); - + for (a = 0; a < tot; a++, fp++, mvert++) { + copy_v3_v3(*fp, mvert->co); } } -void BKE_key_convert_to_mesh(KeyBlock *kb, Mesh *me) +void BKE_keyblock_convert_from_mesh(Mesh *me, KeyBlock *kb) +{ + int tot = me->totvert; + + if (me->totvert == 0) return; + + MEM_SAFE_FREE(kb->data); + + kb->data = MEM_mallocN(me->key->elemsize * tot, __func__); + kb->totelem = tot; + + BKE_keyblock_update_from_mesh(me, kb); +} + +void BKE_keyblock_convert_to_mesh(KeyBlock *kb, Mesh *me) { MVert *mvert; - const float *fp; + const float (*fp)[3]; int a, tot; mvert = me->mvert; @@ -1842,94 +1851,76 @@ void BKE_key_convert_to_mesh(KeyBlock *kb, Mesh *me) tot = min_ii(kb->totelem, me->totvert); - for (a = 0; a < tot; a++, fp += 3, mvert++) { - copy_v3_v3(mvert->co, fp); + for (a = 0; a < tot; a++, fp++, mvert++) { + copy_v3_v3(mvert->co, *fp); } } -/************************* vert coords ************************/ -float (*BKE_key_convert_to_vertcos(Object *ob, KeyBlock *kb))[3] +/************************* raw coords ************************/ +void BKE_keyblock_update_from_vertcos(Object *ob, KeyBlock *kb, float (*vertCos)[3]) { - float (*vertCos)[3], *co; - const float *fp = kb->data; - int tot = 0, a; + float (*co)[3] = vertCos; + float *fp = kb->data; + int tot, a; - /* Count of vertex coords in array */ - if (ob->type == OB_MESH) { - Mesh *me = (Mesh *)ob->data; - tot = me->totvert; - } - else if (ob->type == OB_LATTICE) { - Lattice *lt = (Lattice *)ob->data; - tot = lt->pntsu * lt->pntsv * lt->pntsw; +#ifndef NDEBUG + if (ob->type == OB_LATTICE) { + Lattice *lt = ob->data; + BLI_assert((lt->pntsu * lt->pntsv * lt->pntsw) == kb->totelem); } else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { - Curve *cu = (Curve *)ob->data; - tot = BKE_nurbList_verts_count(&cu->nurb); + Curve *cu = ob->data; + BLI_assert(BKE_nurbList_verts_count(&cu->nurb) == kb->totelem); } + else if (ob->type == OB_MESH) { + Mesh *me = ob->data; + BLI_assert(me->totvert == kb->totelem); + } + else { + BLI_assert(0 == kb->totelem); + } +#endif - if (tot == 0) return NULL; - - vertCos = MEM_mallocN(tot * sizeof(*vertCos), "BKE_key_convert_to_vertcos vertCos"); - - /* Copy coords to array */ - co = (float *)vertCos; + tot = kb->totelem; + if (tot == 0) return; + /* Copy coords to keyblock */ if (ELEM(ob->type, OB_MESH, OB_LATTICE)) { - for (a = 0; a < tot; a++, fp += 3, co += 3) { - copy_v3_v3(co, fp); + for (a = 0; a < tot; a++, fp += 3, co++) { + copy_v3_v3(fp, *co); } } else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { Curve *cu = (Curve *)ob->data; - Nurb *nu = cu->nurb.first; + Nurb *nu; BezTriple *bezt; BPoint *bp; - while (nu) { + for (nu = cu->nurb.first; nu; nu = nu->next) { if (nu->bezt) { - int i; - bezt = nu->bezt; - a = nu->pntsu; + for (a = nu->pntsu, bezt = nu->bezt; a; a--, bezt++) { + int i; - while (a--) { - for (i = 0; i < 3; i++) { - copy_v3_v3(co, fp); - fp += 3; co += 3; + for (i = 0; i < 3; i++, fp += 3, co++) { + copy_v3_v3(fp, *co); } - fp += 3; /* skip alphas */ - - bezt++; } } else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - - while (a--) { - copy_v3_v3(co, fp); - - fp += 4; - co += 3; - - bp++; + for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a; a--, bp++, fp += 4, co++) { + copy_v3_v3(fp, *co); } } - - nu = nu->next; } } - - return vertCos; } -void BKE_key_convert_from_vertcos(Object *ob, KeyBlock *kb, float (*vertCos)[3]) +void BKE_keyblock_convert_from_vertcos(Object *ob, KeyBlock *kb, float (*vertCos)[3]) { - float *co = (float *)vertCos, *fp; - int tot = 0, a, elemsize; + int tot = 0, elemsize; - if (kb->data) MEM_freeN(kb->data); + MEM_SAFE_FREE(kb->data); /* Count of vertex coords in array */ if (ob->type == OB_MESH) { @@ -1948,110 +1939,212 @@ void BKE_key_convert_from_vertcos(Object *ob, KeyBlock *kb, float (*vertCos)[3]) tot = BKE_nurbList_verts_count(&cu->nurb); } - if (tot == 0) { - kb->data = NULL; - return; - } + if (tot == 0) return; - fp = kb->data = MEM_mallocN(tot * elemsize, "BKE_key_convert_to_vertcos vertCos"); + kb->data = MEM_mallocN(tot * elemsize, __func__); /* Copy coords to keyblock */ + BKE_keyblock_update_from_vertcos(ob, kb, vertCos); +} + +float (*BKE_keyblock_convert_to_vertcos(Object *ob, KeyBlock *kb))[3] +{ + float (*vertCos)[3], (*co)[3]; + const float *fp = kb->data; + int tot = 0, a; + + /* Count of vertex coords in array */ + if (ob->type == OB_MESH) { + Mesh *me = (Mesh *)ob->data; + tot = me->totvert; + } + else if (ob->type == OB_LATTICE) { + Lattice *lt = (Lattice *)ob->data; + tot = lt->pntsu * lt->pntsv * lt->pntsw; + } + else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { + Curve *cu = (Curve *)ob->data; + tot = BKE_nurbList_verts_count(&cu->nurb); + } + + if (tot == 0) return NULL; + + co = vertCos = MEM_mallocN(tot * sizeof(*vertCos), __func__); + /* Copy coords to array */ if (ELEM(ob->type, OB_MESH, OB_LATTICE)) { - for (a = 0; a < tot; a++, fp += 3, co += 3) { - copy_v3_v3(fp, co); + for (a = 0; a < tot; a++, fp += 3, co++) { + copy_v3_v3(*co, fp); } } else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { Curve *cu = (Curve *)ob->data; - Nurb *nu = cu->nurb.first; + Nurb *nu; BezTriple *bezt; BPoint *bp; - while (nu) { + for (nu = cu->nurb.first; nu; nu = nu->next) { if (nu->bezt) { - int i; - bezt = nu->bezt; - a = nu->pntsu; + for (a = nu->pntsu, bezt = nu->bezt; a; a--, bezt++) { + int i; - while (a--) { - for (i = 0; i < 3; i++) { - copy_v3_v3(fp, co); - fp += 3; co += 3; + for (i = 0; i < 3; i++, fp += 3, co++) { + copy_v3_v3(*co, fp); } - fp += 3; /* skip alphas */ - - bezt++; } } else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; - - while (a--) { - copy_v3_v3(fp, co); - - fp += 4; - co += 3; - - bp++; + for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a; a--, bp++, fp += 4, co++) { + copy_v3_v3(*co, fp); } } - - nu = nu->next; } } + + return vertCos; } -void BKE_key_convert_from_offset(Object *ob, KeyBlock *kb, float (*ofs)[3]) +/************************* raw coord offsets ************************/ +void BKE_keyblock_update_from_offset(Object *ob, KeyBlock *kb, float (*ofs)[3]) { int a; - float *co = (float *)ofs, *fp = kb->data; + float *fp = kb->data; if (ELEM(ob->type, OB_MESH, OB_LATTICE)) { - for (a = 0; a < kb->totelem; a++, fp += 3, co += 3) { - add_v3_v3(fp, co); + for (a = 0; a < kb->totelem; a++, fp += 3, ofs++) { + add_v3_v3(fp, *ofs); } } else if (ELEM(ob->type, OB_CURVE, OB_SURF)) { Curve *cu = (Curve *)ob->data; - Nurb *nu = cu->nurb.first; + Nurb *nu; BezTriple *bezt; BPoint *bp; - while (nu) { + for (nu = cu->nurb.first; nu; nu = nu->next) { if (nu->bezt) { - int i; - bezt = nu->bezt; - a = nu->pntsu; + for (a = nu->pntsu, bezt = nu->bezt; a; a--, bezt++) { + int i; - while (a--) { - for (i = 0; i < 3; i++) { - add_v3_v3(fp, co); - fp += 3; co += 3; + for (i = 0; i < 3; i++, fp += 3, ofs++) { + add_v3_v3(fp, *ofs); } - fp += 3; /* skip alphas */ - - bezt++; } } else { - bp = nu->bp; - a = nu->pntsu * nu->pntsv; + for (a = nu->pntsu * nu->pntsv, bp = nu->bp; a; a--, bp++, fp += 4, ofs++) { + add_v3_v3(fp, *ofs); + } + } + } + } +} - while (a--) { - add_v3_v3(fp, co); +/* ==========================================================*/ - fp += 4; - co += 3; +/** Move shape key from org_index to new_index. Safe, clamps index to valid range, updates reference keys, + * the object's active shape index, the 'frame' value in case of absolute keys, etc. + * Note indices are expected in real values (not 'fake' shapenr +1 ones). + * + * \param org_index if < 0, current object's active shape will be used as skey to move. + * \return true if something was done, else false. + */ +bool BKE_keyblock_move(Object *ob, int org_index, int new_index) +{ + Key *key = BKE_key_from_object(ob); + KeyBlock *kb; + const int act_index = ob->shapenr - 1; + const int totkey = key->totkey; + int i; + bool rev, in_range = false; - bp++; - } - } + if (org_index < 0) { + org_index = act_index; + } + + CLAMP(new_index, 0, key->totkey - 1); + CLAMP(org_index, 0, key->totkey - 1); + + if (new_index == org_index) { + return false; + } + + rev = ((new_index - org_index) < 0) ? true : false; + + /* We swap 'org' element with its previous/next neighbor (depending on direction of the move) repeatedly, + * until we reach final position. + * This allows us to only loop on the list once! */ + for (kb = (rev ? key->block.last : key->block.first), i = (rev ? totkey - 1 : 0); + kb; + kb = (rev ? kb->prev : kb->next), rev ? i-- : i++) + { + if (i == org_index) { + in_range = true; /* Start list items swapping... */ + } + else if (i == new_index) { + in_range = false; /* End list items swapping. */ + } + + if (in_range) { + KeyBlock *other_kb = rev ? kb->prev : kb->next; + + /* Swap with previous/next list item. */ + BLI_listbase_swaplinks(&key->block, kb, other_kb); + + /* Swap absolute positions. */ + SWAP(float, kb->pos, other_kb->pos); - nu = nu->next; + kb = other_kb; + } + + /* Adjust relative indices, this has to be done on the whole list! */ + if (kb->relative == org_index) { + kb->relative = new_index; + } + else if (kb->relative < org_index && kb->relative >= new_index) { + /* remove after, insert before this index */ + kb->relative++; + } + else if (kb->relative > org_index && kb->relative <= new_index) { + /* remove before, insert after this index */ + kb->relative--; + } + } + + /* Need to update active shape number if it's affected, same principle as for relative indices above. */ + if (org_index == act_index) { + ob->shapenr = new_index + 1; + } + else if (act_index < org_index && act_index >= new_index) { + ob->shapenr++; + } + else if (act_index > org_index && act_index <= new_index) { + ob->shapenr--; + } + + /* First key is always refkey, matches interface and BKE_key_sort */ + key->refkey = key->block.first; + + return true; +} + +/** + * Check if given keyblock (as index) is used as basis by others in given key. + */ +bool BKE_keyblock_is_basis(Key *key, const int index) +{ + KeyBlock *kb; + int i; + + if (key->type == KEY_RELATIVE) { + for (i = 0, kb = key->block.first; kb; i++, kb = kb->next) { + if ((i != index) && (kb->relative == index)) { + return true; + } } } + + return false; } diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c index 4a413850ec0..e738b16c8cc 100644 --- a/source/blender/blenkernel/intern/lamp.c +++ b/source/blender/blenkernel/intern/lamp.c @@ -41,7 +41,6 @@ #include "DNA_scene_types.h" #include "DNA_texture_types.h" -#include "BLI_listbase.h" #include "BLI_math.h" #include "BLI_utildefines.h" diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index 3f12e3efcc7..7732d592da6 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -575,7 +575,7 @@ static bool where_on_path_deform(Object *ob, float ctime, float vec[4], float di /* test for cyclic */ bl = ob->curve_cache->bev.first; - if (!bl->nr) return 0; + if (!bl->nr) return false; if (bl->poly > -1) cycl = 1; if (cycl == 0) { @@ -608,9 +608,9 @@ static bool where_on_path_deform(Object *ob, float ctime, float vec[4], float di /* weight - not used but could be added */ } } - return 1; + return true; } - return 0; + return false; } /* for each point, rotate & translate to curve */ @@ -634,9 +634,7 @@ static bool calc_curve_deform(Scene *scene, Object *par, float co[3], #endif if (par->curve_cache->path == NULL) { - return 0; /* happens on append, cyclic dependencies - * and empty curves - */ + return false; /* happens on append, cyclic dependencies and empty curves */ } /* options */ @@ -718,9 +716,9 @@ static bool calc_curve_deform(Scene *scene, Object *par, float co[3], if (r_quat) copy_qt_qt(r_quat, quat); - return 1; + return true; } - return 0; + return false; } void curve_deform_verts(Scene *scene, Object *cuOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3], @@ -939,10 +937,10 @@ bool object_deform_mball(Object *ob, ListBase *dispbase) (float(*)[3])dl->verts, dl->nr, NULL, 1.0f); } - return 1; + return true; } else { - return 0; + return false; } } diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index bcdaf9b7af0..5bee93349d8 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -53,8 +53,6 @@ #include "BKE_colortools.h" #include "BKE_animsys.h" -#include "RNA_access.h" - static const char *modifier_name[LS_MODIFIER_NUM] = { NULL, "Along Stroke", diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index 83ad2f1b2d2..b8c78ce912c 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -59,8 +59,6 @@ #include "BKE_movieclip.h" #include "BKE_image.h" -#include "NOD_composite.h" - static struct { ListBase splines; struct GHash *id_hash; @@ -1187,11 +1185,12 @@ void BKE_mask_point_parent_matrix_get(MaskSplinePoint *point, float ctime, float MovieTrackingPlaneTrack *plane_track = BKE_tracking_plane_track_get_named(tracking, ob, parent->sub_parent); if (plane_track) { - MovieTrackingPlaneMarker *plane_marker = BKE_tracking_plane_marker_get(plane_track, clip_framenr); + float corners[4][2]; float aspx, aspy; float frame_size[2], H[3][3], mask_from_clip_matrix[3][3], mask_to_clip_matrix[3][3]; - BKE_tracking_homography_between_two_quads(parent->parent_corners_orig, plane_marker->corners, H); + BKE_tracking_plane_marker_get_subframe_corners(plane_track, ctime, corners); + BKE_tracking_homography_between_two_quads(parent->parent_corners_orig, corners, H); unit_m3(mask_from_clip_matrix); @@ -1457,7 +1456,7 @@ void BKE_mask_layer_evaluate(MaskLayer *masklay, const float ctime, const bool d { if (found == 1) { #if 0 - printf("%s: exact %d %d (%d)\n", __func__, (int)ctime, BLI_countlist(&masklay->splines_shapes), + printf("%s: exact %d %d (%d)\n", __func__, (int)ctime, BLI_listbase_count(&masklay->splines_shapes), masklay_shape_a->frame); #endif @@ -1466,7 +1465,7 @@ void BKE_mask_layer_evaluate(MaskLayer *masklay, const float ctime, const bool d else if (found == 2) { float w = masklay_shape_b->frame - masklay_shape_a->frame; #if 0 - printf("%s: tween %d %d (%d %d)\n", __func__, (int)ctime, BLI_countlist(&masklay->splines_shapes), + printf("%s: tween %d %d (%d %d)\n", __func__, (int)ctime, BLI_listbase_count(&masklay->splines_shapes), masklay_shape_a->frame, masklay_shape_b->frame); #endif BKE_mask_layer_shape_to_mask_interp(masklay, masklay_shape_a, masklay_shape_b, @@ -1833,7 +1832,7 @@ static int mask_layer_shape_sort_cb(const void *masklay_shape_a_ptr, const void void BKE_mask_layer_shape_sort(MaskLayer *masklay) { - BLI_sortlist(&masklay->splines_shapes, mask_layer_shape_sort_cb); + BLI_listbase_sort(&masklay->splines_shapes, mask_layer_shape_sort_cb); } bool BKE_mask_layer_shape_spline_from_index(MaskLayer *masklay, int index, diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c index 3ed6148054c..5517fc36bc1 100644 --- a/source/blender/blenkernel/intern/mask_evaluate.c +++ b/source/blender/blenkernel/intern/mask_evaluate.c @@ -40,8 +40,6 @@ #include "BLI_math.h" #include "DNA_mask_types.h" -#include "DNA_node_types.h" -#include "DNA_scene_types.h" #include "BKE_curve.h" #include "BKE_mask.h" diff --git a/source/blender/blenkernel/intern/mask_rasterize.c b/source/blender/blenkernel/intern/mask_rasterize.c index 4dc8ed21463..387d093051e 100644 --- a/source/blender/blenkernel/intern/mask_rasterize.c +++ b/source/blender/blenkernel/intern/mask_rasterize.c @@ -572,7 +572,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas unsigned int masklay_index; MemArena *sf_arena; - mr_handle->layers_tot = (unsigned int)BLI_countlist(&mask->masklayers); + mr_handle->layers_tot = (unsigned int)BLI_listbase_count(&mask->masklayers); mr_handle->layers = MEM_mallocN(sizeof(MaskRasterLayer) * mr_handle->layers_tot, "MaskRasterLayer"); BLI_rctf_init_minmax(&mr_handle->bounds); @@ -608,7 +608,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas continue; } - tot_splines = (unsigned int)BLI_countlist(&masklay->splines); + tot_splines = (unsigned int)BLI_listbase_count(&masklay->splines); open_spline_ranges = MEM_callocN(sizeof(*open_spline_ranges) * tot_splines, __func__); BLI_scanfill_begin_arena(&sf_ctx, sf_arena); @@ -956,7 +956,7 @@ void BKE_maskrasterize_handle_init(MaskRasterHandle *mr_handle, struct Mask *mas &isect_remvertbase, &isect_remedgebase))) { - unsigned int sf_vert_tot_isect = (unsigned int)BLI_countlist(&sf_ctx.fillvertbase); + unsigned int sf_vert_tot_isect = (unsigned int)BLI_listbase_count(&sf_ctx.fillvertbase); unsigned int i = sf_vert_tot; face_coords = MEM_reallocN(face_coords, sizeof(float[3]) * (sf_vert_tot + sf_vert_tot_isect)); diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 29f700cf242..ad1692eadf3 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -116,7 +116,7 @@ void BKE_material_free_ex(Material *ma, bool do_id_user) MEM_freeN(ma->texpaintslot); if (ma->gpumaterial.first) - GPU_material_free(ma); + GPU_material_free(&ma->gpumaterial); } void init_material(Material *ma) @@ -1153,28 +1153,28 @@ static bool material_in_nodetree(bNodeTree *ntree, Material *mat) if (node->id) { if (GS(node->id->name) == ID_MA) { if (node->id == (ID *)mat) { - return 1; + return true; } } else if (node->type == NODE_GROUP) { if (material_in_nodetree((bNodeTree *)node->id, mat)) { - return 1; + return true; } } } } - return 0; + return false; } bool material_in_material(Material *parmat, Material *mat) { if (parmat == mat) - return 1; + return true; else if (parmat->nodetree && parmat->use_nodes) return material_in_nodetree(parmat->nodetree, mat); else - return 0; + return false; } @@ -1336,7 +1336,7 @@ void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma) short index = 0, i; bool use_nodes = BKE_scene_use_new_shading_nodes(scene); - bool is_bi = BKE_scene_uses_blender_internal(scene); + bool is_bi = BKE_scene_uses_blender_internal(scene) || BKE_scene_uses_blender_game(scene); if (!ma) return; @@ -1740,7 +1740,7 @@ void paste_matcopybuf(Material *ma) MEM_freeN(ma->nodetree); } - GPU_material_free(ma); + GPU_material_free(&ma->gpumaterial); id = (ma->id); memcpy(ma, &matcopybuf, sizeof(Material)); diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 453c6df6e3b..4c45269cb0b 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -2436,10 +2436,10 @@ bool BKE_mball_center_bounds(MetaBall *mb, float r_cent[3]) if (BKE_mball_minmax(mb, min, max)) { mid_v3_v3v3(r_cent, min, max); - return 1; + return true; } - return 0; + return false; } void BKE_mball_transform(MetaBall *mb, float mat[4][4]) diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index f3a9e894eb3..3a6c949fe9c 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -755,7 +755,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh, MDeformWeight *dw; for (j = 0, dw = dv->dw; j < dv->totweight; j++, dw++) { - /* note, greater then max defgroups is accounted for in our code, but not < 0 */ + /* note, greater than max defgroups is accounted for in our code, but not < 0 */ if (!finite(dw->weight)) { PRINT_ERR("\tVertex deform %u, group %d has weight: %f\n", i, dw->def_nr, dw->weight); if (do_fixes) { diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index a9e853c873e..54ab5a8aca7 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -47,7 +47,6 @@ #include "DNA_armature_types.h" #include "DNA_object_types.h" -#include "DNA_meshdata_types.h" #include "BLI_utildefines.h" #include "BLI_path_util.h" @@ -57,6 +56,7 @@ #include "BLF_translation.h" +#include "BKE_appdir.h" #include "BKE_key.h" #include "BKE_multires.h" #include "BKE_DerivedMesh.h" @@ -713,7 +713,7 @@ const char *modifier_path_relbase(Object *ob) else { /* last resort, better then using "" which resolves to the current * working directory */ - return BLI_temp_dir_session(); + return BKE_tempdir_session(); } } @@ -723,7 +723,7 @@ void modifier_path_init(char *path, int path_maxlen, const char *name) /* elubie: changed this to default to the same dir as the render output * to prevent saving to C:\ on Windows */ BLI_join_dirfile(path, path_maxlen, - G.relbase_valid ? "//" : BLI_temp_dir_session(), + G.relbase_valid ? "//" : BKE_tempdir_session(), name); } diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index e28adb7c0e0..0e9a7ce45cf 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -69,7 +69,6 @@ #include "BKE_image.h" /* openanim */ #include "BKE_tracking.h" -#include "IMB_colormanagement.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" #include "IMB_moviecache.h" @@ -78,8 +77,6 @@ # include "intern/openexr/openexr_multi.h" #endif -#include "NOD_composite.h" - /*********************** movieclip buffer loaders *************************/ static int sequence_guess_offset(const char *full_name, int head_len, unsigned short numlen) @@ -528,6 +525,15 @@ static bool put_imbuf_cache(MovieClip *clip, MovieClipUser *user, ImBuf *ibuf, i } } +static bool moviecache_check_free_proxy(ImBuf *UNUSED(ibuf), + void *userkey, + void *UNUSED(userdata)) +{ + MovieClipImBufCacheKey *key = (MovieClipImBufCacheKey *)userkey; + + return !(key->proxy == IMB_PROXY_NONE && key->render_flag == 0); +} + /*********************** common functions *************************/ /* only image block itself */ @@ -1170,6 +1176,15 @@ void BKE_movieclip_clear_cache(MovieClip *clip) free_buffers(clip); } +void BKE_movieclip_clear_proxy_cache(MovieClip *clip) +{ + if (clip->cache && clip->cache->moviecache) { + IMB_moviecache_cleanup(clip->cache->moviecache, + moviecache_check_free_proxy, + NULL); + } +} + void BKE_movieclip_reload(MovieClip *clip) { /* clear cache */ @@ -1261,7 +1276,7 @@ void BKE_movieclip_update_scopes(MovieClip *clip, MovieClipUser *user, MovieClip scopes->frame_width = ibuf->x; scopes->frame_height = ibuf->y; - scopes->use_track_mask = track->flag & TRACK_PREVIEW_ALPHA; + scopes->use_track_mask = (track->flag & TRACK_PREVIEW_ALPHA) != 0; } IMB_freeImBuf(ibuf); diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index df992cc9aed..0adc65bd806 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -126,7 +126,7 @@ static BLI_bitmap *multires_mdisps_upsample_hidden(BLI_bitmap *lo_hidden, if (lo_level == hi_level) return MEM_dupallocN(lo_hidden); - subd = BLI_BITMAP_NEW(hi_gridsize * hi_gridsize, "MDisps.hidden upsample"); + subd = BLI_BITMAP_NEW(SQUARE(hi_gridsize), "MDisps.hidden upsample"); factor = BKE_ccg_factor(lo_level, hi_level); offset = 1 << (hi_level - lo_level - 1); @@ -182,9 +182,7 @@ static BLI_bitmap *multires_mdisps_downsample_hidden(BLI_bitmap *old_hidden, BLI_assert(new_level <= old_level); factor = BKE_ccg_factor(new_level, old_level); - new_hidden = BLI_BITMAP_NEW(new_gridsize * new_gridsize, - "downsample hidden"); - + new_hidden = BLI_BITMAP_NEW(SQUARE(new_gridsize), "downsample hidden"); for (y = 0; y < new_gridsize; y++) { @@ -250,15 +248,15 @@ static MDisps *multires_mdisps_initialize_hidden(Mesh *me, int level) MDisps *mdisps = CustomData_add_layer(&me->ldata, CD_MDISPS, CD_CALLOC, NULL, me->totloop); int gridsize = BKE_ccg_gridsize(level); - int gridarea = gridsize * gridsize; - int i, j, k; + int gridarea = SQUARE(gridsize); + int i, j; for (i = 0; i < me->totpoly; i++) { - int hide = 0; + bool hide = false; for (j = 0; j < me->mpoly[i].totloop; j++) { if (me->mvert[me->mloop[me->mpoly[i].loopstart + j].v].flag & ME_HIDE) { - hide = 1; + hide = true; break; } } @@ -599,7 +597,7 @@ static void multires_grid_paint_mask_downsample(GridPaintMask *gpm, int level) { if (level < gpm->level) { int gridsize = BKE_ccg_gridsize(level); - float *data = MEM_callocN(sizeof(float) * gridsize * gridsize, + float *data = MEM_callocN(sizeof(float) * SQUARE(gridsize), "multires_grid_paint_mask_downsample"); int x, y; @@ -1602,7 +1600,7 @@ void multires_load_old_250(Mesh *me) int nvert = mf->v4 ? 4 : 3; int totdisp = mdisps[i].totdisp / nvert; - for (j = 0; j < mf->v4 ? 4 : 3; j++, k++) { + for (j = 0; j < nvert; j++, k++) { mdisps2[k].disps = MEM_callocN(sizeof(float) * 3 * totdisp, "multires disp in conversion"); mdisps2[k].totdisp = totdisp; mdisps2[k].level = mdisps[i].level; diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 19e45142960..b4d63f8053b 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -268,7 +268,7 @@ NlaTrack *add_nlatrack(AnimData *adt, NlaTrack *prev) /* set settings requiring the track to not be part of the stack yet */ nlt->flag = NLATRACK_SELECTED; - nlt->index = BLI_countlist(&adt->nla_tracks); + nlt->index = BLI_listbase_count(&adt->nla_tracks); /* add track to stack, and make it the active one */ if (prev) @@ -567,7 +567,7 @@ bool BKE_nlastrips_has_space(ListBase *strips, float start, float end) /* sanity checks */ if ((strips == NULL) || IS_EQF(start, end)) - return 0; + return false; if (start > end) { puts("BKE_nlastrips_has_space() error... start and end arguments swapped"); SWAP(float, start, end); @@ -579,17 +579,17 @@ bool BKE_nlastrips_has_space(ListBase *strips, float start, float end) * we've gone past the window we need to check for, so things are fine */ if (strip->start >= end) - return 1; + return true; /* if the end of the strip is greater than either of the boundaries, the range * must fall within the extents of the strip */ if ((strip->end > start) || (strip->end > end)) - return 0; + return false; } /* if we are still here, we haven't encountered any overlapping strips */ - return 1; + return true; } /* Rearrange the strips in the track so that they are always in order @@ -646,11 +646,11 @@ bool BKE_nlastrips_add_strip(ListBase *strips, NlaStrip *strip) /* sanity checks */ if (ELEM(NULL, strips, strip)) - return 0; + return false; /* check if any space to add */ if (BKE_nlastrips_has_space(strips, strip->start, strip->end) == 0) - return 0; + return false; /* find the right place to add the strip to the nominated track */ for (ns = strips->first; ns; ns = ns->next) { @@ -667,7 +667,7 @@ bool BKE_nlastrips_add_strip(ListBase *strips, NlaStrip *strip) } /* added... */ - return 1; + return true; } @@ -785,11 +785,11 @@ bool BKE_nlameta_add_strip(NlaStrip *mstrip, NlaStrip *strip) { /* sanity checks */ if (ELEM(NULL, mstrip, strip)) - return 0; + return false; /* firstly, check if the meta-strip has space for this */ if (BKE_nlastrips_has_space(&mstrip->strips, strip->start, strip->end) == 0) - return 0; + return false; /* check if this would need to be added to the ends of the meta, * and subsequently, if the neighboring strips allow us enough room @@ -803,10 +803,10 @@ bool BKE_nlameta_add_strip(NlaStrip *mstrip, NlaStrip *strip) BLI_addhead(&mstrip->strips, strip); mstrip->start = strip->start; - return 1; + return true; } else /* failed... no room before */ - return 0; + return false; } else if (strip->end > mstrip->end) { /* check if strip to the right (if it exists) starts before the @@ -817,10 +817,10 @@ bool BKE_nlameta_add_strip(NlaStrip *mstrip, NlaStrip *strip) BLI_addtail(&mstrip->strips, strip); mstrip->end = strip->end; - return 1; + return true; } else /* failed... no room after */ - return 0; + return false; } else { /* just try to add to the meta-strip (no dimension changes needed) */ @@ -988,7 +988,7 @@ bool BKE_nlatrack_has_space(NlaTrack *nlt, float start, float end) * - bounds cannot be equal (0-length is nasty) */ if ((nlt == NULL) || (nlt->flag & NLATRACK_PROTECTED) || IS_EQF(start, end)) - return 0; + return false; if (start > end) { puts("BKE_nlatrack_has_space() error... start and end arguments swapped"); @@ -1019,7 +1019,7 @@ bool BKE_nlatrack_add_strip(NlaTrack *nlt, NlaStrip *strip) { /* sanity checks */ if (ELEM(NULL, nlt, strip)) - return 0; + return false; /* try to add the strip to the track using a more generic function */ return BKE_nlastrips_add_strip(&nlt->strips, strip); @@ -1036,11 +1036,11 @@ bool BKE_nlatrack_get_bounds(NlaTrack *nlt, float bounds[2]) if (bounds) bounds[0] = bounds[1] = 0.0f; else - return 0; + return false; /* sanity checks */ if (ELEM(NULL, nlt, nlt->strips.first)) - return 0; + return false; /* lower bound is first strip's start frame */ strip = nlt->strips.first; @@ -1051,7 +1051,7 @@ bool BKE_nlatrack_get_bounds(NlaTrack *nlt, float bounds[2]) bounds[1] = strip->end; /* done */ - return 1; + return true; } /* NLA Strips -------------------------------------- */ @@ -1105,7 +1105,7 @@ bool BKE_nlastrip_within_bounds(NlaStrip *strip, float min, float max) /* sanity checks */ if ((strip == NULL) || IS_EQF(stripLen, 0.0f) || IS_EQF(boundsLen, 0.0f)) - return 0; + return false; /* only ok if at least part of the strip is within the bounding window * - first 2 cases cover when the strip length is less than the bounding area @@ -1115,17 +1115,17 @@ bool BKE_nlastrip_within_bounds(NlaStrip *strip, float min, float max) !(IN_RANGE(strip->start, min, max) || IN_RANGE(strip->end, min, max))) { - return 0; + return false; } if ((stripLen > boundsLen) && !(IN_RANGE(min, strip->start, strip->end) || IN_RANGE(max, strip->start, strip->end)) ) { - return 0; + return false; } /* should be ok! */ - return 1; + return true; } @@ -1209,11 +1209,11 @@ static bool nlastrip_is_first(AnimData *adt, NlaStrip *strip) /* sanity checks */ if (ELEM(NULL, adt, strip)) - return 0; + return false; /* check if strip has any strips before it */ if (strip->prev) - return 0; + return false; /* check other tracks to see if they have a strip that's earlier */ /* TODO: or should we check that the strip's track is also the first? */ @@ -1222,12 +1222,12 @@ static bool nlastrip_is_first(AnimData *adt, NlaStrip *strip) ns = nlt->strips.first; if (ns) { if (ns->start < strip->start) - return 0; + return false; } } /* should be first now */ - return 1; + return true; } /* Animated Strips ------------------------------------------- */ @@ -1239,16 +1239,16 @@ bool BKE_nlatrack_has_animated_strips(NlaTrack *nlt) /* sanity checks */ if (ELEM(NULL, nlt, nlt->strips.first)) - return 0; + return false; /* check each strip for F-Curves only (don't care about whether the flags are set) */ for (strip = nlt->strips.first; strip; strip = strip->next) { if (strip->fcurves.first) - return 1; + return true; } /* none found */ - return 0; + return false; } /* Check if given NLA-Tracks have any strips with own F-Curves */ @@ -1258,16 +1258,16 @@ bool BKE_nlatracks_have_animated_strips(ListBase *tracks) /* sanity checks */ if (ELEM(NULL, tracks, tracks->first)) - return 0; + return false; /* check each track, stopping on the first hit */ for (nlt = tracks->first; nlt; nlt = nlt->next) { if (BKE_nlatrack_has_animated_strips(nlt)) - return 1; + return true; } /* none found */ - return 0; + return false; } /* Validate the NLA-Strips 'control' F-Curves based on the flags set*/ @@ -1587,13 +1587,13 @@ bool BKE_nla_tweakmode_enter(AnimData *adt) /* verify that data is valid */ if (ELEM(NULL, adt, adt->nla_tracks.first)) - return 0; + return false; /* if block is already in tweakmode, just leave, but we should report * that this block is in tweakmode (as our returncode) */ if (adt->flag & ADT_NLA_EDIT_ON) - return 1; + return true; /* go over the tracks, finding the active one, and its active strip * - if we cannot find both, then there's nothing to do @@ -1642,7 +1642,7 @@ bool BKE_nla_tweakmode_enter(AnimData *adt) printf("NLA tweakmode enter - neither active requirement found\n"); printf("\tactiveTrack = %p, activeStrip = %p\n", (void *)activeTrack, (void *)activeStrip); } - return 0; + return false; } /* go over all the tracks up to the active one, tagging each strip that uses the same @@ -1677,7 +1677,7 @@ bool BKE_nla_tweakmode_enter(AnimData *adt) adt->flag |= ADT_NLA_EDIT_ON; /* done! */ - return 1; + return true; } /* Exit tweakmode for this AnimData block */ diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 7ab1479905a..b6c9e9309b8 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -2268,8 +2268,8 @@ bool ntreeHasType(const bNodeTree *ntree, int type) if (ntree) for (node = ntree->nodes.first; node; node = node->next) if (node->type == type) - return 1; - return 0; + return true; + return false; } bool ntreeHasTree(const bNodeTree *ntree, const bNodeTree *lookup) @@ -2534,8 +2534,8 @@ bool BKE_node_clipboard_validate(void) /* lists must be aligned */ - BLI_assert(BLI_countlist(&node_clipboard.nodes) == - BLI_countlist(&node_clipboard.nodes_extra_info)); + BLI_assert(BLI_listbase_count(&node_clipboard.nodes) == + BLI_listbase_count(&node_clipboard.nodes_extra_info)); for (node = node_clipboard.nodes.first, node_info = node_clipboard.nodes_extra_info.first; node; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 7a8843f3308..a0d1b25a103 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -96,6 +96,7 @@ #include "BKE_editmesh.h" #include "BKE_mball.h" #include "BKE_modifier.h" +#include "BKE_node.h" #include "BKE_object.h" #include "BKE_paint.h" #include "BKE_particle.h" @@ -107,6 +108,7 @@ #include "BKE_sequencer.h" #include "BKE_speaker.h" #include "BKE_softbody.h" +#include "BKE_subsurf.h" #include "BKE_material.h" #include "BKE_camera.h" #include "BKE_image.h" @@ -119,6 +121,8 @@ #include "BPY_extern.h" #endif +#include "CCGSubSurf.h" + #include "GPU_material.h" /* Vertex parent modifies original BMesh which is not safe for threading. @@ -185,6 +189,7 @@ void BKE_object_free_curve_cache(Object *ob) if (ob->curve_cache->path) { free_path(ob->curve_cache->path); } + BKE_nurbList_free(&ob->curve_cache->deformed_nurbs); MEM_freeN(ob->curve_cache); ob->curve_cache = NULL; } @@ -321,18 +326,7 @@ void BKE_object_free_derived_caches(Object *ob) ob->derivedDeform = NULL; } - if (ob->curve_cache) { - BKE_displist_free(&ob->curve_cache->disp); - BKE_curve_bevelList_free(&ob->curve_cache->bev); - if (ob->curve_cache->path) { - free_path(ob->curve_cache->path); - ob->curve_cache->path = NULL; - } - - /* Signal for viewport to run DAG workarounds. */ - MEM_freeN(ob->curve_cache); - ob->curve_cache = NULL; - } + BKE_object_free_curve_cache(ob); } /* do not free object itself */ @@ -442,6 +436,7 @@ void BKE_object_unlink(Object *ob) Scene *sce; SceneRenderLayer *srl; FreestyleLineSet *lineset; + bNodeTree *ntree; Curve *cu; Tex *tex; Group *group; @@ -643,17 +638,22 @@ void BKE_object_unlink(Object *ob) } /* materials */ - mat = bmain->mat.first; - while (mat) { - + for (mat = bmain->mat.first; mat; mat = mat->id.next) { + if (mat->nodetree) { + ntreeSwitchID(mat->nodetree, &ob->id, NULL); + } for (a = 0; a < MAX_MTEX; a++) { if (mat->mtex[a] && ob == mat->mtex[a]->object) { /* actually, test for lib here... to do */ mat->mtex[a]->object = NULL; } } + } - mat = mat->id.next; + /* node trees */ + for (ntree = bmain->nodetree.first; ntree; ntree = ntree->id.next) { + if (ntree->type == NTREE_SHADER) + ntreeSwitchID(ntree, &ob->id, NULL); } /* textures */ @@ -1078,14 +1078,14 @@ static int lod_cmp(const void *a, const void *b) void BKE_object_lod_sort(Object *ob) { - BLI_sortlist(&ob->lodlevels, lod_cmp); + BLI_listbase_sort(&ob->lodlevels, lod_cmp); } bool BKE_object_lod_remove(Object *ob, int level) { LodLevel *rem; - if (level < 1 || level > BLI_countlist(&ob->lodlevels) - 1) + if (level < 1 || level > BLI_listbase_count(&ob->lodlevels) - 1) return false; rem = BLI_findlink(&ob->lodlevels, level); @@ -1098,7 +1098,7 @@ bool BKE_object_lod_remove(Object *ob, int level) MEM_freeN(rem); /* If there are no user defined lods, remove the base lod as well */ - if (BLI_countlist(&ob->lodlevels) == 1) { + if (BLI_listbase_is_single(&ob->lodlevels)) { LodLevel *base = ob->lodlevels.first; BLI_remlink(&ob->lodlevels, base); MEM_freeN(base); @@ -1136,7 +1136,7 @@ static LodLevel *lod_level_select(Object *ob, const float camera_position[3]) bool BKE_object_lod_is_usable(Object *ob, Scene *scene) { - bool active = (scene) ? ob == OBACT : 0; + bool active = (scene) ? ob == OBACT : false; return (ob->mode == OB_MODE_OBJECT || !active); } @@ -1402,10 +1402,10 @@ bool BKE_object_pose_context_check(Object *ob) (ob->pose) && (ob->mode & OB_MODE_POSE)) { - return 1; + return true; } else { - return 0; + return false; } } @@ -2161,26 +2161,60 @@ static void give_parvert(Object *par, int nr, float vec[3]) int numVerts = dm->getNumVerts(dm); if (nr < numVerts) { - /* avoid dm->getVertDataArray() since it allocates arrays in the dm (not thread safe) */ - int i; + bool use_special_ss_case = false; + + if (dm->type == DM_TYPE_CCGDM) { + ModifierData *md; + VirtualModifierData virtualModifierData; + use_special_ss_case = true; + for (md = modifiers_getVirtualModifierList(par, &virtualModifierData); + md != NULL; + md = md->next) + { + ModifierTypeInfo *mti = modifierType_getInfo(md->type); + /* TODO(sergey): Check for disabled modifiers. */ + if (mti->type != eModifierTypeType_OnlyDeform && md->next != NULL) { + use_special_ss_case = false; + break; + } + } + } - if (em && dm->type == DM_TYPE_EDITBMESH) { - if (em->bm->elem_table_dirty & BM_VERT) { -#ifdef VPARENT_THREADING_HACK - BLI_mutex_lock(&vparent_lock); + if (!use_special_ss_case) { + /* avoid dm->getVertDataArray() since it allocates arrays in the dm (not thread safe) */ + if (em && dm->type == DM_TYPE_EDITBMESH) { if (em->bm->elem_table_dirty & BM_VERT) { - BM_mesh_elem_table_ensure(em->bm, BM_VERT); - } - BLI_mutex_unlock(&vparent_lock); +#ifdef VPARENT_THREADING_HACK + BLI_mutex_lock(&vparent_lock); + if (em->bm->elem_table_dirty & BM_VERT) { + BM_mesh_elem_table_ensure(em->bm, BM_VERT); + } + BLI_mutex_unlock(&vparent_lock); #else - BLI_assert(!"Not safe for threading"); - BM_mesh_elem_table_ensure(em->bm, BM_VERT); + BLI_assert(!"Not safe for threading"); + BM_mesh_elem_table_ensure(em->bm, BM_VERT); #endif + } + } + } + + if (use_special_ss_case) { + /* Special case if the last modifier is SS and no constructive modifier are in front of it. */ + CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; + CCGVert *ccg_vert = ccgSubSurf_getVert(ccgdm->ss, SET_INT_IN_POINTER(nr)); + /* In case we deleted some verts, nr may refer to inexistent one now, see T42557. */ + if (ccg_vert) { + float *co = ccgSubSurf_getVertData(ccgdm->ss, ccg_vert); + add_v3_v3(vec, co); + count++; } } + else if (CustomData_has_layer(&dm->vertData, CD_ORIGINDEX) && + !(em && dm->type == DM_TYPE_EDITBMESH)) + { + int i; - /* get the average of all verts with (original index == nr) */ - if (CustomData_has_layer(&dm->vertData, CD_ORIGINDEX)) { + /* Get the average of all verts with (original index == nr). */ for (i = 0; i < numVerts; i++) { const int *index = dm->getVertData(dm, i, CD_ORIGINDEX); if (*index == nr) { @@ -2219,8 +2253,18 @@ static void give_parvert(Object *par, int nr, float vec[3]) } } else if (ELEM(par->type, OB_CURVE, OB_SURF)) { - Curve *cu = par->data; - ListBase *nurb = BKE_curve_nurbs_get(cu); + ListBase *nurb; + + /* Unless there's some weird depsgraph failure the cache should exist. */ + BLI_assert(par->curve_cache != NULL); + + if (par->curve_cache->deformed_nurbs.first != NULL) { + nurb = &par->curve_cache->deformed_nurbs; + } + else { + Curve *cu = par->data; + nurb = BKE_curve_nurbs_get(cu); + } BKE_nurbList_index_get_co(nurb, nr, vec); } @@ -2357,7 +2401,7 @@ static bool where_is_object_parslow(Object *ob, float obmat[4][4], float slowmat /* include framerate */ fac1 = (1.0f / (1.0f + fabsf(ob->sf))); - if (fac1 >= 1.0f) return 0; + if (fac1 >= 1.0f) return false; fac2 = 1.0f - fac1; fp1 = obmat[0]; @@ -2366,7 +2410,7 @@ static bool where_is_object_parslow(Object *ob, float obmat[4][4], float slowmat fp1[0] = fac1 * fp1[0] + fac2 * fp2[0]; } - return 1; + return true; } /* note, scene is the active scene while actual_scene is the scene the object resides in */ @@ -3255,7 +3299,7 @@ int BKE_object_insert_ptcache(Object *ob) LinkData *link = NULL; int i = 0; - BLI_sortlist(&ob->pc_ids, pc_cmp); + BLI_listbase_sort(&ob->pc_ids, pc_cmp); for (link = ob->pc_ids.first, i = 0; link; link = link->next, i++) { int index = GET_INT_FROM_POINTER(link->data); @@ -3316,7 +3360,7 @@ static KeyBlock *insert_meshkey(Scene *scene, Object *ob, const char *name, cons if (newkey || from_mix == false) { /* create from mesh */ kb = BKE_keyblock_add_ctime(key, name, false); - BKE_key_convert_from_mesh(me, kb); + BKE_keyblock_convert_from_mesh(me, kb); } else { /* copy from current values */ @@ -3353,7 +3397,7 @@ static KeyBlock *insert_lattkey(Scene *scene, Object *ob, const char *name, cons kb->totelem = basekb->totelem; } else { - BKE_key_convert_from_lattice(lt, kb); + BKE_keyblock_convert_from_lattice(lt, kb); } } else { @@ -3393,7 +3437,7 @@ static KeyBlock *insert_curvekey(Scene *scene, Object *ob, const char *name, con kb->totelem = basekb->totelem; } else { - BKE_key_convert_from_curve(cu, kb, lb); + BKE_keyblock_convert_from_curve(cu, kb, lb); } } else { diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c index e53bd26b9a2..e46929dde4a 100644 --- a/source/blender/blenkernel/intern/object_deform.c +++ b/source/blender/blenkernel/intern/object_deform.c @@ -27,18 +27,457 @@ #include "MEM_guardedalloc.h" +#include "BLF_translation.h" + #include "BLI_utildefines.h" #include "BLI_ghash.h" #include "BLI_listbase.h" +#include "DNA_armature_types.h" +#include "DNA_cloth_types.h" +#include "DNA_curve_types.h" +#include "DNA_lattice_types.h" +#include "DNA_meshdata_types.h" +#include "DNA_mesh_types.h" +#include "DNA_modifier_types.h" +#include "DNA_object_types.h" +#include "DNA_object_force.h" +#include "DNA_particle_types.h" +#include "DNA_scene_types.h" + #include "BKE_action.h" +#include "BKE_deform.h" +#include "BKE_editmesh.h" #include "BKE_object_deform.h" /* own include */ #include "BKE_object.h" #include "BKE_modifier.h" -#include "DNA_armature_types.h" -#include "DNA_modifier_types.h" -#include "DNA_object_types.h" +/** \name Misc helpers + * \{ */ + +static Lattice *object_defgroup_lattice_get(ID *id) +{ + Lattice *lt = (Lattice *)id; + BLI_assert(GS(id->name) == ID_LT); + return (lt->editlatt) ? lt->editlatt->latt : lt; +} + +/** + * Update users of vgroups from this object, according to given map. + * + * Use it when you remove or reorder vgroups in the object. + * + * \param map an array mapping old indices to new indices. + */ +void BKE_object_defgroup_remap_update_users(Object *ob, int *map) +{ + ModifierData *md; + ParticleSystem *psys; + int a; + + /* these cases don't use names to refer to vertex groups, so when + * they get removed the numbers get out of sync, this corrects that */ + + if (ob->soft) { + ob->soft->vertgroup = map[ob->soft->vertgroup]; + } + + for (md = ob->modifiers.first; md; md = md->next) { + if (md->type == eModifierType_Explode) { + ExplodeModifierData *emd = (ExplodeModifierData *)md; + emd->vgroup = map[emd->vgroup]; + } + else if (md->type == eModifierType_Cloth) { + ClothModifierData *clmd = (ClothModifierData *)md; + ClothSimSettings *clsim = clmd->sim_parms; + + if (clsim) { + clsim->vgroup_mass = map[clsim->vgroup_mass]; + clsim->vgroup_bend = map[clsim->vgroup_bend]; + clsim->vgroup_struct = map[clsim->vgroup_struct]; + } + } + } + + for (psys = ob->particlesystem.first; psys; psys = psys->next) { + for (a = 0; a < PSYS_TOT_VG; a++) { + psys->vgroup[a] = map[psys->vgroup[a]]; + } + } +} +/** \} */ + + +/** \name Group creation + * \{ */ + +/** + * Add a vgroup of given name to object. *Does not* handle MDeformVert data at all! + */ +bDeformGroup *BKE_object_defgroup_add_name(Object *ob, const char *name) +{ + bDeformGroup *defgroup; + + if (!ob || !OB_TYPE_SUPPORT_VGROUP(ob->type)) + return NULL; + + defgroup = BKE_defgroup_new(ob, name); + + ob->actdef = BLI_listbase_count(&ob->defbase); + + return defgroup; +} + +/** + * Add a vgroup of default name to object. *Does not* handle MDeformVert data at all! + */ +bDeformGroup *BKE_object_defgroup_add(Object *ob) +{ + return BKE_object_defgroup_add_name(ob, DATA_("Group")); +} + +/** + * Create MDeformVert data for given ID. Work in Object mode only. + */ +MDeformVert *BKE_object_defgroup_data_create(ID *id) +{ + if (GS(id->name) == ID_ME) { + Mesh *me = (Mesh *)id; + me->dvert = CustomData_add_layer(&me->vdata, CD_MDEFORMVERT, CD_CALLOC, NULL, me->totvert); + return me->dvert; + } + else if (GS(id->name) == ID_LT) { + Lattice *lt = (Lattice *)id; + lt->dvert = MEM_callocN(sizeof(MDeformVert) * lt->pntsu * lt->pntsv * lt->pntsw, "lattice deformVert"); + return lt->dvert; + } + + return NULL; +} +/** \} */ + + +/** \name Group clearing + * \{ */ + +/** + * Remove all verts (or only selected ones) from given vgroup. Work in Object and Edit modes. + * + * \param allverts If true, remove all vertices, else only selected ones. + * \return True if any vertex was removed, false otherwise. + */ +bool BKE_object_defgroup_clear(Object *ob, bDeformGroup *dg, const bool use_selection) +{ + MDeformVert *dv; + const int def_nr = BLI_findindex(&ob->defbase, dg); + bool changed = false; + + if (ob->type == OB_MESH) { + Mesh *me = ob->data; + + if (me->edit_btmesh) { + BMEditMesh *em = me->edit_btmesh; + const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT); + + if (cd_dvert_offset != -1) { + BMVert *eve; + BMIter iter; + + BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { + dv = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); + + if (dv && dv->dw && (!use_selection || BM_elem_flag_test(eve, BM_ELEM_SELECT))) { + MDeformWeight *dw = defvert_find_index(dv, def_nr); + defvert_remove_group(dv, dw); /* dw can be NULL */ + changed = true; + } + } + } + } + else { + if (me->dvert) { + MVert *mv; + int i; + + mv = me->mvert; + dv = me->dvert; + + for (i = 0; i < me->totvert; i++, mv++, dv++) { + if (mv->flag & SELECT) { + if (dv->dw && (!use_selection || (mv->flag & SELECT))) { + MDeformWeight *dw = defvert_find_index(dv, def_nr); + defvert_remove_group(dv, dw); /* dw can be NULL */ + changed = true; + } + } + } + } + } + } + else if (ob->type == OB_LATTICE) { + Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data)); + + if (lt->dvert) { + BPoint *bp; + int i, tot = lt->pntsu * lt->pntsv * lt->pntsw; + + for (i = 0, bp = lt->def; i < tot; i++, bp++) { + if (!use_selection || (bp->f1 & SELECT)) { + MDeformWeight *dw; + + dv = <->dvert[i]; + + dw = defvert_find_index(dv, def_nr); + defvert_remove_group(dv, dw); /* dw can be NULL */ + changed = true; + } + } + } + } + + return changed; +} + +/** + * Remove all verts (or only selected ones) from all vgroups. Work in Object and Edit modes. + * + * \param allverts If true, remove all vertices, else only selected ones. + * \return True if any vertex was removed, false otherwise. + */ +bool BKE_object_defgroup_clear_all(Object *ob, const bool use_selection) +{ + bDeformGroup *dg; + bool changed = false; + + for (dg = ob->defbase.first; dg; dg = dg->next) { + if (BKE_object_defgroup_clear(ob, dg, use_selection)) { + changed = true; + } + } + + return changed; +} +/** \} */ + + +/** \name Group removal + * \{ */ + +static void object_defgroup_remove_update_users(Object *ob, const int idx) +{ + int i, defbase_tot = BLI_listbase_count(&ob->defbase) + 1; + int *map = MEM_mallocN(sizeof(int) * defbase_tot, "vgroup del"); + + map[idx] = map[0] = 0; + for (i = 1; i < idx; i++) { + map[i] = i; + } + for (i = idx + 1; i < defbase_tot; i++) { + map[i] = i - 1; + } + + BKE_object_defgroup_remap_update_users(ob, map); + MEM_freeN(map); +} + +static void object_defgroup_remove_common(Object *ob, bDeformGroup *dg, const int def_nr) +{ + object_defgroup_remove_update_users(ob, def_nr + 1); + + /* Remove the group */ + BLI_freelinkN(&ob->defbase, dg); + + /* Update the active deform index if necessary */ + if (ob->actdef > def_nr) + ob->actdef--; + + /* remove all dverts */ + if (BLI_listbase_is_empty(&ob->defbase)) { + if (ob->type == OB_MESH) { + Mesh *me = ob->data; + CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert); + me->dvert = NULL; + } + else if (ob->type == OB_LATTICE) { + Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data)); + if (lt->dvert) { + MEM_freeN(lt->dvert); + lt->dvert = NULL; + } + } + } + else if (ob->actdef < 1) { /* Keep a valid active index if we still have some vgroups. */ + ob->actdef = 1; + } +} + +static void object_defgroup_remove_object_mode(Object *ob, bDeformGroup *dg) +{ + MDeformVert *dvert_array = NULL; + int dvert_tot = 0; + const int def_nr = BLI_findindex(&ob->defbase, dg); + + BLI_assert(def_nr != -1); + + BKE_object_defgroup_array_get(ob->data, &dvert_array, &dvert_tot); + + if (dvert_array) { + int i, j; + MDeformVert *dv; + for (i = 0, dv = dvert_array; i < dvert_tot; i++, dv++) { + MDeformWeight *dw; + + dw = defvert_find_index(dv, def_nr); + defvert_remove_group(dv, dw); /* dw can be NULL */ + + /* inline, make into a function if anything else needs to do this */ + for (j = 0; j < dv->totweight; j++) { + if (dv->dw[j].def_nr > def_nr) { + dv->dw[j].def_nr--; + } + } + /* done */ + } + } + + object_defgroup_remove_common(ob, dg, def_nr); +} + +static void object_defgroup_remove_edit_mode(Object *ob, bDeformGroup *dg) +{ + int i; + const int def_nr = BLI_findindex(&ob->defbase, dg); + + BLI_assert(def_nr != -1); + + /* Make sure that no verts are using this group - if none were removed, we can skip next per-vert update. */ + if (!BKE_object_defgroup_clear(ob, dg, false)) { + /* Nothing to do. */ + } + /* Else, make sure that any groups with higher indices are adjusted accordingly */ + else if (ob->type == OB_MESH) { + Mesh *me = ob->data; + BMEditMesh *em = me->edit_btmesh; + const int cd_dvert_offset = CustomData_get_offset(&em->bm->vdata, CD_MDEFORMVERT); + + BMIter iter; + BMVert *eve; + MDeformVert *dvert; + + BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { + dvert = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset); + + if (dvert) { + for (i = 0; i < dvert->totweight; i++) { + if (dvert->dw[i].def_nr > def_nr) { + dvert->dw[i].def_nr--; + } + } + } + } + } + else if (ob->type == OB_LATTICE) { + Lattice *lt = ((Lattice *)(ob->data))->editlatt->latt; + BPoint *bp; + MDeformVert *dvert = lt->dvert; + int a, tot; + + if (dvert) { + tot = lt->pntsu * lt->pntsv * lt->pntsw; + for (a = 0, bp = lt->def; a < tot; a++, bp++, dvert++) { + for (i = 0; i < dvert->totweight; i++) { + if (dvert->dw[i].def_nr > def_nr) { + dvert->dw[i].def_nr--; + } + } + } + } + } + + object_defgroup_remove_common(ob, dg, def_nr); +} + +/** + * Remove given vgroup from object. Work in Object and Edit modes. + */ +void BKE_object_defgroup_remove(Object *ob, bDeformGroup *defgroup) +{ + if (BKE_object_is_in_editmode_vgroup(ob)) + object_defgroup_remove_edit_mode(ob, defgroup); + else + object_defgroup_remove_object_mode(ob, defgroup); +} + +/** + * Remove all vgroups from object. Work in Object and Edit modes. + */ +void BKE_object_defgroup_remove_all(Object *ob) +{ + bDeformGroup *dg = (bDeformGroup *)ob->defbase.first; + const bool edit_mode = BKE_object_is_in_editmode_vgroup(ob); + + if (dg) { + while (dg) { + bDeformGroup *next_dg = dg->next; + + if (edit_mode) + object_defgroup_remove_edit_mode(ob, dg); + else + object_defgroup_remove_object_mode(ob, dg); + + dg = next_dg; + } + } + else { /* ob->defbase is empty... */ + /* remove all dverts */ + if (ob->type == OB_MESH) { + Mesh *me = ob->data; + CustomData_free_layer_active(&me->vdata, CD_MDEFORMVERT, me->totvert); + me->dvert = NULL; + } + else if (ob->type == OB_LATTICE) { + Lattice *lt = object_defgroup_lattice_get((ID *)(ob->data)); + if (lt->dvert) { + MEM_freeN(lt->dvert); + lt->dvert = NULL; + } + } + /* Fix counters/indices */ + ob->actdef = 0; + } +} + +/** + * Get MDeformVert vgroup data from given object. Should only be used in Object mode. + * + * \return True if the id type supports weights. + */ +bool BKE_object_defgroup_array_get(ID *id, MDeformVert **dvert_arr, int *dvert_tot) +{ + if (id) { + switch (GS(id->name)) { + case ID_ME: + { + Mesh *me = (Mesh *)id; + *dvert_arr = me->dvert; + *dvert_tot = me->totvert; + return true; + } + case ID_LT: + { + Lattice *lt = object_defgroup_lattice_get(id); + *dvert_arr = lt->dvert; + *dvert_tot = lt->pntsu * lt->pntsv * lt->pntsw; + return true; + } + } + } + + *dvert_arr = NULL; + *dvert_tot = 0; + return false; +} +/** \} */ /* --- functions for getting vgroup aligned maps --- */ @@ -46,11 +485,11 @@ * gets the status of "flag" for each bDeformGroup * in ob->defbase and returns an array containing them */ -bool *BKE_objdef_lock_flags_get(Object *ob, const int defbase_tot) +bool *BKE_object_defgroup_lock_flags_get(Object *ob, const int defbase_tot) { bool is_locked = false; int i; - //int defbase_tot = BLI_countlist(&ob->defbase); + //int defbase_tot = BLI_listbase_count(&ob->defbase); bool *lock_flags = MEM_mallocN(defbase_tot * sizeof(bool), "defflags"); bDeformGroup *defgroup; @@ -66,21 +505,21 @@ bool *BKE_objdef_lock_flags_get(Object *ob, const int defbase_tot) return NULL; } -bool *BKE_objdef_validmap_get(Object *ob, const int defbase_tot) +bool *BKE_object_defgroup_validmap_get(Object *ob, const int defbase_tot) { bDeformGroup *dg; ModifierData *md; - bool *vgroup_validmap; + bool *defgroup_validmap; GHash *gh; int i, step1 = 1; - //int defbase_tot = BLI_countlist(&ob->defbase); + //int defbase_tot = BLI_listbase_count(&ob->defbase); VirtualModifierData virtualModifierData; if (BLI_listbase_is_empty(&ob->defbase)) { return NULL; } - gh = BLI_ghash_str_new_ex("BKE_objdef_validmap_get gh", defbase_tot); + gh = BLI_ghash_str_new_ex(__func__, defbase_tot); /* add all names to a hash table */ for (dg = ob->defbase.first; dg; dg = dg->next) { @@ -115,23 +554,23 @@ bool *BKE_objdef_validmap_get(Object *ob, const int defbase_tot) } } - vgroup_validmap = MEM_mallocN(sizeof(*vgroup_validmap) * defbase_tot, "wpaint valid map"); + defgroup_validmap = MEM_mallocN(sizeof(*defgroup_validmap) * defbase_tot, "wpaint valid map"); /* add all names to a hash table */ for (dg = ob->defbase.first, i = 0; dg; dg = dg->next, i++) { - vgroup_validmap[i] = (BLI_ghash_lookup(gh, dg->name) != NULL); + defgroup_validmap[i] = (BLI_ghash_lookup(gh, dg->name) != NULL); } BLI_assert(i == BLI_ghash_size(gh)); BLI_ghash_free(gh, NULL, NULL); - return vgroup_validmap; + return defgroup_validmap; } /* Returns total selected vgroups, * wpi.defbase_sel is assumed malloc'd, all values are set */ -bool *BKE_objdef_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_tot) +bool *BKE_object_defgroup_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_tot) { bool *dg_selection = MEM_mallocN(defbase_tot * sizeof(bool), __func__); bDeformGroup *defgroup; @@ -158,3 +597,86 @@ bool *BKE_objdef_selected_get(Object *ob, int defbase_tot, int *r_dg_flags_sel_t return dg_selection; } + + +/** + * Return the subset type of the Vertex Group Selection + */ +bool *BKE_object_defgroup_subset_from_select_type( + Object *ob, eVGroupSelect subset_type, int *r_defgroup_tot, int *r_subset_count) +{ + bool *defgroup_validmap = NULL; + *r_defgroup_tot = BLI_listbase_count(&ob->defbase); + + switch (subset_type) { + case WT_VGROUP_ACTIVE: + { + const int def_nr_active = ob->actdef - 1; + defgroup_validmap = MEM_mallocN(*r_defgroup_tot * sizeof(*defgroup_validmap), __func__); + memset(defgroup_validmap, false, *r_defgroup_tot * sizeof(*defgroup_validmap)); + if ((def_nr_active >= 0) && (def_nr_active < *r_defgroup_tot)) { + *r_subset_count = 1; + defgroup_validmap[def_nr_active] = true; + } + else { + *r_subset_count = 0; + } + break; + } + case WT_VGROUP_BONE_SELECT: + { + defgroup_validmap = BKE_object_defgroup_selected_get(ob, *r_defgroup_tot, r_subset_count); + break; + } + case WT_VGROUP_BONE_DEFORM: + { + int i; + defgroup_validmap = BKE_object_defgroup_validmap_get(ob, *r_defgroup_tot); + *r_subset_count = 0; + for (i = 0; i < *r_defgroup_tot; i++) { + if (defgroup_validmap[i] == true) { + *r_subset_count += 1; + } + } + break; + } + case WT_VGROUP_BONE_DEFORM_OFF: + { + int i; + defgroup_validmap = BKE_object_defgroup_validmap_get(ob, *r_defgroup_tot); + *r_subset_count = 0; + for (i = 0; i < *r_defgroup_tot; i++) { + defgroup_validmap[i] = !defgroup_validmap[i]; + if (defgroup_validmap[i] == true) { + *r_subset_count += 1; + } + } + break; + } + case WT_VGROUP_ALL: + default: + { + defgroup_validmap = MEM_mallocN(*r_defgroup_tot * sizeof(*defgroup_validmap), __func__); + memset(defgroup_validmap, true, *r_defgroup_tot * sizeof(*defgroup_validmap)); + *r_subset_count = *r_defgroup_tot; + break; + } + } + + return defgroup_validmap; +} + +/** + * store indices from the defgroup_validmap (faster lookups in some cases) + */ +void BKE_object_defgroup_subset_to_index_array( + const bool *defgroup_validmap, const int defgroup_tot, int *r_defgroup_subset_map) +{ + int i, j = 0; + for (i = 0; i < defgroup_tot; i++) { + if (defgroup_validmap[i]) { + r_defgroup_subset_map[j++] = i; + } + } +} + diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index 0d82c6e89a1..2bee6b76ad6 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -1240,7 +1240,7 @@ int count_duplilist(Object *ob) DupliApplyData *duplilist_apply(Object *ob, ListBase *duplilist) { DupliApplyData *apply_data = NULL; - int num_objects = BLI_countlist(duplilist); + int num_objects = BLI_listbase_count(duplilist); if (num_objects > 0) { DupliObject *dob; diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index d16575d80c8..96fff339521 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -316,7 +316,7 @@ void BKE_paint_curve_set(Brush *br, PaintCurve *pc) void BKE_palette_color_remove(Palette *palette, PaletteColor *color) { if (color) { - int numcolors = BLI_countlist(&palette->colors); + int numcolors = BLI_listbase_count(&palette->colors); if ((numcolors == palette->active_color + 1) && (numcolors != 1)) palette->active_color--; @@ -352,7 +352,7 @@ PaletteColor *BKE_palette_color_add(Palette *palette) { PaletteColor *color = MEM_callocN(sizeof(*color), "Pallete Color"); BLI_addtail(&palette->colors, color); - palette->active_color = BLI_countlist(&palette->colors) - 1; + palette->active_color = BLI_listbase_count(&palette->colors) - 1; return color; } @@ -644,11 +644,11 @@ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob) VirtualModifierData virtualModifierData; if (mmd || ob->sculpt->bm) - return 0; + return false; /* non-locked shape keys could be handled in the same way as deformed mesh */ if ((ob->shapeflag & OB_SHAPE_LOCK) == 0 && me->key && ob->shapenr) - return 1; + return true; md = modifiers_getVirtualModifierList(ob, &virtualModifierData); @@ -658,11 +658,11 @@ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob) if (!modifier_isEnabled(scene, md, eModifierMode_Realtime)) continue; if (ELEM(md->type, eModifierType_ShapeKey, eModifierType_Multires)) continue; - if (mti->type == eModifierTypeType_OnlyDeform) return 1; - else if ((sd->flags & SCULPT_ONLY_DEFORM) == 0) return 1; + if (mti->type == eModifierTypeType_OnlyDeform) return true; + else if ((sd->flags & SCULPT_ONLY_DEFORM) == 0) return true; } - return 0; + return false; } /** @@ -740,7 +740,7 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, BKE_free_sculptsession_deformMats(ss); - ss->orig_cos = (ss->kb) ? BKE_key_convert_to_vertcos(ob, ss->kb) : BKE_mesh_vertexCos_get(me, NULL); + ss->orig_cos = (ss->kb) ? BKE_keyblock_convert_to_vertcos(ob, ss->kb) : BKE_mesh_vertexCos_get(me, NULL); BKE_crazyspace_build_sculpt(scene, ob, &ss->deform_imats, &ss->deform_cos); BKE_pbvh_apply_vertCos(ss->pbvh, ss->deform_cos); @@ -755,14 +755,14 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, } if (ss->kb != NULL && ss->deform_cos == NULL) { - ss->deform_cos = BKE_key_convert_to_vertcos(ob, ss->kb); + ss->deform_cos = BKE_keyblock_convert_to_vertcos(ob, ss->kb); } /* if pbvh is deformed, key block is already applied to it */ if (ss->kb) { bool pbvh_deformd = BKE_pbvh_isDeformed(ss->pbvh); if (!pbvh_deformd || ss->deform_cos == NULL) { - float (*vertCos)[3] = BKE_key_convert_to_vertcos(ob, ss->kb); + float (*vertCos)[3] = BKE_keyblock_convert_to_vertcos(ob, ss->kb); if (vertCos) { if (!pbvh_deformd) { diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 530573d6e38..d577293fccb 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -981,14 +981,14 @@ bool psys_render_simplify_params(ParticleSystem *psys, ChildParticle *cpa, float int b; if (!(psys->renderdata && (psys->part->simplify_flag & PART_SIMPLIFY_ENABLE))) - return 0; + return false; data = psys->renderdata; if (!data->do_simplify) - return 0; + return false; b = (data->index_mf_to_mpoly) ? DM_origindex_mface_mpoly(data->index_mf_to_mpoly, data->index_mp_to_orig, cpa->num) : cpa->num; if (b == ORIGINDEX_NONE) { - return 0; + return false; } elem = &data->elems[b]; @@ -1043,7 +1043,7 @@ static float interpolate_particle_value(float v1, float v2, float v3, float v4, return value; } -void psys_interpolate_particle(short type, ParticleKey keys[4], float dt, ParticleKey *result, int velocity) +void psys_interpolate_particle(short type, ParticleKey keys[4], float dt, ParticleKey *result, bool velocity) { float t[4]; @@ -1073,7 +1073,6 @@ void psys_interpolate_particle(short type, ParticleKey keys[4], float dt, Partic } - typedef struct ParticleInterpolationData { HairKey *hkey[2]; @@ -3514,8 +3513,8 @@ ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *n psys->part = psys_new_settings(DATA_("ParticleSettings"), NULL); - if (BLI_countlist(&ob->particlesystem) > 1) - BLI_snprintf(psys->name, sizeof(psys->name), DATA_("ParticleSystem %i"), BLI_countlist(&ob->particlesystem)); + if (BLI_listbase_count_ex(&ob->particlesystem, 2) > 1) + BLI_snprintf(psys->name, sizeof(psys->name), DATA_("ParticleSystem %i"), BLI_listbase_count(&ob->particlesystem)); else BLI_strncpy(psys->name, DATA_("ParticleSystem"), sizeof(psys->name)); @@ -3524,7 +3523,7 @@ ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *n if (name) BLI_strncpy_utf8(md->name, name, sizeof(md->name)); else - BLI_snprintf(md->name, sizeof(md->name), DATA_("ParticleSystem %i"), BLI_countlist(&ob->particlesystem)); + BLI_snprintf(md->name, sizeof(md->name), DATA_("ParticleSystem %i"), BLI_listbase_count(&ob->particlesystem)); modifier_unique_name(&ob->modifiers, md); psmd = (ParticleSystemModifierData *) md; @@ -4564,8 +4563,7 @@ void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa psys_particle_on_emitter(psmd, PART_FROM_FACE, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, loc, nor, 0, 0, 0, 0); if (psys->part->rotmode == PART_ROT_VEL) { - copy_m3_m4(nmat, ob->imat); - transpose_m3(nmat); + transpose_m3_m4(nmat, ob->imat); mul_m3_v3(nmat, nor); normalize_v3(nor); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 155299b69c3..7ad99c14565 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -2764,24 +2764,6 @@ static void sph_force_cb(void *sphdata_v, ParticleKey *state, float *force, floa sphdata->pass++; } -/* powf is really slow for raising to integer powers. */ -MINLINE float pow2(float x) -{ - return x * x; -} -MINLINE float pow3(float x) -{ - return pow2(x) * x; -} -MINLINE float pow4(float x) -{ - return pow2(pow2(x)); -} -MINLINE float pow7(float x) -{ - return pow2(pow3(x)) * x; -} - static void sphclassical_density_accum_cb(void *userdata, int index, float UNUSED(squared_dist)) { SPHRangeData *pfr = (SPHRangeData *)userdata; @@ -2803,7 +2785,7 @@ static void sphclassical_density_accum_cb(void *userdata, int index, float UNUSE /* Smoothing factor. Utilise the Wendland kernel. gnuplot: * q1(x) = (2.0 - x)**4 * ( 1.0 + 2.0 * x) * plot [0:2] q1(x) */ - q = qfac / pow3(pfr->h) * pow4(2.0f - rij_h) * ( 1.0f + 2.0f * rij_h); + q = qfac / pow3f(pfr->h) * pow4f(2.0f - rij_h) * ( 1.0f + 2.0f * rij_h); q *= pfr->npsys->part->mass; if (pfr->use_size) @@ -2857,7 +2839,7 @@ static void sphclassical_force_cb(void *sphdata_v, ParticleKey *state, float *fo float rest_density = fluid->rest_density * (fluid->flag & SPH_FAC_DENSITY ? 4.77f : 1.0f); // Use speed of sound squared - float stiffness = pow2(fluid->stiffness_k); + float stiffness = pow2f(fluid->stiffness_k); ParticleData *npa; float vec[3]; @@ -2878,10 +2860,10 @@ static void sphclassical_force_cb(void *sphdata_v, ParticleKey *state, float *fo pfr.pa = pa; sph_evaluate_func(NULL, psys, state->co, &pfr, interaction_radius, sphclassical_neighbour_accum_cb); - pressure = stiffness * (pow7(pa->sphdensity / rest_density) - 1.0f); + pressure = stiffness * (pow7f(pa->sphdensity / rest_density) - 1.0f); /* multiply by mass so that we return a force, not accel */ - qfac2 *= sphdata->mass / pow3(pfr.h); + qfac2 *= sphdata->mass / pow3f(pfr.h); pfn = pfr.neighbors; for (i = 0; i < pfr.tot_neighbors; i++, pfn++) { @@ -2902,19 +2884,19 @@ static void sphclassical_force_cb(void *sphdata_v, ParticleKey *state, float *fo if (rij_h > 2.0f) continue; - npressure = stiffness * (pow7(npa->sphdensity / rest_density) - 1.0f); + npressure = stiffness * (pow7f(npa->sphdensity / rest_density) - 1.0f); /* First derivative of smoothing factor. Utilise the Wendland kernel. * gnuplot: * q2(x) = 2.0 * (2.0 - x)**4 - 4.0 * (2.0 - x)**3 * (1.0 + 2.0 * x) * plot [0:2] q2(x) * Particles > 2h away are excluded above. */ - dq = qfac2 * (2.0f * pow4(2.0f - rij_h) - 4.0f * pow3(2.0f - rij_h) * (1.0f + 2.0f * rij_h) ); + dq = qfac2 * (2.0f * pow4f(2.0f - rij_h) - 4.0f * pow3f(2.0f - rij_h) * (1.0f + 2.0f * rij_h) ); if (pfn->psys->part->flag & PART_SIZEMASS) dq *= npa->size; - pressureTerm = pressure / pow2(pa->sphdensity) + npressure / pow2(npa->sphdensity); + pressureTerm = pressure / pow2f(pa->sphdensity) + npressure / pow2f(npa->sphdensity); /* Note that 'minus' is removed, because vec = vecBA, not vecAB. * This applies to the viscosity calculation below, too. */ diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index ff6fae08460..bd953890443 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -943,7 +943,7 @@ static bool update_search_cb(PBVHNode *node, void *data_v) if (node->flag & PBVH_Leaf) return (node->flag & flag) != 0; - return 1; + return true; } static void pbvh_update_normals(PBVH *bvh, PBVHNode **nodes, @@ -1474,10 +1474,10 @@ bool ray_face_intersection(const float ray_start[3], (t3 && isect_ray_tri_epsilon_v3(ray_start, ray_normal, t0, t2, t3, &dist, NULL, 0.1f) && dist < *fdist)) { *fdist = dist; - return 1; + return true; } else { - return 0; + return false; } } diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index a6a7664ec61..19ed49c727a 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -50,7 +50,6 @@ #include "BLI_threads.h" #include "BLI_math.h" #include "BLI_utildefines.h" -#include "BLI_system.h" #include "BLF_translation.h" @@ -58,6 +57,7 @@ #include "WM_api.h" +#include "BKE_appdir.h" #include "BKE_anim.h" #include "BKE_blender.h" #include "BKE_cloth.h" @@ -1043,8 +1043,6 @@ static void ptcache_rigidbody_interpolate(int index, void *rb_v, void **data, fl { RigidBodyWorld *rbw = rb_v; Object *ob = NULL; - ParticleKey keys[4]; - float dfra; if (rbw->objects) ob = rbw->objects[index]; @@ -1053,6 +1051,11 @@ static void ptcache_rigidbody_interpolate(int index, void *rb_v, void **data, fl RigidBodyOb *rbo = ob->rigidbody_object; if (rbo->type == RBO_TYPE_ACTIVE) { + ParticleKey keys[4]; + ParticleKey result; + float dfra; + + memset(keys, 0, sizeof(keys)); copy_v3_v3(keys[1].co, rbo->pos); copy_qt_qt(keys[1].rot, rbo->orn); @@ -1062,16 +1065,17 @@ static void ptcache_rigidbody_interpolate(int index, void *rb_v, void **data, fl memcpy(keys[2].rot, data + 3, 4 * sizeof(float)); } else { - BKE_ptcache_make_particle_key(keys+2, 0, data, cfra2); + BKE_ptcache_make_particle_key(&keys[2], 0, data, cfra2); } dfra = cfra2 - cfra1; - psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, keys, 1); - interp_qt_qtqt(keys->rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra); + /* note: keys[0] and keys[3] unused for type < 1 (crappy) */ + psys_interpolate_particle(-1, keys, (cfra - cfra1) / dfra, &result, true); + interp_qt_qtqt(result.rot, keys[1].rot, keys[2].rot, (cfra - cfra1) / dfra); - copy_v3_v3(rbo->pos, keys->co); - copy_qt_qt(rbo->orn, keys->rot); + copy_v3_v3(rbo->pos, result.co); + copy_qt_qt(rbo->orn, result.rot); } } } @@ -1465,7 +1469,7 @@ static int ptcache_path(PTCacheID *pid, char *filename) /* use the temp path. this is weak but better then not using point cache at all */ /* temporary directory is assumed to exist and ALWAYS has a trailing slash */ - BLI_snprintf(filename, MAX_PTCACHE_PATH, "%s"PTCACHE_PATH, BLI_temp_dir_session()); + BLI_snprintf(filename, MAX_PTCACHE_PATH, "%s"PTCACHE_PATH, BKE_tempdir_session()); return BLI_add_slash(filename); /* new strlen() */ } @@ -2567,12 +2571,19 @@ void BKE_ptcache_id_clear(PTCacheID *pid, int mode, unsigned int cfra) if (pid->cache->flag & PTCACHE_DISK_CACHE) { ptcache_path(pid, path); - len = ptcache_filename(pid, filename, cfra, 0, 0); /* no path */ - dir = opendir(path); if (dir==NULL) return; - + + len = ptcache_filename(pid, filename, cfra, 0, 0); /* no path */ + /* append underscore terminator to ensure we don't match similar names + * from objects whose names start with the same prefix + */ + if (len < sizeof(filename) - 2) { + BLI_strncpy(filename + len, "_", sizeof(filename) - 2 - len); + len += 1; + } + BLI_snprintf(ext, sizeof(ext), "_%02u"PTCACHE_EXT, pid->stack_index); while ((de = readdir(dir)) != NULL) { diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 3d61b0bdefb..3bf5c4cc47e 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -62,8 +62,6 @@ #include "BKE_pointcache.h" #include "BKE_rigidbody.h" -#include "RNA_access.h" - #ifdef WITH_BULLET /* ************************************** */ @@ -401,7 +399,7 @@ static void rigidbody_validate_sim_shape(Object *ob, bool rebuild) height = size[2]; } else if (rbo->shape == RB_SHAPE_SPHERE) { - /* take radius to the the largest dimension to try and encompass everything */ + /* take radius to the largest dimension to try and encompass everything */ radius = MAX3(size[0], size[1], size[2]); } @@ -483,7 +481,7 @@ void BKE_rigidbody_calc_volume(Object *ob, float *r_vol) height = size[2]; } else if (rbo->shape == RB_SHAPE_SPHERE) { - /* take radius to the the largest dimension to try and encompass everything */ + /* take radius to the largest dimension to try and encompass everything */ radius = max_fff(size[0], size[1], size[2]) * 0.5f; } @@ -1158,7 +1156,7 @@ static void rigidbody_update_ob_array(RigidBodyWorld *rbw) GroupObject *go; int i, n; - n = BLI_countlist(&rbw->group->gobject); + n = BLI_listbase_count(&rbw->group->gobject); if (rbw->numbodies != n) { rbw->numbodies = n; @@ -1499,7 +1497,7 @@ void BKE_rigidbody_rebuild_world(Scene *scene, float ctime) cache = rbw->pointcache; /* flag cache as outdated if we don't have a world or number of objects in the simulation has changed */ - if (rbw->physics_world == NULL || rbw->numbodies != BLI_countlist(&rbw->group->gobject)) { + if (rbw->physics_world == NULL || rbw->numbodies != BLI_listbase_count(&rbw->group->gobject)) { cache->flag |= PTCACHE_OUTDATED; } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 5bfd6e8a120..13e9b7fb0c4 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -63,12 +63,14 @@ #include "BKE_anim.h" #include "BKE_animsys.h" #include "BKE_action.h" +#include "BKE_armature.h" #include "BKE_colortools.h" #include "BKE_depsgraph.h" #include "BKE_editmesh.h" #include "BKE_fcurve.h" #include "BKE_freestyle.h" #include "BKE_global.h" +#include "BKE_gpencil.h" #include "BKE_group.h" #include "BKE_idprop.h" #include "BKE_image.h" @@ -98,6 +100,10 @@ # include <sys/time.h> #endif +const char *RE_engine_id_BLENDER_RENDER = "BLENDER_RENDER"; +const char *RE_engine_id_BLENDER_GAME = "BLENDER_GAME"; +const char *RE_engine_id_CYCLES = "CYCLES"; + void free_avicodecdata(AviCodecData *acd) { if (acd) { @@ -303,6 +309,19 @@ Scene *BKE_scene_copy(Scene *sce, int type) BKE_sequence_base_dupli_recursive(sce, scen, &scen->ed->seqbase, &sce->ed->seqbase, SEQ_DUPE_ALL); } } + + /* grease pencil */ + if (scen->gpd) { + if (type == SCE_COPY_FULL) { + scen->gpd = gpencil_data_duplicate(scen->gpd, false); + } + else if (type == SCE_COPY_EMPTY) { + scen->gpd = NULL; + } + else { + id_us_plus((ID *)scen->gpd); + } + } return scen; } @@ -595,7 +614,7 @@ Scene *BKE_scene_add(Main *bmain, const char *name) sce->r.ffcodecdata.audio_bitrate = 192; sce->r.ffcodecdata.audio_channels = 2; - BLI_strncpy(sce->r.engine, "BLENDER_RENDER", sizeof(sce->r.engine)); + BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_RENDER, sizeof(sce->r.engine)); sce->audio.distance_model = 2.0f; sce->audio.doppler_factor = 1.0f; @@ -1092,27 +1111,24 @@ void BKE_scene_base_select(Scene *sce, Base *selbase) } /* checks for cycle, returns 1 if it's all OK */ -int BKE_scene_validate_setscene(Main *bmain, Scene *sce) +bool BKE_scene_validate_setscene(Main *bmain, Scene *sce) { - Scene *scene; + Scene *sce_iter; int a, totscene; + + if (sce->set == NULL) return true; + totscene = BLI_listbase_count(&bmain->scene); - if (sce->set == NULL) return 1; - - totscene = 0; - for (scene = bmain->scene.first; scene; scene = scene->id.next) - totscene++; - - for (a = 0, scene = sce; scene->set; scene = scene->set, a++) { + for (a = 0, sce_iter = sce; sce_iter->set; sce_iter = sce_iter->set, a++) { /* more iterations than scenes means we have a cycle */ if (a > totscene) { /* the tested scene gets zero'ed, that's typically current scene */ sce->set = NULL; - return 0; + return false; } } - return 1; + return true; } /* This function is needed to cope with fractional frames - including two Blender rendering features @@ -1242,8 +1258,35 @@ static void scene_depsgraph_hack(EvaluationContext *eval_ctx, Scene *scene, Scen } } } +} +/* That's like really a bummer, because currently animation data for armatures + * might want to use pose, and pose might be missing on the object. + * This happens when changing visible layers, which leads to situations when + * pose is missing or marked for recalc, animation will change it and then + * object update will restore the pose. + * + * This could be solved by the new dependency graph, but for until then we'll + * do an extra pass on the objects to ensure it's all fine. + */ +#define POSE_ANIMATION_WORKAROUND + +#ifdef POSE_ANIMATION_WORKAROUND +static void scene_armature_depsgraph_workaround(Main *bmain) +{ + Object *ob; + if (BLI_listbase_is_empty(&bmain->armature) || !DAG_id_type_tagged(bmain, ID_OB)) { + return; + } + for (ob = bmain->object.first; ob; ob = ob->id.next) { + if (ob->type == OB_ARMATURE && ob->adt && ob->adt->recalc & ADT_RECALC_ANIM) { + if (ob->pose == NULL || (ob->pose->flag & POSE_RECALC)) { + BKE_pose_rebuild(ob, ob->data); + } + } + } } +#endif static void scene_rebuild_rbw_recursive(Scene *scene, float ctime) { @@ -1736,6 +1779,10 @@ void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain, BKE_mask_evaluate_all_masks(bmain, ctime, true); +#ifdef POSE_ANIMATION_WORKAROUND + scene_armature_depsgraph_workaround(bmain); +#endif + /* All 'standard' (i.e. without any dependencies) animation is handled here, * with an 'local' to 'macro' order of evaluation. This should ensure that * settings stored nestled within a hierarchy (i.e. settings in a Texture block @@ -1805,13 +1852,13 @@ bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer * Scene *sce; if (act == -1) { - return 0; + return false; } else if ( (scene->r.layers.first == scene->r.layers.last) && (scene->r.layers.first == srl)) { /* ensure 1 layer is kept */ - return 0; + return false; } BLI_remlink(&scene->r.layers, srl); @@ -1833,7 +1880,7 @@ bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer * } } - return 1; + return true; } /* render simplification */ @@ -1902,9 +1949,13 @@ bool BKE_scene_use_new_shading_nodes(Scene *scene) bool BKE_scene_uses_blender_internal(struct Scene *scene) { - return strcmp("BLENDER_RENDER", scene->r.engine) == 0; + return STREQ(scene->r.engine, RE_engine_id_BLENDER_RENDER); } +bool BKE_scene_uses_blender_game(struct Scene *scene) +{ + return STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME); +} void BKE_scene_base_flag_to_objects(struct Scene *scene) { diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index c9647b05ce7..ddc0d5874f8 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -257,26 +257,15 @@ Editing *BKE_sequencer_editing_get(Scene *scene, bool alloc) return scene->ed; } -static void seq_free_clipboard_recursive(Sequence *seq_parent) -{ - Sequence *seq, *nseq; - - for (seq = seq_parent->seqbase.first; seq; seq = nseq) { - nseq = seq->next; - seq_free_clipboard_recursive(seq); - } - - BKE_sequence_clipboard_pointers_free(seq_parent); - BKE_sequence_free_ex(NULL, seq_parent, false); -} - void BKE_sequencer_free_clipboard(void) { Sequence *seq, *nseq; + BKE_sequencer_base_clipboard_pointers_free(&seqbase_clipboard); + for (seq = seqbase_clipboard.first; seq; seq = nseq) { nseq = seq->next; - seq_free_clipboard_recursive(seq); + seq_free_sequence_recurse(NULL, seq); } BLI_listbase_clear(&seqbase_clipboard); } @@ -373,6 +362,33 @@ void BKE_sequence_clipboard_pointers_restore(Sequence *seq, Main *bmain) seqclipboard_ptr_restore(bmain, (ID **)&seq->mask); seqclipboard_ptr_restore(bmain, (ID **)&seq->sound); } + +/* recursive versions of funcions above */ +void BKE_sequencer_base_clipboard_pointers_free(ListBase *seqbase) +{ + Sequence *seq; + for (seq = seqbase->first; seq; seq = seq->next) { + BKE_sequence_clipboard_pointers_free(seq); + BKE_sequencer_base_clipboard_pointers_free(&seq->seqbase); + } +} +void BKE_sequencer_base_clipboard_pointers_store(ListBase *seqbase) +{ + Sequence *seq; + for (seq = seqbase->first; seq; seq = seq->next) { + BKE_sequence_clipboard_pointers_store(seq); + BKE_sequencer_base_clipboard_pointers_store(&seq->seqbase); + } +} +void BKE_sequencer_base_clipboard_pointers_restore(ListBase *seqbase, Main *bmain) +{ + Sequence *seq; + for (seq = seqbase->first; seq; seq = seq->next) { + BKE_sequence_clipboard_pointers_restore(seq, bmain); + BKE_sequencer_base_clipboard_pointers_restore(&seq->seqbase, bmain); + } +} + /* end clipboard pointer mess */ @@ -876,7 +892,6 @@ void BKE_sequencer_sort(Scene *scene) Editing *ed = BKE_sequencer_editing_get(scene, false); Sequence *seq, *seqt; - if (ed == NULL) return; @@ -1474,20 +1489,25 @@ static void seq_proxy_build_frame(const SeqRenderData *context, Sequence *seq, i int quality; int rectx, recty; int ok; - ImBuf *ibuf; + ImBuf *ibuf_tmp, *ibuf; if (!seq_proxy_get_fname(seq, cfra, proxy_render_size, name)) { return; } - ibuf = seq_render_strip(context, seq, cfra); + ibuf_tmp = seq_render_strip(context, seq, cfra); - rectx = (proxy_render_size * ibuf->x) / 100; - recty = (proxy_render_size * ibuf->y) / 100; + rectx = (proxy_render_size * ibuf_tmp->x) / 100; + recty = (proxy_render_size * ibuf_tmp->y) / 100; - if (ibuf->x != rectx || ibuf->y != recty) { + if (ibuf_tmp->x != rectx || ibuf_tmp->y != recty) { + ibuf = IMB_dupImBuf(ibuf_tmp); + IMB_freeImBuf(ibuf_tmp); IMB_scalefastImBuf(ibuf, (short)rectx, (short)recty); } + else { + ibuf = ibuf_tmp; + } /* depth = 32 is intentionally left in, otherwise ALPHA channels * won't work... */ @@ -2509,6 +2529,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq int do_seq; // bool have_seq = false; /* UNUSED */ bool have_comp = false; + bool use_gpencil = true; Scene *scene; int is_thread_main = BLI_thread_is_main(); @@ -2533,6 +2554,10 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq BKE_scene_camera_switch_update(scene); camera = scene->camera; } + + if (seq->flag & SEQ_SCENE_NO_GPENCIL) { + use_gpencil = false; + } if (have_comp == false && camera == NULL) { scene->r.cfra = oldcfra; @@ -2566,7 +2591,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq ibuf = sequencer_view3d_cb(scene, camera, width, height, IB_rect, context->scene->r.seq_prev_type, (context->scene->r.seq_flag & R_SEQ_SOLID_TEX) != 0, - true, scene->r.alphamode, err_out); + use_gpencil, true, scene->r.alphamode, err_out); if (ibuf == NULL) { fprintf(stderr, "seq_render_scene_strip failed to get opengl buffer: %s\n", err_out); } @@ -3080,7 +3105,7 @@ ImBuf *BKE_sequencer_give_ibuf(const SeqRenderData *context, float cfra, int cha if (ed == NULL) return NULL; if ((chanshown < 0) && !BLI_listbase_is_empty(&ed->metastack)) { - int count = BLI_countlist(&ed->metastack); + int count = BLI_listbase_count(&ed->metastack); count = max_ii(count + chanshown, 0); seqbasep = ((MetaStack *)BLI_findlink(&ed->metastack, count))->oldbasep; } @@ -3395,7 +3420,7 @@ static bool update_changed_seq_recurs(Scene *scene, Sequence *seq, Sequence *cha /* recurs downwards to see if this seq depends on the changed seq */ if (seq == NULL) - return 0; + return false; if (seq == changed_seq) free_imbuf = true; @@ -3513,28 +3538,16 @@ bool BKE_sequence_single_check(Sequence *seq) } /* check if the selected seq's reference unselected seq's */ -bool BKE_sequence_base_isolated_sel_check(ListBase *seqbase, bool one_only) +bool BKE_sequence_base_isolated_sel_check(ListBase *seqbase) { Sequence *seq; - /* is there a valid selection select */ + /* is there more than 1 select */ bool ok = false; - /* is there one selected already? */ - bool first = false; for (seq = seqbase->first; seq; seq = seq->next) { if (seq->flag & SELECT) { - if (one_only) { - ok = true; - break; - } - else { - if (first) { - ok = true; - break; - } - else - first = true; - } + ok = true; + break; } } @@ -4616,11 +4629,15 @@ Sequence *BKE_sequence_dupli_recursive(Scene *scene, Scene *scene_to, Sequence * return seqn; } -void BKE_sequence_base_dupli_recursive(Scene *scene, Scene *scene_to, ListBase *nseqbase, ListBase *seqbase, int dupe_flag) +void BKE_sequence_base_dupli_recursive( + Scene *scene, Scene *scene_to, ListBase *nseqbase, ListBase *seqbase, + int dupe_flag) { Sequence *seq; Sequence *seqn = NULL; Sequence *last_seq = BKE_sequencer_active_get(scene); + /* always include meta's strips */ + int dupe_flag_recursive = dupe_flag | SEQ_DUPE_ALL; for (seq = seqbase->first; seq; seq = seq->next) { seq->tmp = NULL; @@ -4633,8 +4650,11 @@ void BKE_sequence_base_dupli_recursive(Scene *scene, Scene *scene_to, ListBase * } BLI_addtail(nseqbase, seqn); - if (seq->type == SEQ_TYPE_META) - BKE_sequence_base_dupli_recursive(scene, scene_to, &seqn->seqbase, &seq->seqbase, dupe_flag); + if (seq->type == SEQ_TYPE_META) { + BKE_sequence_base_dupli_recursive( + scene, scene_to, &seqn->seqbase, &seq->seqbase, + dupe_flag_recursive); + } if (dupe_flag & SEQ_DUPE_CONTEXT) { if (seq == last_seq) { @@ -4664,3 +4684,70 @@ bool BKE_sequence_is_valid_check(Sequence *seq) return true; } +int BKE_sequencer_find_next_prev_edit( + Scene *scene, int cfra, const short side, + const bool do_skip_mute, const bool do_center, const bool do_unselected) +{ + Editing *ed = BKE_sequencer_editing_get(scene, false); + Sequence *seq; + + int dist, best_dist, best_frame = cfra; + int seq_frames[2], seq_frames_tot; + + /* in case where both is passed, frame just finds the nearest end while frame_left the nearest start */ + + best_dist = MAXFRAME * 2; + + if (ed == NULL) return cfra; + + for (seq = ed->seqbasep->first; seq; seq = seq->next) { + int i; + + if (do_skip_mute && (seq->flag & SEQ_MUTE)) { + continue; + } + + if (do_unselected && (seq->flag & SELECT)) + continue; + + if (do_center) { + seq_frames[0] = (seq->startdisp + seq->enddisp) / 2; + seq_frames_tot = 1; + } + else { + seq_frames[0] = seq->startdisp; + seq_frames[1] = seq->enddisp; + + seq_frames_tot = 2; + } + + for (i = 0; i < seq_frames_tot; i++) { + const int seq_frame = seq_frames[i]; + + dist = MAXFRAME * 2; + + switch (side) { + case SEQ_SIDE_LEFT: + if (seq_frame < cfra) { + dist = cfra - seq_frame; + } + break; + case SEQ_SIDE_RIGHT: + if (seq_frame > cfra) { + dist = seq_frame - cfra; + } + break; + case SEQ_SIDE_BOTH: + dist = abs(seq_frame - cfra); + break; + } + + if (dist < best_dist) { + best_frame = seq_frame; + best_dist = dist; + } + } + } + + return best_frame; +} diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index d2a4d15a2c6..d91818615f3 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -52,7 +52,6 @@ #include "BKE_deform.h" #include "BKE_mesh.h" /* for OMP limits. */ #include "BKE_subsurf.h" -#include "BKE_editmesh.h" #include "BLI_strict_flags.h" diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 90ac712e55a..4c46875bd48 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -60,6 +60,7 @@ #include "DNA_scene_types.h" #include "DNA_smoke_types.h" +#include "BKE_appdir.h" #include "BKE_animsys.h" #include "BKE_armature.h" #include "BKE_bvhutils.h" @@ -205,7 +206,7 @@ void smoke_reallocate_highres_fluid(SmokeDomainSettings *sds, float dx, int res[ /* smoke_turbulence_init uses non-threadsafe functions from fftw3 lib (like fftw_plan & co). */ BLI_lock_thread(LOCK_FFTW); - sds->wt = smoke_turbulence_init(res, sds->amplify + 1, sds->noise, BLI_temp_dir_session(), use_fire, use_colors); + sds->wt = smoke_turbulence_init(res, sds->amplify + 1, sds->noise, BKE_tempdir_session(), use_fire, use_colors); BLI_unlock_thread(LOCK_FFTW); @@ -953,7 +954,7 @@ static bool subframe_updateObject(Scene *scene, Object *ob, int update_mesh, int /* if other is dynamic paint canvas, don't update */ if (smd && (smd->type & MOD_SMOKE_TYPE_DOMAIN)) - return 1; + return true; /* if object has parents, update them too */ if (parent_recursion) { @@ -965,7 +966,7 @@ static bool subframe_updateObject(Scene *scene, Object *ob, int update_mesh, int /* skip subframe if object is parented * to vertex of a dynamic paint canvas */ if (is_domain && (ob->partype == PARVERT1 || ob->partype == PARVERT3)) - return 0; + return false; /* also update constraint targets */ for (con = ob->constraints.first; con; con = con->next) { @@ -1011,7 +1012,7 @@ static bool subframe_updateObject(Scene *scene, Object *ob, int update_mesh, int BKE_pose_where_is(scene, ob); } - return 0; + return false; } /********************************************************** @@ -1424,7 +1425,7 @@ static void emit_from_particles(Object *flow_ob, SmokeDomainSettings *sds, Smoke static void sample_derivedmesh( SmokeFlowSettings *sfs, MVert *mvert, MTFace *tface, MFace *mface, - float *influence_map, float *velocity_map, int index, int base_res[3], float flow_center[3], + float *influence_map, float *velocity_map, int index, const int base_res[3], float flow_center[3], BVHTreeFromMesh *treeData, const float ray_start[3], const float *vert_vel, bool has_velocity, int defgrp_index, MDeformVert *dvert, float x, float y, float z) { @@ -2020,7 +2021,7 @@ BLI_INLINE void apply_inflow_fields(SmokeFlowSettings *sfs, float emission_value if (fuel && fuel[index] > FLT_EPSILON) { /* instead of using 1.0 for all new fuel add slight falloff * to reduce flow blockiness */ - float value = 1.0f - powf(1.0f - emission_value, 2.0f); + float value = 1.0f - pow2f(1.0f - emission_value); if (value > react[index]) { float f = fuel_flow / fuel[index]; diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 13575560669..941344cf21e 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -3349,7 +3349,7 @@ static void mesh_to_softbody(Scene *scene, Object *ob) build_bps_springlist(ob); /* scan for springs attached to bodypoints ONCE */ /* insert *other second order* springs if desired */ if (sb->secondspring > 0.0000001f) { - add_2nd_order_springs(ob, sb->secondspring); /* exploits the the first run of build_bps_springlist(ob);*/ + add_2nd_order_springs(ob, sb->secondspring); /* exploits the first run of build_bps_springlist(ob);*/ build_bps_springlist(ob); /* yes we need to do it again*/ } springs_from_mesh(ob); /* write the 'rest'-length of the springs */ @@ -3561,7 +3561,7 @@ static void curve_surf_to_softbody(Scene *scene, Object *ob) if (ob->softflag & OB_SB_EDGES) { if (ob->type==OB_CURVE) { - totspring= totvert - BLI_countlist(&cu->nurb); + totspring = totvert - BLI_listbase_count(&cu->nurb); } } diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index da6ead06d98..3c7b01f9052 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -36,6 +36,7 @@ #include "BLI_blenlib.h" #include "BLI_math.h" +#include "BLI_threads.h" #include "DNA_anim_types.h" #include "DNA_object_types.h" @@ -116,6 +117,12 @@ void BKE_sound_free(bSound *sound) } sound_free_waveform(sound); + + if (sound->mutex) { + BLI_mutex_free(sound->mutex); + sound->mutex = NULL; + } + #endif /* WITH_AUDASPACE */ } @@ -296,12 +303,6 @@ void sound_cache(bSound *sound) sound->playback_handle = sound->handle; } -void sound_cache_notifying(struct Main *main, bSound *sound) -{ - sound_cache(sound); - sound_update_sequencer(main, sound); -} - void sound_delete_cache(bSound *sound) { sound->flags &= ~SOUND_FLAGS_CACHING; @@ -680,22 +681,40 @@ void sound_free_waveform(bSound *sound) sound->waveform = NULL; } -void sound_read_waveform(bSound *sound) +void sound_read_waveform(bSound *sound, bool locked, short *stop) { AUD_SoundInfo info; - + SoundWaveform *waveform = NULL; + info = AUD_getInfo(sound->playback_handle); - + if (info.length > 0) { - SoundWaveform *waveform = MEM_mallocN(sizeof(SoundWaveform), "SoundWaveform"); int length = info.length * SOUND_WAVE_SAMPLES_PER_SECOND; - + + waveform = MEM_mallocN(sizeof(SoundWaveform), "SoundWaveform"); waveform->data = MEM_mallocN(length * sizeof(float) * 3, "SoundWaveform.samples"); - waveform->length = AUD_readSound(sound->playback_handle, waveform->data, length, SOUND_WAVE_SAMPLES_PER_SECOND); - + waveform->length = AUD_readSound(sound->playback_handle, waveform->data, length, SOUND_WAVE_SAMPLES_PER_SECOND, stop); + + if (*stop) { + MEM_freeN(waveform->data); + MEM_freeN(waveform); + if (locked) + BLI_mutex_lock(sound->mutex); + sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING; + if (locked) + BLI_mutex_unlock(sound->mutex); + return; + } + sound_free_waveform(sound); - sound->waveform = waveform; } + + if (locked) + BLI_mutex_lock(sound->mutex); + sound->waveform = waveform; + sound->flags &= ~SOUND_FLAGS_WAVEFORM_LOADING; + if (locked) + BLI_mutex_unlock(sound->mutex); } void sound_update_scene(Main *bmain, struct Scene *scene) @@ -830,7 +849,7 @@ void sound_stop_scene(struct Scene *UNUSED(scene)) {} void sound_seek_scene(struct Main *UNUSED(bmain), struct Scene *UNUSED(scene)) {} float sound_sync_scene(struct Scene *UNUSED(scene)) { return NAN_FLT; } int sound_scene_playing(struct Scene *UNUSED(scene)) { return -1; } -void sound_read_waveform(struct bSound *UNUSED(sound)) {} +void sound_read_waveform(struct bSound *sound, bool locked, short *stop) { UNUSED_VARS(sound, locked, stop); } void sound_init_main(struct Main *UNUSED(bmain)) {} void sound_set_cfra(int UNUSED(cfra)) {} void sound_update_sequencer(struct Main *UNUSED(main), struct bSound *UNUSED(sound)) {} diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 0bd9517dcfd..c777fcd5e7b 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -41,7 +41,6 @@ #include "MEM_guardedalloc.h" -#include "DNA_material_types.h" #include "DNA_mesh_types.h" #include "DNA_meshdata_types.h" #include "DNA_modifier_types.h" @@ -66,8 +65,6 @@ #include "BKE_scene.h" #include "BKE_subsurf.h" -#include "PIL_time.h" - #ifndef USE_DYNSIZE # include "BLI_array.h" #endif @@ -75,7 +72,6 @@ #include "GPU_draw.h" #include "GPU_extensions.h" #include "GPU_glew.h" -#include "GPU_material.h" #include "CCGSubSurf.h" @@ -411,7 +407,7 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, CCGFace **faceMap; MTFace *tf; MLoopUV *mluv; - CCGFaceIterator *fi; + CCGFaceIterator fi; int index, gridSize, gridFaces, /*edgeSize,*/ totface, x, y, S; MLoopUV *dmloopuv = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, n); /* need to update both CD_MTFACE & CD_MLOOPUV, hrmf, we could get away with @@ -438,11 +434,10 @@ static void set_subsurf_uv(CCGSubSurf *ss, DerivedMesh *dm, DerivedMesh *result, /* make a map from original faces to CCGFaces */ faceMap = MEM_mallocN(totface * sizeof(*faceMap), "facemapuv"); - for (fi = ccgSubSurf_getFaceIterator(uvss); !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) { - CCGFace *f = ccgFaceIterator_getCurrent(fi); + for (ccgSubSurf_initFaceIterator(uvss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) { + CCGFace *f = ccgFaceIterator_getCurrent(&fi); faceMap[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f))] = f; } - ccgFaceIterator_free(fi); /* load coordinates from uvss into tface */ tf = tface; @@ -699,9 +694,9 @@ static void ccgDM_getMinMax(DerivedMesh *dm, float r_min[3], float r_max[3]) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; CCGSubSurf *ss = ccgdm->ss; - CCGVertIterator *vi; - CCGEdgeIterator *ei; - CCGFaceIterator *fi; + CCGVertIterator vi; + CCGEdgeIterator ei; + CCGFaceIterator fi; CCGKey key; int i, edgeSize = ccgSubSurf_getEdgeSize(ss); int gridSize = ccgSubSurf_getGridSize(ss); @@ -711,25 +706,23 @@ static void ccgDM_getMinMax(DerivedMesh *dm, float r_min[3], float r_max[3]) if (!ccgSubSurf_getNumVerts(ss)) r_min[0] = r_min[1] = r_min[2] = r_max[0] = r_max[1] = r_max[2] = 0.0; - for (vi = ccgSubSurf_getVertIterator(ss); !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) { - CCGVert *v = ccgVertIterator_getCurrent(vi); + for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) { + CCGVert *v = ccgVertIterator_getCurrent(&vi); float *co = ccgSubSurf_getVertData(ss, v); minmax_v3_v3v3(co, r_min, r_max); } - ccgVertIterator_free(vi); - for (ei = ccgSubSurf_getEdgeIterator(ss); !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) { - CCGEdge *e = ccgEdgeIterator_getCurrent(ei); + for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) { + CCGEdge *e = ccgEdgeIterator_getCurrent(&ei); CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e); for (i = 0; i < edgeSize; i++) minmax_v3_v3v3(CCG_elem_offset_co(&key, edgeData, i), r_min, r_max); } - ccgEdgeIterator_free(ei); - for (fi = ccgSubSurf_getFaceIterator(ss); !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) { - CCGFace *f = ccgFaceIterator_getCurrent(fi); + for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) { + CCGFace *f = ccgFaceIterator_getCurrent(&fi); int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f); for (S = 0; S < numVerts; S++) { @@ -740,7 +733,6 @@ static void ccgDM_getMinMax(DerivedMesh *dm, float r_min[3], float r_max[3]) minmax_v3_v3v3(CCG_grid_elem_co(&key, faceGridData, x, y), r_min, r_max); } } - ccgFaceIterator_free(fi); } static int ccgDM_getNumVerts(DerivedMesh *dm) @@ -1433,9 +1425,9 @@ static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) int edgeSize = ccgSubSurf_getEdgeSize(ss); int gridSize = ccgSubSurf_getGridSize(ss); int i; - CCGVertIterator *vi; - CCGEdgeIterator *ei; - CCGFaceIterator *fi; + CCGVertIterator vi; + CCGEdgeIterator ei; + CCGFaceIterator fi; CCGFace **faceMap2; CCGEdge **edgeMap2; CCGVert **vertMap2; @@ -1443,30 +1435,27 @@ static void ccgdm_getVertCos(DerivedMesh *dm, float (*cos)[3]) totvert = ccgSubSurf_getNumVerts(ss); vertMap2 = MEM_mallocN(totvert * sizeof(*vertMap2), "vertmap"); - for (vi = ccgSubSurf_getVertIterator(ss); !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) { - CCGVert *v = ccgVertIterator_getCurrent(vi); + for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) { + CCGVert *v = ccgVertIterator_getCurrent(&vi); vertMap2[GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v))] = v; } - ccgVertIterator_free(vi); totedge = ccgSubSurf_getNumEdges(ss); edgeMap2 = MEM_mallocN(totedge * sizeof(*edgeMap2), "edgemap"); - for (ei = ccgSubSurf_getEdgeIterator(ss), i = 0; !ccgEdgeIterator_isStopped(ei); i++, ccgEdgeIterator_next(ei)) { - CCGEdge *e = ccgEdgeIterator_getCurrent(ei); + for (ccgSubSurf_initEdgeIterator(ss, &ei), i = 0; !ccgEdgeIterator_isStopped(&ei); i++, ccgEdgeIterator_next(&ei)) { + CCGEdge *e = ccgEdgeIterator_getCurrent(&ei); edgeMap2[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))] = e; } - ccgEdgeIterator_free(ei); totface = ccgSubSurf_getNumFaces(ss); faceMap2 = MEM_mallocN(totface * sizeof(*faceMap2), "facemap"); - for (fi = ccgSubSurf_getFaceIterator(ss); !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) { - CCGFace *f = ccgFaceIterator_getCurrent(fi); + for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) { + CCGFace *f = ccgFaceIterator_getCurrent(&fi); faceMap2[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f))] = f; } - ccgFaceIterator_free(fi); i = 0; for (index = 0; index < totface; index++) { @@ -1516,12 +1505,12 @@ static void ccgDM_foreachMappedVert( DMForeachFlag flag) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; - CCGVertIterator *vi; + CCGVertIterator vi; CCGKey key; CCG_key_top_level(&key, ccgdm->ss); - for (vi = ccgSubSurf_getVertIterator(ccgdm->ss); !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) { - CCGVert *v = ccgVertIterator_getCurrent(vi); + for (ccgSubSurf_initVertIterator(ccgdm->ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) { + CCGVert *v = ccgVertIterator_getCurrent(&vi); const int index = ccgDM_getVertMapIndex(ccgdm->ss, v); if (index != -1) { @@ -1530,8 +1519,6 @@ static void ccgDM_foreachMappedVert( func(userData, index, CCG_elem_co(&key, vd), no, NULL); } } - - ccgVertIterator_free(vi); } static void ccgDM_foreachMappedEdge( @@ -1541,14 +1528,14 @@ static void ccgDM_foreachMappedEdge( { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; CCGSubSurf *ss = ccgdm->ss; - CCGEdgeIterator *ei; + CCGEdgeIterator ei; CCGKey key; int i, edgeSize = ccgSubSurf_getEdgeSize(ss); CCG_key_top_level(&key, ss); - for (ei = ccgSubSurf_getEdgeIterator(ss); !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) { - CCGEdge *e = ccgEdgeIterator_getCurrent(ei); + for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) { + CCGEdge *e = ccgEdgeIterator_getCurrent(&ei); const int index = ccgDM_getEdgeMapIndex(ss, e); if (index != -1) { @@ -1558,8 +1545,6 @@ static void ccgDM_foreachMappedEdge( } } } - - ccgEdgeIterator_free(ei); } static void ccgDM_foreachMappedLoop( @@ -1597,28 +1582,26 @@ static void ccgDM_drawVerts(DerivedMesh *dm) CCGSubSurf *ss = ccgdm->ss; int edgeSize = ccgSubSurf_getEdgeSize(ss); int gridSize = ccgSubSurf_getGridSize(ss); - CCGVertIterator *vi; - CCGEdgeIterator *ei; - CCGFaceIterator *fi; + CCGVertIterator vi; + CCGEdgeIterator ei; + CCGFaceIterator fi; glBegin(GL_POINTS); - for (vi = ccgSubSurf_getVertIterator(ss); !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) { - CCGVert *v = ccgVertIterator_getCurrent(vi); + for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) { + CCGVert *v = ccgVertIterator_getCurrent(&vi); glVertex3fv(ccgSubSurf_getVertData(ss, v)); } - ccgVertIterator_free(vi); - for (ei = ccgSubSurf_getEdgeIterator(ss); !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) { - CCGEdge *e = ccgEdgeIterator_getCurrent(ei); + for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) { + CCGEdge *e = ccgEdgeIterator_getCurrent(&ei); int x; for (x = 1; x < edgeSize - 1; x++) glVertex3fv(ccgSubSurf_getEdgeData(ss, e, x)); } - ccgEdgeIterator_free(ei); - for (fi = ccgSubSurf_getFaceIterator(ss); !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) { - CCGFace *f = ccgFaceIterator_getCurrent(fi); + for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) { + CCGFace *f = ccgFaceIterator_getCurrent(&fi); int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f); glVertex3fv(ccgSubSurf_getFaceCenterData(f)); @@ -1630,7 +1613,6 @@ static void ccgDM_drawVerts(DerivedMesh *dm) for (x = 1; x < gridSize - 1; x++) glVertex3fv(ccgSubSurf_getFaceGridData(ss, f, S, x, y)); } - ccgFaceIterator_free(fi); glEnd(); } @@ -2289,7 +2271,7 @@ static void ccgDM_drawMappedFacesMat(DerivedMesh *dm, static void ccgDM_drawFacesTex_common(DerivedMesh *dm, DMSetDrawOptionsTex drawParams, - DMSetDrawOptions drawParamsMapped, + DMSetDrawOptionsMappedTex drawParamsMapped, DMCompareDrawOptions compareDrawOptions, void *userData, DMDrawFlag flag) { @@ -2352,15 +2334,16 @@ static void ccgDM_drawFacesTex_common(DerivedMesh *dm, mat_nr_cache = mat_nr; } - tf = tf_base + gridOffset; - tf_stencil = tf_stencil_base + gridOffset; + + tf = tf_base ? tf_base + gridOffset : NULL; + tf_stencil = tf_stencil_base ? tf_stencil_base + gridOffset : NULL; gridOffset += gridFaces * gridFaces * numVerts; } if (drawParams) draw_option = drawParams(tf, (mcol != NULL), mat_nr); else if (index != ORIGINDEX_NONE) - draw_option = (drawParamsMapped) ? drawParamsMapped(userData, index) : DM_DRAW_OPTION_NORMAL; + draw_option = (drawParamsMapped) ? drawParamsMapped(userData, index, mat_nr) : DM_DRAW_OPTION_NORMAL; else draw_option = GPU_enable_material(mat_nr, NULL) ? DM_DRAW_OPTION_NORMAL : DM_DRAW_OPTION_SKIP; @@ -2529,7 +2512,7 @@ static void ccgDM_drawFacesTex(DerivedMesh *dm, } static void ccgDM_drawMappedFacesTex(DerivedMesh *dm, - DMSetDrawOptions setDrawOptions, + DMSetDrawOptionsMappedTex setDrawOptions, DMCompareDrawOptions compareDrawOptions, void *userData, DMDrawFlag flag) { @@ -2585,6 +2568,7 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, DMFlagMat *faceFlags = ccgdm->faceFlags; int useColors = flag & DM_DRAW_USE_COLORS; int gridFaces = gridSize - 1, totface; + int prev_mat_nr = -1; CCG_key_top_level(&key, ss); @@ -2625,9 +2609,16 @@ static void ccgDM_drawMappedFaces(DerivedMesh *dm, { DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL; - if (index == ORIGINDEX_NONE) - draw_option = setMaterial(faceFlags ? faceFlags[origIndex].mat_nr + 1 : 1, NULL); /* XXX, no faceFlags no material */ - else if (setDrawOptions) + if (setMaterial) { + int mat_nr = faceFlags ? faceFlags[origIndex].mat_nr + 1 : 1; + + if (mat_nr != prev_mat_nr) { + setMaterial(mat_nr, NULL); /* XXX, no faceFlags no material */ + prev_mat_nr = mat_nr; + } + } + + if (setDrawOptions && (index != ORIGINDEX_NONE)) draw_option = setDrawOptions(userData, index); if (draw_option != DM_DRAW_OPTION_SKIP) { @@ -2744,15 +2735,15 @@ static void ccgDM_drawMappedEdges(DerivedMesh *dm, { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; CCGSubSurf *ss = ccgdm->ss; - CCGEdgeIterator *ei; + CCGEdgeIterator ei; CCGKey key; int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss); CCG_key_top_level(&key, ss); ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL); - for (ei = ccgSubSurf_getEdgeIterator(ss); !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) { - CCGEdge *e = ccgEdgeIterator_getCurrent(ei); + for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) { + CCGEdge *e = ccgEdgeIterator_getCurrent(&ei); CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e); int index = ccgDM_getEdgeMapIndex(ss, e); @@ -2770,8 +2761,6 @@ static void ccgDM_drawMappedEdges(DerivedMesh *dm, } glEnd(); } - - ccgEdgeIterator_free(ei); } static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm, @@ -2782,14 +2771,14 @@ static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm, CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; CCGSubSurf *ss = ccgdm->ss; CCGKey key; - CCGEdgeIterator *ei; + CCGEdgeIterator ei; int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss); CCG_key_top_level(&key, ss); ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL); - for (ei = ccgSubSurf_getEdgeIterator(ss); !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) { - CCGEdge *e = ccgEdgeIterator_getCurrent(ei); + for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) { + CCGEdge *e = ccgEdgeIterator_getCurrent(&ei); CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e); int index = ccgDM_getEdgeMapIndex(ss, e); @@ -2808,8 +2797,6 @@ static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm, } glEnd(); } - - ccgEdgeIterator_free(ei); } static void ccgDM_foreachMappedFaceCenter( @@ -2821,12 +2808,12 @@ static void ccgDM_foreachMappedFaceCenter( CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; CCGSubSurf *ss = ccgdm->ss; CCGKey key; - CCGFaceIterator *fi; + CCGFaceIterator fi; CCG_key_top_level(&key, ss); - for (fi = ccgSubSurf_getFaceIterator(ss); !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) { - CCGFace *f = ccgFaceIterator_getCurrent(fi); + for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) { + CCGFace *f = ccgFaceIterator_getCurrent(&fi); const int index = ccgDM_getFaceMapIndex(ss, f); if (index != -1) { @@ -2836,8 +2823,6 @@ static void ccgDM_foreachMappedFaceCenter( func(userData, index, CCG_elem_co(&key, vd), no); } } - - ccgFaceIterator_free(fi); } static void ccgDM_release(DerivedMesh *dm) @@ -3433,9 +3418,9 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, DerivedMesh *dm) { CCGDerivedMesh *ccgdm = MEM_callocN(sizeof(*ccgdm), "ccgdm"); - CCGVertIterator *vi; - CCGEdgeIterator *ei; - CCGFaceIterator *fi; + CCGVertIterator vi; + CCGEdgeIterator ei; + CCGFaceIterator fi; int index, totvert, totedge, totface; int i; int vertNum, edgeNum, faceNum; @@ -3568,30 +3553,27 @@ static CCGDerivedMesh *getCCGDerivedMesh(CCGSubSurf *ss, totvert = ccgSubSurf_getNumVerts(ss); ccgdm->vertMap = MEM_mallocN(totvert * sizeof(*ccgdm->vertMap), "vertMap"); - for (vi = ccgSubSurf_getVertIterator(ss); !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) { - CCGVert *v = ccgVertIterator_getCurrent(vi); + for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) { + CCGVert *v = ccgVertIterator_getCurrent(&vi); ccgdm->vertMap[GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v))].vert = v; } - ccgVertIterator_free(vi); totedge = ccgSubSurf_getNumEdges(ss); ccgdm->edgeMap = MEM_mallocN(totedge * sizeof(*ccgdm->edgeMap), "edgeMap"); - for (ei = ccgSubSurf_getEdgeIterator(ss); !ccgEdgeIterator_isStopped(ei); ccgEdgeIterator_next(ei)) { - CCGEdge *e = ccgEdgeIterator_getCurrent(ei); + for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) { + CCGEdge *e = ccgEdgeIterator_getCurrent(&ei); ccgdm->edgeMap[GET_INT_FROM_POINTER(ccgSubSurf_getEdgeEdgeHandle(e))].edge = e; } - ccgEdgeIterator_free(ei); totface = ccgSubSurf_getNumFaces(ss); ccgdm->faceMap = MEM_mallocN(totface * sizeof(*ccgdm->faceMap), "faceMap"); - for (fi = ccgSubSurf_getFaceIterator(ss); !ccgFaceIterator_isStopped(fi); ccgFaceIterator_next(fi)) { - CCGFace *f = ccgFaceIterator_getCurrent(fi); + for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) { + CCGFace *f = ccgFaceIterator_getCurrent(&fi); ccgdm->faceMap[GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f))].face = f; } - ccgFaceIterator_free(fi); ccgdm->reverseFaceMap = MEM_callocN(sizeof(int) * ccgSubSurf_getNumFinalFaces(ss), "reverseFaceMap"); @@ -3996,13 +3978,13 @@ void subsurf_calculate_limit_positions(Mesh *me, float (*r_positions)[3]) */ CCGSubSurf *ss = _getSubSurf(NULL, 1, 3, CCG_USE_ARENA); float edge_sum[3], face_sum[3]; - CCGVertIterator *vi; + CCGVertIterator vi; DerivedMesh *dm = CDDM_from_mesh(me); ss_sync_from_derivedmesh(ss, dm, NULL, 0); - for (vi = ccgSubSurf_getVertIterator(ss); !ccgVertIterator_isStopped(vi); ccgVertIterator_next(vi)) { - CCGVert *v = ccgVertIterator_getCurrent(vi); + for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) { + CCGVert *v = ccgVertIterator_getCurrent(&vi); int idx = GET_INT_FROM_POINTER(ccgSubSurf_getVertVertHandle(v)); int N = ccgSubSurf_getVertNumEdges(v); int numFaces = ccgSubSurf_getVertNumFaces(v); @@ -4031,7 +4013,6 @@ void subsurf_calculate_limit_positions(Mesh *me, float (*r_positions)[3]) r_positions[idx][1] = (co[1] * N * N + edge_sum[1] * 4 + face_sum[1]) / (N * (N + 5)); r_positions[idx][2] = (co[2] * N * N + edge_sum[2] * 4 + face_sum[2]) / (N * (N + 5)); } - ccgVertIterator_free(vi); ccgSubSurf_free(ss); diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 8a272cd9d81..77629715edb 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -369,8 +369,8 @@ int BKE_text_reload(Text *text) buffer = MEM_mallocN(len, "text_buffer"); - // under windows fread can return less then len bytes because - // of CR stripping + /* under windows fread can return less than len bytes because + * of CR stripping */ len = fread(buffer, 1, len, fp); fclose(fp); @@ -425,8 +425,8 @@ Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const fseek(fp, 0L, SEEK_SET); buffer = MEM_mallocN(len, "text_buffer"); - // under windows fread can return less then len bytes because - // of CR stripping + /* under windows fread can return less than len bytes because + * of CR stripping */ len = fread(buffer, 1, len, fp); fclose(fp); @@ -1515,7 +1515,7 @@ static bool max_undo_test(Text *text, int x) /* XXX error("Undo limit reached, buffer cleared\n"); */ MEM_freeN(text->undo_buf); init_undo_text(text); - return 0; + return false; } else { void *tmp = text->undo_buf; @@ -1526,7 +1526,7 @@ static bool max_undo_test(Text *text, int x) } } - return 1; + return true; } #if 0 /* UNUSED */ @@ -2474,6 +2474,7 @@ void txt_delete_word(Text *text) { txt_jump_right(text, true, true); txt_delete_sel(text); + txt_make_dirty(text); } void txt_backspace_char(Text *text) @@ -2522,6 +2523,7 @@ void txt_backspace_word(Text *text) { txt_jump_left(text, true, true); txt_delete_sel(text); + txt_make_dirty(text); } /* Max spaces to replace a tab with, currently hardcoded to TXT_TABSIZE = 4. @@ -2548,13 +2550,13 @@ static bool txt_add_char_intern(Text *text, unsigned int add, bool replace_tabs) if (add == '\n') { txt_split_curline(text); - return 1; + return true; } /* insert spaces rather than tabs */ if (add == '\t' && replace_tabs) { txt_convert_tab_to_spaces(text); - return 1; + return true; } txt_delete_sel(text); @@ -2603,7 +2605,7 @@ bool txt_replace_char(Text *text, unsigned int add) size_t del_size = 0, add_size; char ch[BLI_UTF8_MAX]; - if (!text->curl) return 0; + if (!text->curl) return false; /* If text is selected or we're at the end of the line just use txt_add_char */ if (text->curc == text->curl->len || txt_has_sel(text) || add == '\n') { @@ -2642,7 +2644,7 @@ bool txt_replace_char(Text *text, unsigned int add) text->curc += add_size; txt_pop_sel(text); } - return 1; + return true; } void txt_indent(Text *text) @@ -2977,37 +2979,37 @@ bool text_check_delim(const char ch) for (a = 0; a < (sizeof(delims) - 1); a++) { if (ch == delims[a]) - return 1; + return true; } - return 0; + return false; } bool text_check_digit(const char ch) { - if (ch < '0') return 0; - if (ch <= '9') return 1; - return 0; + if (ch < '0') return false; + if (ch <= '9') return true; + return false; } bool text_check_identifier(const char ch) { - if (ch < '0') return 0; - if (ch <= '9') return 1; - if (ch < 'A') return 0; - if (ch <= 'Z' || ch == '_') return 1; - if (ch < 'a') return 0; - if (ch <= 'z') return 1; - return 0; + if (ch < '0') return false; + if (ch <= '9') return true; + if (ch < 'A') return false; + if (ch <= 'Z' || ch == '_') return true; + if (ch < 'a') return false; + if (ch <= 'z') return true; + return false; } bool text_check_identifier_nodigit(const char ch) { - if (ch <= '9') return 0; - if (ch < 'A') return 0; - if (ch <= 'Z' || ch == '_') return 1; - if (ch < 'a') return 0; - if (ch <= 'z') return 1; - return 0; + if (ch <= '9') return false; + if (ch < 'A') return false; + if (ch <= 'Z' || ch == '_') return true; + if (ch < 'a') return false; + if (ch <= 'z') return true; + return false; } #ifndef WITH_PYTHON @@ -3025,8 +3027,8 @@ int text_check_identifier_nodigit_unicode(const unsigned int ch) bool text_check_whitespace(const char ch) { if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') - return 1; - return 0; + return true; + return false; } int text_find_identifier_start(const char *str, int i) diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c index f938ed08142..3c02d5c19fc 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -37,7 +37,6 @@ #include "MEM_guardedalloc.h" -#include "BLI_blenlib.h" #include "BLI_math.h" #include "BLI_kdopbvh.h" #include "BLI_utildefines.h" @@ -328,7 +327,7 @@ bool do_colorband(const ColorBand *coba, float in, float out[4]) int ipotype; int a; - if (coba == NULL || coba->tot == 0) return 0; + if (coba == NULL || coba->tot == 0) return false; cbd1 = coba->data; @@ -464,7 +463,7 @@ bool do_colorband(const ColorBand *coba, float in, float out[4]) } } } - return 1; /* OK */ + return true; /* OK */ } void colorband_table_RGBA(ColorBand *coba, float **array, int *size) @@ -1302,7 +1301,7 @@ bool has_current_material_texture(Material *ma) node = nodeGetActiveID(ma->nodetree, ID_TE); if (node) - return 1; + return true; } return (ma != NULL); @@ -1596,17 +1595,17 @@ void BKE_free_oceantex(struct OceanTex *ot) bool BKE_texture_dependsOnTime(const struct Tex *texture) { if (texture->ima && BKE_image_is_animated(texture->ima)) { - return 1; + return true; } else if (texture->adt) { /* assume anything in adt means the texture is animated */ - return 1; + return true; } else if (texture->type == TEX_NOISE) { /* noise always varies with time */ - return 1; + return true; } - return 0; + return false; } /* ------------------------------------------------------------------------- */ diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index 40d9dc0d7e0..d580c184a8b 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -1456,6 +1456,35 @@ MovieTrackingPlaneMarker *BKE_tracking_plane_marker_ensure(MovieTrackingPlaneTra return plane_marker; } +void BKE_tracking_plane_marker_get_subframe_corners(MovieTrackingPlaneTrack *plane_track, + float framenr, + float corners[4][2]) +{ + MovieTrackingPlaneMarker *marker = BKE_tracking_plane_marker_get(plane_track, (int)framenr); + MovieTrackingPlaneMarker *marker_last = plane_track->markers + (plane_track->markersnr - 1); + int i; + if (marker != marker_last) { + MovieTrackingPlaneMarker *marker_next = marker + 1; + if (marker_next->framenr == marker->framenr + 1) { + float fac = (framenr - (int) framenr) / (marker_next->framenr - marker->framenr); + for (i = 0; i < 4; ++i) { + interp_v2_v2v2(corners[i], marker->corners[i], + marker_next->corners[i], fac); + } + } + else { + for (i = 0; i < 4; ++i) { + copy_v2_v2(corners[i], marker->corners[i]); + } + } + } + else { + for (i = 0; i < 4; ++i) { + copy_v2_v2(corners[i], marker->corners[i]); + } + } +} + /*********************** Object *************************/ MovieTrackingObject *BKE_tracking_object_add(MovieTracking *tracking, const char *name) @@ -1475,7 +1504,7 @@ MovieTrackingObject *BKE_tracking_object_add(MovieTracking *tracking, const char BLI_addtail(&tracking->objects, object); tracking->tot_object++; - tracking->objectnr = BLI_countlist(&tracking->objects) - 1; + tracking->objectnr = BLI_listbase_count(&tracking->objects) - 1; object->scale = 1.0f; object->keyframe1 = 1; @@ -2410,30 +2439,30 @@ static void tracking_dopesheet_channels_sort(MovieTracking *tracking, int sort_m if (inverse) { if (sort_method == TRACKING_DOPE_SORT_NAME) { - BLI_sortlist(&dopesheet->channels, channels_alpha_inverse_sort); + BLI_listbase_sort(&dopesheet->channels, channels_alpha_inverse_sort); } else if (sort_method == TRACKING_DOPE_SORT_LONGEST) { - BLI_sortlist(&dopesheet->channels, channels_longest_segment_inverse_sort); + BLI_listbase_sort(&dopesheet->channels, channels_longest_segment_inverse_sort); } else if (sort_method == TRACKING_DOPE_SORT_TOTAL) { - BLI_sortlist(&dopesheet->channels, channels_total_track_inverse_sort); + BLI_listbase_sort(&dopesheet->channels, channels_total_track_inverse_sort); } else if (sort_method == TRACKING_DOPE_SORT_AVERAGE_ERROR) { - BLI_sortlist(&dopesheet->channels, channels_average_error_inverse_sort); + BLI_listbase_sort(&dopesheet->channels, channels_average_error_inverse_sort); } } else { if (sort_method == TRACKING_DOPE_SORT_NAME) { - BLI_sortlist(&dopesheet->channels, channels_alpha_sort); + BLI_listbase_sort(&dopesheet->channels, channels_alpha_sort); } else if (sort_method == TRACKING_DOPE_SORT_LONGEST) { - BLI_sortlist(&dopesheet->channels, channels_longest_segment_sort); + BLI_listbase_sort(&dopesheet->channels, channels_longest_segment_sort); } else if (sort_method == TRACKING_DOPE_SORT_TOTAL) { - BLI_sortlist(&dopesheet->channels, channels_total_track_sort); + BLI_listbase_sort(&dopesheet->channels, channels_total_track_sort); } else if (sort_method == TRACKING_DOPE_SORT_AVERAGE_ERROR) { - BLI_sortlist(&dopesheet->channels, channels_average_error_sort); + BLI_listbase_sort(&dopesheet->channels, channels_average_error_sort); } } } diff --git a/source/blender/blenkernel/intern/tracking_auto.c b/source/blender/blenkernel/intern/tracking_auto.c new file mode 100644 index 00000000000..22a380ea835 --- /dev/null +++ b/source/blender/blenkernel/intern/tracking_auto.c @@ -0,0 +1,568 @@ +/* + * ***** 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) 2011 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation, + * Sergey Sharybin + * Keir Mierle + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/tracking_auto.c + * \ingroup bke + */ + +#include <stdlib.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_movieclip_types.h" +#include "DNA_object_types.h" /* SELECT */ + +#include "BLI_threads.h" +#include "BLI_utildefines.h" +#include "BLI_math.h" + +#include "BKE_movieclip.h" +#include "BKE_tracking.h" + +#include "libmv-capi.h" +#include "tracking_private.h" + +typedef struct AutoTrackOptions { + int clip_index; /** Index of the clip this track belogs to. */ + int track_index; /* Index of the track in AutoTrack tracks structure. */ + MovieTrackingTrack *track; /* Pointer to an original track/ */ + libmv_TrackRegionOptions track_region_options; /* Options for the region + tracker. */ + bool use_keyframe_match; /* Keyframe pattern matching. */ + + /* TODO(sergey): A bit awkward to keep it in here, only used to + * place a disabled marker once the tracking fails, + * Wither find a more clear way to do it or call it track context + * or state, not options. + */ + bool is_failed; + int failed_frame; +} AutoTrackOptions; + +typedef struct AutoTrackContext { + MovieClip *clips[MAX_ACCESSOR_CLIP]; + int num_clips; + + MovieClipUser user; + int frame_width, frame_height; + + struct libmv_AutoTrack *autotrack; + TrackingImageAccessor *image_accessor; + + int num_tracks; /* Number of tracks being tracked. */ + AutoTrackOptions *options; /* Per-tracking track options. */ + + bool backwards; + bool sequence; + int first_frame; + int sync_frame; + bool first_sync; + SpinLock spin_lock; +} AutoTrackContext; + +static void normalized_to_libmv_frame(const float normalized[2], + const int frame_dimensions[2], + float result[2]) +{ + result[0] = normalized[0] * frame_dimensions[0] - 0.5f; + result[1] = normalized[1] * frame_dimensions[1] - 0.5f; +} + +static void normalized_relative_to_libmv_frame(const float normalized[2], + const float origin[2], + const int frame_dimensions[2], + float result[2]) +{ + result[0] = (normalized[0] + origin[0]) * frame_dimensions[0] - 0.5f; + result[1] = (normalized[1] + origin[1]) * frame_dimensions[1] - 0.5f; +} + +static void libmv_frame_to_normalized(const float frame_coord[2], + const int frame_dimensions[2], + float result[2]) +{ + result[0] = (frame_coord[0] + 0.5f) / frame_dimensions[0]; + result[1] = (frame_coord[1] + 0.5f) / frame_dimensions[1]; +} + +static void libmv_frame_to_normalized_relative(const float frame_coord[2], + const float origin[2], + const int frame_dimensions[2], + float result[2]) +{ + result[0] = (frame_coord[0] - origin[0]) / frame_dimensions[0]; + result[1] = (frame_coord[1] - origin[1]) / frame_dimensions[1]; +} + +static void dna_marker_to_libmv_marker(/*const*/ MovieTrackingTrack *track, + /*const*/ MovieTrackingMarker *marker, + int clip, + int track_index, + int frame_width, + int frame_height, + bool backwards, + libmv_Marker *libmv_marker) +{ + const int frame_dimensions[2] = {frame_width, frame_height}; + int i; + libmv_marker->clip = clip; + libmv_marker->frame = marker->framenr; + libmv_marker->track = track_index; + + normalized_to_libmv_frame(marker->pos, + frame_dimensions, + libmv_marker->center); + for (i = 0; i < 4; ++i) { + normalized_relative_to_libmv_frame(marker->pattern_corners[i], + marker->pos, + frame_dimensions, + libmv_marker->patch[i]); + } + + normalized_relative_to_libmv_frame(marker->search_min, + marker->pos, + frame_dimensions, + libmv_marker->search_region_min); + + normalized_relative_to_libmv_frame(marker->search_max, + marker->pos, + frame_dimensions, + libmv_marker->search_region_max); + + /* TODO(sergey): All the markers does have 1.0 weight. */ + libmv_marker->weight = 1.0f; + + if (marker->flag & MARKER_TRACKED) { + libmv_marker->source = LIBMV_MARKER_SOURCE_TRACKED; + } + else { + libmv_marker->source = LIBMV_MARKER_SOURCE_MANUAL; + } + libmv_marker->status = LIBMV_MARKER_STATUS_UNKNOWN; + libmv_marker->model_type = LIBMV_MARKER_MODEL_TYPE_POINT; + libmv_marker->model_id = 0; + + /* TODO(sergey): We currently don't support reference marker from + * different clip. + */ + libmv_marker->reference_clip = clip; + + if (track->pattern_match == TRACK_MATCH_KEYFRAME) { + MovieTrackingMarker *keyframe_marker = + tracking_get_keyframed_marker(track, + marker->framenr, + backwards); + libmv_marker->reference_frame = keyframe_marker->framenr; + } + else { + libmv_marker->reference_frame = backwards ? + marker->framenr - 1 : + marker->framenr; + } + + libmv_marker->disabled_channels = + ((track->flag & TRACK_DISABLE_RED) ? LIBMV_MARKER_CHANNEL_R : 0) | + ((track->flag & TRACK_DISABLE_GREEN) ? LIBMV_MARKER_CHANNEL_G : 0) | + ((track->flag & TRACK_DISABLE_BLUE) ? LIBMV_MARKER_CHANNEL_B : 0); +} + +static void libmv_marker_to_dna_marker(libmv_Marker *libmv_marker, + int frame_width, + int frame_height, + MovieTrackingMarker *marker) +{ + const int frame_dimensions[2] = {frame_width, frame_height}; + int i; + marker->framenr = libmv_marker->frame; + + libmv_frame_to_normalized(libmv_marker->center, + frame_dimensions, + marker->pos); + for (i = 0; i < 4; ++i) { + libmv_frame_to_normalized_relative(libmv_marker->patch[i], + libmv_marker->center, + frame_dimensions, + marker->pattern_corners[i]); + } + + libmv_frame_to_normalized_relative(libmv_marker->search_region_min, + libmv_marker->center, + frame_dimensions, + marker->search_min); + + libmv_frame_to_normalized_relative(libmv_marker->search_region_max, + libmv_marker->center, + frame_dimensions, + marker->search_max); + + marker->flag = 0; + if (libmv_marker->source == LIBMV_MARKER_SOURCE_TRACKED) { + marker->flag |= MARKER_TRACKED; + } + else { + marker->flag &= ~MARKER_TRACKED; + } +} + +static bool check_track_trackable(MovieClip *clip, + MovieTrackingTrack *track, + MovieClipUser *user) +{ + if (TRACK_SELECTED(track) && + (track->flag & (TRACK_LOCKED | TRACK_HIDDEN)) == 0) + { + MovieTrackingMarker *marker; + int frame; + frame = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr); + marker = BKE_tracking_marker_get(track, frame); + return (marker->flag & MARKER_DISABLED) == 0; + } + return false; +} + +/* Returns false if marker crossed margin area from frame bounds. */ +static bool tracking_check_marker_margin(libmv_Marker *libmv_marker, + int margin, + int frame_width, + int frame_height) +{ + float patch_min[2], patch_max[2]; + float margin_left, margin_top, margin_right, margin_bottom; + + INIT_MINMAX2(patch_min, patch_max); + minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[0]); + minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[1]); + minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[2]); + minmax_v2v2_v2(patch_min, patch_max, libmv_marker->patch[3]); + + margin_left = max_ff(libmv_marker->center[0] - patch_min[0], margin); + margin_top = max_ff(patch_max[1] - libmv_marker->center[1], margin); + margin_right = max_ff(patch_max[0] - libmv_marker->center[0], margin); + margin_bottom = max_ff(libmv_marker->center[1] - patch_min[1], margin); + + if (libmv_marker->center[0] < margin_left || + libmv_marker->center[0] > frame_width - margin_right || + libmv_marker->center[1] < margin_bottom || + libmv_marker->center[1] > frame_height - margin_top) + { + return false; + } + + return true; +} + +AutoTrackContext *BKE_autotrack_context_new(MovieClip *clip, + MovieClipUser *user, + const bool backwards, + const bool sequence) +{ + AutoTrackContext *context = MEM_callocN(sizeof(AutoTrackContext), + "autotrack context"); + MovieTracking *tracking = &clip->tracking; + MovieTrackingTrack *track; + ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking); + int i, track_index, frame_width, frame_height; + + BKE_movieclip_get_size(clip, user, &frame_width, &frame_height); + + /* TODO(sergey): Currently using only a single clip. */ + context->clips[0] = clip; + context->num_clips = 1; + + context->user = *user; + context->user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL; + context->user.render_flag = 0; + context->frame_width = frame_width; + context->frame_height = frame_height; + context->backwards = backwards; + context->sequence = sequence; + context->first_frame = user->framenr; + context->sync_frame = user->framenr; + context->first_sync = true; + + BLI_spin_init(&context->spin_lock); + + context->image_accessor = + tracking_image_accessor_new(context->clips, 1, user->framenr); + context->autotrack = + libmv_autoTrackNew(context->image_accessor->libmv_accessor); + + /* Fill in Autotrack with all markers we know. */ + track_index = 0; + for (track = tracksbase->first; + track; + track = track->next) + { + if (check_track_trackable(clip, track, user)) { + context->num_tracks++; + } + + for (i = 0; i < track->markersnr; ++i) { + MovieTrackingMarker *marker = track->markers + i; + if ((marker->flag & MARKER_DISABLED) == 0) { + libmv_Marker libmv_marker; + dna_marker_to_libmv_marker(track, + marker, + 0, + track_index, + frame_width, + frame_height, + backwards, + &libmv_marker); + libmv_autoTrackAddMarker(context->autotrack, + &libmv_marker); + } + } + track_index++; + } + + /* Create per-track tracking options. */ + context->options = + MEM_callocN(sizeof(AutoTrackOptions) * context->num_tracks, + "auto track options"); + i = track_index = 0; + for (track = tracksbase->first; + track; + track = track->next) + { + if (check_track_trackable(clip, track, user)) { + AutoTrackOptions *options = &context->options[i++]; + /* TODO(sergey): Single clip only for now. */ + options->clip_index = 0; + options->track_index = track_index; + options->track = track; + tracking_configure_tracker(track, + NULL, + &options->track_region_options); + options->use_keyframe_match = + track->pattern_match == TRACK_MATCH_KEYFRAME; + } + ++track_index; + } + + return context; +} + +bool BKE_autotrack_context_step(AutoTrackContext *context) +{ + int frame_delta = context->backwards ? -1 : 1; + bool ok = false; + int track; + +#pragma omp parallel for if(context->num_tracks > 1) + for (track = 0; track < context->num_tracks; ++track) { + AutoTrackOptions *options = &context->options[track]; + libmv_Marker libmv_current_marker, + libmv_reference_marker, + libmv_tracked_marker; + libmv_TrackRegionResult libmv_result; + int frame = BKE_movieclip_remap_scene_to_clip_frame( + context->clips[options->clip_index], + context->user.framenr); + bool has_marker; + + BLI_spin_lock(&context->spin_lock); + has_marker = libmv_autoTrackGetMarker(context->autotrack, + options->clip_index, + frame, + options->track_index, + &libmv_current_marker); + BLI_spin_unlock(&context->spin_lock); + + if (has_marker) { + if (!tracking_check_marker_margin(&libmv_current_marker, + options->track->margin, + context->frame_width, + context->frame_height)) + { + continue; + } + + libmv_tracked_marker = libmv_current_marker; + libmv_tracked_marker.frame = frame + frame_delta; + + if (options->use_keyframe_match) { + libmv_tracked_marker.reference_frame = + libmv_current_marker.reference_frame; + libmv_autoTrackGetMarker(context->autotrack, + options->clip_index, + libmv_tracked_marker.reference_frame, + options->track_index, + &libmv_reference_marker); + } + else { + libmv_tracked_marker.reference_frame = frame; + libmv_reference_marker = libmv_current_marker; + } + + if (libmv_autoTrackMarker(context->autotrack, + &options->track_region_options, + &libmv_tracked_marker, + &libmv_result)) + { + BLI_spin_lock(&context->spin_lock); + libmv_autoTrackAddMarker(context->autotrack, + &libmv_tracked_marker); + BLI_spin_unlock(&context->spin_lock); + } + else { + options->is_failed = true; + options->failed_frame = frame + frame_delta; + } + ok = true; + } + } + + BLI_spin_lock(&context->spin_lock); + context->user.framenr += frame_delta; + BLI_spin_unlock(&context->spin_lock); + + return ok; +} + +void BKE_autotrack_context_sync(AutoTrackContext *context) +{ + int newframe, frame_delta = context->backwards ? -1 : 1; + int clip, frame; + + BLI_spin_lock(&context->spin_lock); + newframe = context->user.framenr; + for (frame = context->sync_frame; + frame != (context->backwards ? newframe - 1 : newframe + 1); + frame += frame_delta) + { + MovieTrackingMarker marker; + libmv_Marker libmv_marker; + int clip = 0; + int track; + for (track = 0; track < context->num_tracks; ++track) { + 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); + continue; + } + } + if (libmv_autoTrackGetMarker(context->autotrack, + clip, + track_frame, + options->track_index, + &libmv_marker)) + { + libmv_marker_to_dna_marker(&libmv_marker, + context->frame_width, + context->frame_height, + &marker); + if (context->first_sync && frame == context->sync_frame) { + tracking_marker_insert_disabled(options->track, + &marker, + !context->backwards, + false); + } + BKE_tracking_marker_insert(options->track, &marker); + tracking_marker_insert_disabled(options->track, + &marker, + context->backwards, + false); + } + } + } + BLI_spin_unlock(&context->spin_lock); + + for (clip = 0; clip < context->num_clips; ++clip) { + MovieTracking *tracking = &context->clips[clip]->tracking; + BKE_tracking_dopesheet_tag_update(tracking); + } + + context->sync_frame = newframe; + context->first_sync = false; +} + +void BKE_autotrack_context_sync_user(AutoTrackContext *context, + MovieClipUser *user) +{ + user->framenr = context->sync_frame; +} + +void BKE_autotrack_context_finish(AutoTrackContext *context) +{ + int clip_index; + + for (clip_index = 0; clip_index < context->num_clips; ++clip_index) { + MovieClip *clip = context->clips[clip_index]; + ListBase *plane_tracks_base = + BKE_tracking_get_active_plane_tracks(&clip->tracking); + MovieTrackingPlaneTrack *plane_track; + + for (plane_track = plane_tracks_base->first; + plane_track; + plane_track = plane_track->next) + { + if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) { + int track; + for (track = 0; track < context->num_tracks; ++track) { + MovieTrackingTrack *old_track; + bool do_update = false; + int j; + + old_track = context->options[track].track; + for (j = 0; j < plane_track->point_tracksnr; j++) { + if (plane_track->point_tracks[j] == old_track) { + do_update = true; + break; + } + } + + if (do_update) { + BKE_tracking_track_plane_from_existing_motion( + plane_track, + context->first_frame); + break; + } + } + } + } + } +} + +void BKE_autotrack_context_free(AutoTrackContext *context) +{ + libmv_autoTrackDestroy(context->autotrack); + tracking_image_accessor_destroy(context->image_accessor); + MEM_freeN(context->options); + BLI_spin_end(&context->spin_lock); + MEM_freeN(context); +} diff --git a/source/blender/blenkernel/intern/tracking_detect.c b/source/blender/blenkernel/intern/tracking_detect.c index 62039b761e8..6df51b5441a 100644 --- a/source/blender/blenkernel/intern/tracking_detect.c +++ b/source/blender/blenkernel/intern/tracking_detect.c @@ -40,7 +40,6 @@ #include "BKE_tracking.h" #include "IMB_imbuf_types.h" -#include "IMB_imbuf.h" #include "libmv-capi.h" diff --git a/source/blender/blenkernel/intern/tracking_region_tracker.c b/source/blender/blenkernel/intern/tracking_region_tracker.c index c41106f37cb..dd7def16ca8 100644 --- a/source/blender/blenkernel/intern/tracking_region_tracker.c +++ b/source/blender/blenkernel/intern/tracking_region_tracker.c @@ -35,11 +35,8 @@ #include "MEM_guardedalloc.h" #include "DNA_movieclip_types.h" -#include "DNA_object_types.h" /* SELECT */ #include "BLI_utildefines.h" -#include "BLI_math.h" -#include "BLI_ghash.h" #include "BLI_threads.h" #include "BKE_tracking.h" @@ -51,170 +48,6 @@ #include "libmv-capi.h" #include "tracking_private.h" -typedef struct TrackContext { - /* the reference marker and cutout search area */ - MovieTrackingMarker reference_marker; - - /* keyframed patch. This is the search area */ - float *search_area; - int search_area_height; - int search_area_width; - int framenr; - - float *mask; -} TrackContext; - -typedef struct MovieTrackingContext { - MovieClipUser user; - MovieClip *clip; - int clip_flag; - - int frames, first_frame; - bool first_time; - - MovieTrackingSettings settings; - TracksMap *tracks_map; - - bool backwards, sequence; - int sync_frame; -} MovieTrackingContext; - -static void track_context_free(void *customdata) -{ - TrackContext *track_context = (TrackContext *)customdata; - - if (track_context->search_area) - MEM_freeN(track_context->search_area); - - if (track_context->mask) - MEM_freeN(track_context->mask); -} - -/* Create context for motion 2D tracking, copies all data needed - * for thread-safe tracking, allowing clip modifications during - * tracking. - */ -MovieTrackingContext *BKE_tracking_context_new(MovieClip *clip, MovieClipUser *user, - const bool backwards, const bool sequence) -{ - MovieTrackingContext *context = MEM_callocN(sizeof(MovieTrackingContext), "trackingContext"); - MovieTracking *tracking = &clip->tracking; - MovieTrackingSettings *settings = &tracking->settings; - ListBase *tracksbase = BKE_tracking_get_active_tracks(tracking); - MovieTrackingTrack *track; - MovieTrackingObject *object = BKE_tracking_object_get_active(tracking); - int num_tracks = 0; - - context->clip = clip; - context->settings = *settings; - context->backwards = backwards; - context->sync_frame = user->framenr; - context->first_time = true; - context->first_frame = user->framenr; - context->sequence = sequence; - - /* count */ - track = tracksbase->first; - while (track) { - if (TRACK_SELECTED(track) && (track->flag & (TRACK_LOCKED | TRACK_HIDDEN)) == 0) { - int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr); - MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); - - if ((marker->flag & MARKER_DISABLED) == 0) - num_tracks++; - } - - track = track->next; - } - - /* create tracking contextx for all tracks which would be tracked */ - if (num_tracks) { - int width, height; - - context->tracks_map = tracks_map_new(object->name, object->flag & TRACKING_OBJECT_CAMERA, - num_tracks, sizeof(TrackContext)); - - BKE_movieclip_get_size(clip, user, &width, &height); - - /* create tracking data */ - track = tracksbase->first; - while (track) { - if (TRACK_SELECTED(track) && (track->flag & (TRACK_HIDDEN | TRACK_LOCKED)) == 0) { - int framenr = BKE_movieclip_remap_scene_to_clip_frame(clip, user->framenr); - MovieTrackingMarker *marker = BKE_tracking_marker_get(track, framenr); - - if ((marker->flag & MARKER_DISABLED) == 0) { - TrackContext track_context; - memset(&track_context, 0, sizeof(TrackContext)); - tracks_map_insert(context->tracks_map, track, &track_context); - } - } - - track = track->next; - } - } - - /* store needed clip flags passing to get_buffer functions - * - MCLIP_USE_PROXY is needed to because timecode affects on movie clip - * only in case Proxy/Timecode flag is set, so store this flag to use - * timecodes properly but reset render size to SIZE_FULL so correct resolution - * would be used for images - * - MCLIP_USE_PROXY_CUSTOM_DIR is needed because proxy/timecode files might - * be stored in a different location - * ignore all the rest possible flags for now - */ - context->clip_flag = clip->flag & MCLIP_TIMECODE_FLAGS; - - context->user = *user; - context->user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL; - context->user.render_flag = 0; - - if (!sequence) - BLI_begin_threaded_malloc(); - - return context; -} - -/* Free context used for tracking. */ -void BKE_tracking_context_free(MovieTrackingContext *context) -{ - if (!context->sequence) - BLI_end_threaded_malloc(); - - tracks_map_free(context->tracks_map, track_context_free); - - MEM_freeN(context); -} - -/* Synchronize tracks between clip editor and tracking context, - * by merging them together so all new created tracks and tracked - * ones presents in the movie clip. - */ -void BKE_tracking_context_sync(MovieTrackingContext *context) -{ - MovieTracking *tracking = &context->clip->tracking; - int newframe; - - tracks_map_merge(context->tracks_map, tracking); - - if (context->backwards) - newframe = context->user.framenr + 1; - else - newframe = context->user.framenr - 1; - - context->sync_frame = newframe; - - BKE_tracking_dopesheet_tag_update(tracking); -} - -/* Synchronize clip user's frame number with a frame number from tracking context, - * used to update current frame displayed in the clip editor while tracking. - */ -void BKE_tracking_context_sync_user(const MovieTrackingContext *context, MovieClipUser *user) -{ - user->framenr = context->sync_frame; -} - /* **** utility functions for tracking **** */ /* convert from float and byte RGBA to grayscale. Supports different coefficients for RGB. */ @@ -280,7 +113,7 @@ static float *track_get_search_floatbuf(ImBuf *ibuf, MovieTrackingTrack *track, return gray_pixels; } -/* Get image boffer for a given frame +/* Get image buffer for a given frame * * Frame is in clip space. */ @@ -296,51 +129,6 @@ static ImBuf *tracking_context_get_frame_ibuf(MovieClip *clip, MovieClipUser *us return ibuf; } -/* Get previous keyframed marker. */ -static MovieTrackingMarker *tracking_context_get_keyframed_marker(MovieTrackingTrack *track, - int curfra, bool backwards) -{ - MovieTrackingMarker *marker_keyed = NULL; - MovieTrackingMarker *marker_keyed_fallback = NULL; - int a = BKE_tracking_marker_get(track, curfra) - track->markers; - - while (a >= 0 && a < track->markersnr) { - int next = backwards ? a + 1 : a - 1; - bool is_keyframed = false; - MovieTrackingMarker *cur_marker = &track->markers[a]; - MovieTrackingMarker *next_marker = NULL; - - if (next >= 0 && next < track->markersnr) - next_marker = &track->markers[next]; - - if ((cur_marker->flag & MARKER_DISABLED) == 0) { - /* If it'll happen so we didn't find a real keyframe marker, - * fallback to the first marker in current tracked segment - * as a keyframe. - */ - if (next_marker && next_marker->flag & MARKER_DISABLED) { - if (marker_keyed_fallback == NULL) - marker_keyed_fallback = cur_marker; - } - - is_keyframed |= (cur_marker->flag & MARKER_TRACKED) == 0; - } - - if (is_keyframed) { - marker_keyed = cur_marker; - - break; - } - - a = next; - } - - if (marker_keyed == NULL) - marker_keyed = marker_keyed_fallback; - - return marker_keyed; -} - /* Get image buffer for previous marker's keyframe. */ static ImBuf *tracking_context_get_keyframed_ibuf(MovieClip *clip, MovieClipUser *user, int clip_flag, MovieTrackingTrack *track, int curfra, bool backwards, @@ -349,7 +137,7 @@ static ImBuf *tracking_context_get_keyframed_ibuf(MovieClip *clip, MovieClipUser MovieTrackingMarker *marker_keyed; int keyed_framenr; - marker_keyed = tracking_context_get_keyframed_marker(track, curfra, backwards); + marker_keyed = tracking_get_keyframed_marker(track, curfra, backwards); if (marker_keyed == NULL) { return NULL; } @@ -381,50 +169,9 @@ static ImBuf *tracking_context_get_reference_ibuf(MovieClip *clip, MovieClipUser return ibuf; } -/* Update track's reference patch (patch from which track is tracking from) - * - * Returns false if reference image buffer failed to load. - */ -static bool track_context_update_reference(MovieTrackingContext *context, TrackContext *track_context, - MovieTrackingTrack *track, MovieTrackingMarker *marker, int curfra, - int frame_width, int frame_height) -{ - MovieTrackingMarker *reference_marker = NULL; - ImBuf *reference_ibuf = NULL; - int width, height; - - /* calculate patch for keyframed position */ - reference_ibuf = tracking_context_get_reference_ibuf(context->clip, &context->user, context->clip_flag, - track, curfra, context->backwards, &reference_marker); - - if (!reference_ibuf) - return false; - - track_context->reference_marker = *reference_marker; - - if (track_context->search_area) { - MEM_freeN(track_context->search_area); - } - - track_context->search_area = track_get_search_floatbuf(reference_ibuf, track, reference_marker, &width, &height); - track_context->search_area_height = height; - track_context->search_area_width = width; - - if ((track->algorithm_flag & TRACK_ALGORITHM_FLAG_USE_MASK) != 0) { - if (track_context->mask) - MEM_freeN(track_context->mask); - - track_context->mask = BKE_tracking_track_get_mask(frame_width, frame_height, track, marker); - } - - IMB_freeImBuf(reference_ibuf); - - return true; -} - /* Fill in libmv tracker options structure with settings need to be used to perform track. */ -static void tracking_configure_tracker(const MovieTrackingTrack *track, float *mask, - libmv_TrackRegionOptions *options) +void tracking_configure_tracker(const MovieTrackingTrack *track, float *mask, + libmv_TrackRegionOptions *options) { options->motion_model = track->motion_model; @@ -442,102 +189,6 @@ static void tracking_configure_tracker(const MovieTrackingTrack *track, float *m options->image1_mask = NULL; } -/* returns false if marker crossed margin area from frame bounds */ -static bool tracking_check_marker_margin(MovieTrackingTrack *track, MovieTrackingMarker *marker, - int frame_width, int frame_height) -{ - float pat_min[2], pat_max[2]; - float margin_left, margin_top, margin_right, margin_bottom; - float normalized_track_margin[2]; - - /* margin from frame boundaries */ - BKE_tracking_marker_pattern_minmax(marker, pat_min, pat_max); - - normalized_track_margin[0] = (float)track->margin / frame_width; - normalized_track_margin[1] = (float)track->margin / frame_height; - - margin_left = max_ff(-pat_min[0], normalized_track_margin[0]); - margin_top = max_ff( pat_max[1], normalized_track_margin[1]); - margin_right = max_ff( pat_max[0], normalized_track_margin[0]); - margin_bottom = max_ff(-pat_min[1], normalized_track_margin[1]); - - /* do not track markers which are too close to boundary */ - if (marker->pos[0] < margin_left || marker->pos[0] > 1.0f - margin_right || - marker->pos[1] < margin_bottom || marker->pos[1] > 1.0f - margin_top) - { - return false; - } - - return true; -} - -/* Scale search area of marker based on scale changes of pattern area, - * - * TODO(sergey): currently based on pattern bounding box scale change, - * smarter approach here is welcome. - */ -static void tracking_scale_marker_search(const MovieTrackingMarker *old_marker, MovieTrackingMarker *new_marker) -{ - float old_pat_min[2], old_pat_max[2]; - float new_pat_min[2], new_pat_max[2]; - float scale_x, scale_y; - - BKE_tracking_marker_pattern_minmax(old_marker, old_pat_min, old_pat_max); - BKE_tracking_marker_pattern_minmax(new_marker, new_pat_min, new_pat_max); - - scale_x = (new_pat_max[0] - new_pat_min[0]) / (old_pat_max[0] - old_pat_min[0]); - scale_y = (new_pat_max[1] - new_pat_min[1]) / (old_pat_max[1] - old_pat_min[1]); - - new_marker->search_min[0] *= scale_x; - new_marker->search_min[1] *= scale_y; - - new_marker->search_max[0] *= scale_x; - new_marker->search_max[1] *= scale_y; -} - -/* Insert new marker which was tracked from old_marker to a new image, - * will also ensure tracked segment is surrounded by disabled markers. - */ -static void tracking_insert_new_marker(MovieTrackingContext *context, MovieTrackingTrack *track, - const MovieTrackingMarker *old_marker, int curfra, bool tracked, - int frame_width, int frame_height, - const double dst_pixel_x[5], const double dst_pixel_y[5]) -{ - MovieTrackingMarker new_marker; - int frame_delta = context->backwards ? -1 : 1; - int nextfra = curfra + frame_delta; - - new_marker = *old_marker; - - if (tracked) { - tracking_set_marker_coords_from_tracking(frame_width, frame_height, &new_marker, dst_pixel_x, dst_pixel_y); - new_marker.flag |= MARKER_TRACKED; - new_marker.framenr = nextfra; - - tracking_scale_marker_search(old_marker, &new_marker); - - if (context->first_time) { - /* check if there's no keyframe/tracked markers before tracking marker. - * if so -- create disabled marker before currently tracking "segment" - */ - - tracking_marker_insert_disabled(track, old_marker, !context->backwards, false); - } - - /* insert currently tracked marker */ - BKE_tracking_marker_insert(track, &new_marker); - - /* make currently tracked segment be finished with disabled marker */ - tracking_marker_insert_disabled(track, &new_marker, context->backwards, false); - } - else { - new_marker.framenr = nextfra; - new_marker.flag |= MARKER_DISABLED; - - BKE_tracking_marker_insert(track, &new_marker); - } -} - /* Peform tracking from a reference_marker to destination_ibuf. * Uses marker as an initial position guess. * @@ -601,130 +252,6 @@ static bool configure_and_run_tracker(ImBuf *destination_ibuf, MovieTrackingTrac return tracked; } -/* Track all the tracks from context one more frame, - * returns FALSe if nothing was tracked. - */ -bool BKE_tracking_context_step(MovieTrackingContext *context) -{ - ImBuf *destination_ibuf; - int frame_delta = context->backwards ? -1 : 1; - int curfra = BKE_movieclip_remap_scene_to_clip_frame(context->clip, context->user.framenr); - int a, map_size; - bool ok = false; - - int frame_width, frame_height; - - map_size = tracks_map_get_size(context->tracks_map); - - /* Nothing to track, avoid unneeded frames reading to save time and memory. */ - if (!map_size) - return false; - - /* Get an image buffer for frame we're tracking to. */ - context->user.framenr += frame_delta; - - destination_ibuf = BKE_movieclip_get_ibuf_flag(context->clip, &context->user, - context->clip_flag, MOVIECLIP_CACHE_SKIP); - if (!destination_ibuf) - return false; - - frame_width = destination_ibuf->x; - frame_height = destination_ibuf->y; - -#pragma omp parallel for private(a) shared(destination_ibuf, ok) if (map_size > 1) - for (a = 0; a < map_size; a++) { - TrackContext *track_context = NULL; - MovieTrackingTrack *track; - MovieTrackingMarker *marker; - - tracks_map_get_indexed_element(context->tracks_map, a, &track, (void **)&track_context); - - marker = BKE_tracking_marker_get_exact(track, curfra); - - if (marker && (marker->flag & MARKER_DISABLED) == 0) { - bool tracked = false, need_readjust; - double dst_pixel_x[5], dst_pixel_y[5]; - - if (track->pattern_match == TRACK_MATCH_KEYFRAME) - need_readjust = context->first_time; - else - need_readjust = true; - - /* do not track markers which are too close to boundary */ - if (tracking_check_marker_margin(track, marker, frame_width, frame_height)) { - if (need_readjust) { - if (track_context_update_reference(context, track_context, track, marker, - curfra, frame_width, frame_height) == false) - { - /* happens when reference frame fails to be loaded */ - continue; - } - } - - tracked = configure_and_run_tracker(destination_ibuf, track, - &track_context->reference_marker, marker, - track_context->search_area, - track_context->search_area_width, - track_context->search_area_height, - track_context->mask, - dst_pixel_x, dst_pixel_y); - } - - BLI_spin_lock(&context->tracks_map->spin_lock); - tracking_insert_new_marker(context, track, marker, curfra, tracked, - frame_width, frame_height, dst_pixel_x, dst_pixel_y); - BLI_spin_unlock(&context->tracks_map->spin_lock); - - ok = true; - } - } - - IMB_freeImBuf(destination_ibuf); - - context->first_time = false; - context->frames++; - - return ok; -} - -void BKE_tracking_context_finish(MovieTrackingContext *context) -{ - MovieClip *clip = context->clip; - ListBase *plane_tracks_base = BKE_tracking_get_active_plane_tracks(&clip->tracking); - MovieTrackingPlaneTrack *plane_track; - int map_size = tracks_map_get_size(context->tracks_map); - - for (plane_track = plane_tracks_base->first; - plane_track; - plane_track = plane_track->next) - { - if ((plane_track->flag & PLANE_TRACK_AUTOKEY) == 0) { - int i; - for (i = 0; i < map_size; i++) { - TrackContext *track_context = NULL; - MovieTrackingTrack *track, *old_track; - bool do_update = false; - int j; - - tracks_map_get_indexed_element(context->tracks_map, i, &track, (void **)&track_context); - - old_track = BLI_ghash_lookup(context->tracks_map->hash, track); - for (j = 0; j < plane_track->point_tracksnr; j++) { - if (plane_track->point_tracks[j] == old_track) { - do_update = true; - break; - } - } - - if (do_update) { - BKE_tracking_track_plane_from_existing_motion(plane_track, context->first_frame); - break; - } - } - } - } -} - static bool refine_marker_reference_frame_get(MovieTrackingTrack *track, MovieTrackingMarker *marker, bool backwards, diff --git a/source/blender/blenkernel/intern/tracking_solver.c b/source/blender/blenkernel/intern/tracking_solver.c index 056220e27d8..d5e2f24e9ed 100644 --- a/source/blender/blenkernel/intern/tracking_solver.c +++ b/source/blender/blenkernel/intern/tracking_solver.c @@ -356,7 +356,7 @@ MovieReconstructContext *BKE_tracking_reconstruction_context_new(MovieClip *clip MovieReconstructContext *context = MEM_callocN(sizeof(MovieReconstructContext), "MovieReconstructContext data"); ListBase *tracksbase = BKE_tracking_object_get_tracks(tracking, object); float aspy = 1.0f / tracking->camera.pixel_aspect; - int num_tracks = BLI_countlist(tracksbase); + int num_tracks = BLI_listbase_count(tracksbase); int sfra = INT_MAX, efra = INT_MIN; MovieTrackingTrack *track; @@ -391,7 +391,7 @@ MovieReconstructContext *BKE_tracking_reconstruction_context_new(MovieClip *clip last_marker--; } - if (first < track->markersnr - 1) + if (first <= track->markersnr - 1) sfra = min_ii(sfra, first_marker->framenr); if (last >= 0) @@ -509,6 +509,11 @@ bool BKE_tracking_reconstruction_finish(MovieReconstructContext *context, MovieT MovieTrackingReconstruction *reconstruction; MovieTrackingObject *object; + if (!libmv_reconstructionIsValid(context->reconstruction)) { + printf("Failed solve the motion: most likely there are no good keyframes\n"); + return false; + } + tracks_map_merge(context->tracks_map, tracking); BKE_tracking_dopesheet_tag_update(tracking); diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c index 0a8293630c7..17e4a3c73c3 100644 --- a/source/blender/blenkernel/intern/tracking_util.c +++ b/source/blender/blenkernel/intern/tracking_util.c @@ -47,8 +47,13 @@ #include "BLF_translation.h" +#include "BKE_movieclip.h" #include "BKE_tracking.h" +#include "IMB_imbuf_types.h" +#include "IMB_imbuf.h" +#include "IMB_moviecache.h" + #include "tracking_private.h" #include "libmv-capi.h" @@ -390,8 +395,7 @@ void tracking_marker_insert_disabled(MovieTrackingTrack *track, const MovieTrack } -/* Fill in Libmv C-API camera intrinsics options from tracking structure. - */ +/* Fill in Libmv C-API camera intrinsics options from tracking structure. */ void tracking_cameraIntrinscisOptionsFromTracking(MovieTracking *tracking, int calibration_width, int calibration_height, libmv_CameraIntrinsicsOptions *camera_intrinsics_options) @@ -453,3 +457,441 @@ void tracking_trackingCameraFromIntrinscisOptions(MovieTracking *tracking, BLI_assert(!"Unknown distortion model"); } } + +/* Get previous keyframed marker. */ +MovieTrackingMarker *tracking_get_keyframed_marker(MovieTrackingTrack *track, + int current_frame, + bool backwards) +{ + MovieTrackingMarker *marker_keyed = NULL; + MovieTrackingMarker *marker_keyed_fallback = NULL; + int a = BKE_tracking_marker_get(track, current_frame) - track->markers; + + while (a >= 0 && a < track->markersnr) { + int next = backwards ? a + 1 : a - 1; + bool is_keyframed = false; + MovieTrackingMarker *cur_marker = &track->markers[a]; + MovieTrackingMarker *next_marker = NULL; + + if (next >= 0 && next < track->markersnr) + next_marker = &track->markers[next]; + + if ((cur_marker->flag & MARKER_DISABLED) == 0) { + /* If it'll happen so we didn't find a real keyframe marker, + * fallback to the first marker in current tracked segment + * as a keyframe. + */ + if (next_marker && next_marker->flag & MARKER_DISABLED) { + if (marker_keyed_fallback == NULL) + marker_keyed_fallback = cur_marker; + } + + is_keyframed |= (cur_marker->flag & MARKER_TRACKED) == 0; + } + + if (is_keyframed) { + marker_keyed = cur_marker; + + break; + } + + a = next; + } + + if (marker_keyed == NULL) + marker_keyed = marker_keyed_fallback; + + return marker_keyed; +} + +/*********************** Frame accessr *************************/ + +typedef struct AccessCacheKey { + int clip_index; + int frame; + int downscale; + libmv_InputMode input_mode; + int64_t transform_key; +} AccessCacheKey; + +static unsigned int accesscache_hashhash(const void *key_v) +{ + const AccessCacheKey *key = (const AccessCacheKey *) key_v; + /* TODP(sergey): Need better hasing here for faster frame access. */ + return key->clip_index << 16 | key->frame; +} + +static bool accesscache_hashcmp(const void *a_v, const void *b_v) +{ + const AccessCacheKey *a = (const AccessCacheKey *) a_v; + const AccessCacheKey *b = (const AccessCacheKey *) b_v; + +#define COMPARE_FIELD(field) + { \ + if (a->clip_index != b->clip_index) { \ + return false; \ + } \ + } (void) 0 + + COMPARE_FIELD(clip_index); + COMPARE_FIELD(frame); + COMPARE_FIELD(downscale); + COMPARE_FIELD(input_mode); + COMPARE_FIELD(transform_key); + +#undef COMPARE_FIELD + + return true; +} + +static void accesscache_put(TrackingImageAccessor *accessor, + int clip_index, + int frame, + libmv_InputMode input_mode, + int downscale, + int64_t transform_key, + ImBuf *ibuf) +{ + AccessCacheKey key; + key.clip_index = clip_index; + key.frame = frame; + key.input_mode = input_mode; + key.downscale = downscale; + key.transform_key = transform_key; + IMB_moviecache_put(accessor->cache, &key, ibuf); +} + +static ImBuf *accesscache_get(TrackingImageAccessor *accessor, + int clip_index, + int frame, + libmv_InputMode input_mode, + int downscale, + int64_t transform_key) +{ + AccessCacheKey key; + key.clip_index = clip_index; + key.frame = frame; + key.input_mode = input_mode; + key.downscale = downscale; + key.transform_key = transform_key; + return IMB_moviecache_get(accessor->cache, &key); +} + +static ImBuf *accessor_get_preprocessed_ibuf(TrackingImageAccessor *accessor, + int clip_index, + int frame) +{ + MovieClip *clip; + MovieClipUser user; + ImBuf *ibuf; + int scene_frame; + + BLI_assert(clip_index < accessor->num_clips); + + clip = accessor->clips[clip_index]; + scene_frame = BKE_movieclip_remap_clip_to_scene_frame(clip, frame); + BKE_movieclip_user_set_frame(&user, scene_frame); + user.render_size = MCLIP_PROXY_RENDER_SIZE_FULL; + user.render_flag = 0; + ibuf = BKE_movieclip_get_ibuf(clip, &user); + + return ibuf; +} + +static ImBuf *make_grayscale_ibuf_copy(ImBuf *ibuf) +{ + ImBuf *grayscale = IMB_allocImBuf(ibuf->x, ibuf->y, 32, 0); + size_t size; + int i; + + BLI_assert(ibuf->channels == 3 || ibuf->channels == 4); + + /* TODO(sergey): Bummer, currently IMB API only allows to create 4 channels + * float buffer, so we do it manually here. + * + * Will generalize it later. + */ + size = (size_t)grayscale->x * (size_t)grayscale->y * sizeof(float); + grayscale->channels = 1; + if ((grayscale->rect_float = MEM_mapallocN(size, "tracking grayscale image"))) { + grayscale->mall |= IB_rectfloat; + grayscale->flags |= IB_rectfloat; + } + + for (i = 0; i < grayscale->x * grayscale->y; ++i) { + const float *pixel = ibuf->rect_float + ibuf->channels * i; + + grayscale->rect_float[i] = 0.2126f * pixel[0] + + 0.7152f * pixel[1] + + 0.0722f * pixel[2]; + } + + return grayscale; +} + +static void ibuf_to_float_image(const ImBuf *ibuf, libmv_FloatImage *float_image) +{ + BLI_assert(ibuf->rect_float != NULL); + float_image->buffer = ibuf->rect_float; + float_image->width = ibuf->x; + float_image->height = ibuf->y; + float_image->channels = ibuf->channels; +} + +static ImBuf *float_image_to_ibuf(libmv_FloatImage *float_image) +{ + ImBuf *ibuf = IMB_allocImBuf(float_image->width, float_image->height, 32, 0); + size_t size = (size_t)ibuf->x * (size_t)ibuf->y * + float_image->channels * sizeof(float); + ibuf->channels = float_image->channels; + if ((ibuf->rect_float = MEM_mapallocN(size, "tracking grayscale image"))) { + ibuf->mall |= IB_rectfloat; + ibuf->flags |= IB_rectfloat; + } + memcpy(ibuf->rect_float, float_image->buffer, size); + return ibuf; +} + +static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor, + int clip_index, + int frame, + libmv_InputMode input_mode, + int downscale, + const libmv_Region *region, + const libmv_FrameTransform *transform) +{ + ImBuf *ibuf, *orig_ibuf, *final_ibuf; + int64_t transform_key = 0; + + if (transform != NULL) { + transform_key = libmv_frameAccessorgetTransformKey(transform); + } + + /* First try to get fully processed image from the cache. */ + ibuf = accesscache_get(accessor, + clip_index, + frame, + input_mode, + downscale, + transform_key); + if (ibuf != NULL) { + return ibuf; + } + + /* And now we do postprocessing of the original frame. */ + orig_ibuf = accessor_get_preprocessed_ibuf(accessor, clip_index, frame); + + if (orig_ibuf == NULL) { + return NULL; + } + + if (region != NULL) { + int width = region->max[0] - region->min[0], + height = region->max[1] - region->min[1]; + + /* If the requested region goes outside of the actual frame we still + * return the requested region size, but only fill it's partially with + * the data we can. + */ + int clamped_origin_x = max_ii((int)region->min[0], 0), + clamped_origin_y = max_ii((int)region->min[1], 0); + int dst_offset_x = clamped_origin_x - (int)region->min[0], + dst_offset_y = clamped_origin_y - (int)region->min[1]; + int clamped_width = width - dst_offset_x, + clamped_height = height - dst_offset_y; + clamped_width = min_ii(clamped_width, orig_ibuf->x - clamped_origin_x); + clamped_height = min_ii(clamped_height, orig_ibuf->y - clamped_origin_y); + + final_ibuf = IMB_allocImBuf(width, height, 32, IB_rectfloat); + + if (orig_ibuf->rect_float != NULL) { + IMB_rectcpy(final_ibuf, orig_ibuf, + dst_offset_x, dst_offset_y, + clamped_origin_x, clamped_origin_y, + clamped_width, clamped_height); + } + else { + int y; + /* TODO(sergey): We don't do any color space or alpha conversion + * here. Probably Libmv is better to work in the linear space, + * but keep sRGB space here for compatibility for now. + */ + for (y = 0; y < clamped_height; ++y) { + int x; + for (x = 0; x < clamped_width; ++x) { + int src_x = x + clamped_origin_x, + src_y = y + clamped_origin_y; + int dst_x = x + dst_offset_x, + dst_y = y + dst_offset_y; + int dst_index = (dst_y * width + dst_x) * 4, + src_index = (src_y * orig_ibuf->x + src_x) * 4; + rgba_uchar_to_float(final_ibuf->rect_float + dst_index, + (unsigned char *)orig_ibuf->rect + + src_index); + } + } + } + } + else { + /* Libmv only works with float images, + * + * This would likely make it so loads of float buffers are being stored + * in the cache which is nice on the one hand (faster re-use of the + * frames) but on the other hand it bumps the memory usage up. + */ + BLI_lock_thread(LOCK_MOVIECLIP); + IMB_float_from_rect(orig_ibuf); + BLI_unlock_thread(LOCK_MOVIECLIP); + final_ibuf = orig_ibuf; + } + + if (downscale > 0) { + if (final_ibuf == orig_ibuf) { + final_ibuf = IMB_dupImBuf(orig_ibuf); + } + IMB_scaleImBuf(final_ibuf, + ibuf->x / (1 << downscale), + ibuf->y / (1 << downscale)); + } + + if (transform != NULL) { + libmv_FloatImage input_image, output_image; + ibuf_to_float_image(final_ibuf, &input_image); + libmv_frameAccessorgetTransformRun(transform, + &input_image, + &output_image); + if (final_ibuf != orig_ibuf) { + IMB_freeImBuf(final_ibuf); + } + final_ibuf = float_image_to_ibuf(&output_image); + libmv_floatImageDestroy(&output_image); + } + + if (input_mode == LIBMV_IMAGE_MODE_RGBA) { + BLI_assert(ibuf->channels == 3 || ibuf->channels == 4); + /* pass */ + } + else /* if (input_mode == LIBMV_IMAGE_MODE_MONO) */ { + if (final_ibuf->channels != 1) { + ImBuf *grayscale_ibuf = make_grayscale_ibuf_copy(final_ibuf); + if (final_ibuf != orig_ibuf) { + /* We dereference original frame later. */ + IMB_freeImBuf(final_ibuf); + } + final_ibuf = grayscale_ibuf; + } + } + + /* it's possible processing still didn't happen at this point, + * but we really need a copy of the buffer to be transformed + * and to be put to the cache. + */ + if (final_ibuf == orig_ibuf) { + final_ibuf = IMB_dupImBuf(orig_ibuf); + } + + IMB_freeImBuf(orig_ibuf); + + /* We put postprocessed frame to the cache always for now, + * not the smartest thing in the world, but who cares at this point. + */ + + /* TODO(sergey): Disable cache for now, because we don't store region + * in the cache key and can't check whether cached version is usable for + * us or not. + * + * Need to think better about what to cache and when. + */ + if (false) { + accesscache_put(accessor, + clip_index, + frame, + input_mode, + downscale, + transform_key, + final_ibuf); + } + + return final_ibuf; +} + +static libmv_CacheKey accessor_get_image_callback( + struct libmv_FrameAccessorUserData *user_data, + int clip_index, + int frame, + libmv_InputMode input_mode, + int downscale, + const libmv_Region *region, + const libmv_FrameTransform *transform, + float **destination, + int *width, + int *height, + int *channels) +{ + TrackingImageAccessor *accessor = (TrackingImageAccessor *) user_data; + ImBuf *ibuf; + + BLI_assert(clip_index >= 0 && clip_index < accessor->num_clips); + + ibuf = accessor_get_ibuf(accessor, + clip_index, + frame, + input_mode, + downscale, + region, + transform); + + if (ibuf) { + *destination = ibuf->rect_float; + *width = ibuf->x; + *height = ibuf->y; + *channels = ibuf->channels; + } + else { + *destination = NULL; + *width = 0; + *height = 0; + *channels = 0; + } + + return ibuf; +} + +static void accessor_release_image_callback(libmv_CacheKey cache_key) +{ + ImBuf *ibuf = (ImBuf *) cache_key; + IMB_freeImBuf(ibuf); +} + +TrackingImageAccessor *tracking_image_accessor_new(MovieClip *clips[MAX_ACCESSOR_CLIP], + int num_clips, + int start_frame) +{ + TrackingImageAccessor *accessor = + MEM_callocN(sizeof(TrackingImageAccessor), "tracking image accessor"); + + BLI_assert(num_clips <= MAX_ACCESSOR_CLIP); + + accessor->cache = IMB_moviecache_create("frame access cache", + sizeof(AccessCacheKey), + accesscache_hashhash, + accesscache_hashcmp); + + memcpy(accessor->clips, clips, num_clips * sizeof(MovieClip *)); + accessor->num_clips = num_clips; + accessor->start_frame = start_frame; + + accessor->libmv_accessor = + libmv_FrameAccessorNew((libmv_FrameAccessorUserData *) accessor, + accessor_get_image_callback, + accessor_release_image_callback); + + return accessor; +} + +void tracking_image_accessor_destroy(TrackingImageAccessor *accessor) +{ + IMB_moviecache_free(accessor->cache); + libmv_FrameAccessorDestroy(accessor->libmv_accessor); + MEM_freeN(accessor); +} diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 8e3c92314e6..8113e2bf9ef 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -38,8 +38,8 @@ #include "DNA_scene_types.h" #include "DNA_texture_types.h" -#include "BLI_listbase.h" #include "BLI_utildefines.h" +#include "BLI_listbase.h" #include "BKE_animsys.h" #include "BKE_global.h" @@ -49,6 +49,8 @@ #include "BKE_node.h" #include "BKE_world.h" +#include "GPU_material.h" + void BKE_world_free_ex(World *wrld, bool do_id_user) { MTex *mtex; @@ -69,6 +71,9 @@ void BKE_world_free_ex(World *wrld, bool do_id_user) MEM_freeN(wrld->nodetree); } + if (wrld->gpumaterial.first) + GPU_material_free(&wrld->gpumaterial); + BKE_icon_delete((struct ID *)wrld); wrld->id.icon_id = 0; } @@ -134,6 +139,8 @@ World *BKE_world_copy(World *wrld) if (wrld->preview) wrldn->preview = BKE_previewimg_copy(wrld->preview); + BLI_listbase_clear(&wrldn->gpumaterial); + return wrldn; } @@ -158,6 +165,8 @@ World *localize_world(World *wrld) wrldn->preview = NULL; + BLI_listbase_clear(&wrldn->gpumaterial); + return wrldn; } diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c index aef44993912..8a6a0438b84 100644 --- a/source/blender/blenkernel/intern/writeavi.c +++ b/source/blender/blenkernel/intern/writeavi.c @@ -80,7 +80,9 @@ static void filepath_avi(char *string, RenderData *rd); # include "BKE_writeffmpeg.h" #endif -#include "BKE_writeframeserver.h" +#ifdef WITH_FRAMESERVER +# include "BKE_writeframeserver.h" +#endif bMovieHandle *BKE_movie_handle_get(const char imtype) { diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index ca21180000d..d4f5da2e36f 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -57,7 +57,6 @@ #include "BKE_sound.h" #include "BKE_writeffmpeg.h" -#include "IMB_imbuf_types.h" #include "IMB_imbuf.h" #include "ffmpeg_compat.h" @@ -484,7 +483,6 @@ static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char AVDictionary **dictionary) { IDProperty *prop; - void *iter; IDProperty *curr; /* TODO(sergey): This is actually rather stupid, because changing @@ -495,7 +493,7 @@ static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char * * For as long we don't allow editing properties in the interface * it's all good. bug if we allow editing them, we'll need to - * repace it with some smarter code which would port settings + * replace it with some smarter code which would port settings * from deprecated to new one. */ ffmpeg_set_expert_options(rd); @@ -509,9 +507,7 @@ static void set_ffmpeg_properties(RenderData *rd, AVCodecContext *c, const char return; } - iter = IDP_GetGroupIterator(prop); - - while ((curr = IDP_GroupIterNext(iter)) != NULL) { + for (curr = prop->data.group.first; curr; curr = curr->next) { if (ffmpeg_proprty_valid(c, prop_name, curr)) set_ffmpeg_property_option(c, curr, dictionary); } @@ -696,7 +692,7 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex } if (codec->sample_fmts) { - /* check if the prefered sample format for this codec is supported. + /* check if the preferred sample format for this codec is supported. * this is because, depending on the version of libav, and with the whole ffmpeg/libav fork situation, * you have various implementations around. float samples in particular are not always supported. */ diff --git a/source/blender/blenkernel/tracking_private.h b/source/blender/blenkernel/tracking_private.h index 6efa1533e3e..591ee4d0d01 100644 --- a/source/blender/blenkernel/tracking_private.h +++ b/source/blender/blenkernel/tracking_private.h @@ -95,4 +95,32 @@ void tracking_cameraIntrinscisOptionsFromTracking(struct MovieTracking *tracking void tracking_trackingCameraFromIntrinscisOptions(struct MovieTracking *tracking, const struct libmv_CameraIntrinsicsOptions *camera_intrinsics_options); +struct libmv_TrackRegionOptions; + +void tracking_configure_tracker(const MovieTrackingTrack *track, float *mask, + struct libmv_TrackRegionOptions *options); + +struct MovieTrackingMarker *tracking_get_keyframed_marker( + struct MovieTrackingTrack *track, + int current_frame, + bool backwards); + +/*********************** Frame accessr *************************/ + +struct libmv_FrameAccessor; + +#define MAX_ACCESSOR_CLIP 64 +typedef struct TrackingImageAccessor { + struct MovieCache *cache; + struct MovieClip *clips[MAX_ACCESSOR_CLIP]; + int num_clips; + int start_frame; + struct libmv_FrameAccessor *libmv_accessor; +} TrackingImageAccessor; + +TrackingImageAccessor *tracking_image_accessor_new(MovieClip *clips[MAX_ACCESSOR_CLIP], + int num_clips, + int start_frame); +void tracking_image_accessor_destroy(TrackingImageAccessor *accessor); + #endif /* __TRACKING_PRIVATE_H__ */ |