diff options
Diffstat (limited to 'source/blender/blenkernel')
156 files changed, 11105 insertions, 9666 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 700bfe568f1..c3cea6c883c 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -98,6 +98,9 @@ struct ColorBand; struct GPUVertexAttribs; struct GPUDrawObject; struct PBVH; +struct EvaluationContext; + +#include "DNA_object_enums.h" /* number of sub-elements each mesh element has (for interpolation) */ #define SUB_ELEMS_VERT 0 @@ -142,8 +145,6 @@ 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 MTexPoly *mtexpoly, const bool has_vcol, int matnr); typedef enum DMDrawFlag { DM_DRAW_USE_COLORS = (1 << 0), @@ -382,16 +383,13 @@ struct DerivedMesh { /** Get the BVH used for paint modes */ - struct PBVH *(*getPBVH)(struct Object *ob, DerivedMesh *dm); + struct PBVH *(*getPBVH)(struct Object *ob, DerivedMesh *dm, eObjectMode object_mode); /* Drawing Operations */ /** Draw all vertices as bgl points (no options) */ void (*drawVerts)(DerivedMesh *dm); - /** Draw edges in the UV mesh (if exists) */ - void (*drawUVEdges)(DerivedMesh *dm); - /** Draw all edges as lines (no options) * * Also called for *final* editmode DerivedMeshes @@ -411,14 +409,6 @@ struct DerivedMesh { void (*drawFacesSolid)(DerivedMesh *dm, float (*partial_redraw_planes)[4], bool fast, DMSetMaterial setMaterial); - /** Draw all faces using MTFace - * - Drawing options too complicated to enumerate, look at code. - */ - void (*drawFacesTex)(DerivedMesh *dm, - DMSetDrawOptionsTex setDrawOptions, - DMCompareDrawOptions compareDrawOptions, - void *userData, DMDrawFlag flag); - /** Draw all faces with GLSL materials * o setMaterial is called for every different material nr * o Only if setMaterial returns true @@ -445,14 +435,6 @@ struct DerivedMesh { void *userData, DMDrawFlag flag); - /** Draw mapped faces using MTFace - * - Drawing options too complicated to enumerate, look at code. - */ - void (*drawMappedFacesTex)(DerivedMesh *dm, - DMSetDrawOptionsMappedTex setDrawOptions, - DMCompareDrawOptions compareDrawOptions, - void *userData, DMDrawFlag flag); - /** Draw mapped faces with GLSL materials * - setMaterial is called for every different material nr * - setDrawOptions is called for every face @@ -680,56 +662,56 @@ void mesh_get_mapped_verts_coords(DerivedMesh *dm, float (*r_cos)[3], const int /* */ DerivedMesh *mesh_get_derived_final( - struct Scene *scene, struct Object *ob, - CustomDataMask dataMask); + const struct EvaluationContext *eval_ctx, struct Scene *scene, + struct Object *ob, CustomDataMask dataMask); DerivedMesh *mesh_get_derived_deform( - struct Scene *scene, struct Object *ob, - CustomDataMask dataMask); + const struct EvaluationContext *eval_ctx, struct Scene *scene, + struct Object *ob, CustomDataMask dataMask); DerivedMesh *mesh_create_derived_for_modifier( - struct Scene *scene, struct Object *ob, + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ModifierData *md, int build_shapekey_layers); DerivedMesh *mesh_create_derived_render( - struct Scene *scene, struct Object *ob, - CustomDataMask dataMask); + const struct EvaluationContext *eval_ctx, struct Scene *scene, + struct Object *ob, CustomDataMask dataMask); DerivedMesh *getEditDerivedBMesh( struct BMEditMesh *em, struct Object *ob, CustomDataMask data_mask, float (*vertexCos)[3]); DerivedMesh *mesh_create_derived_index_render( - struct Scene *scene, struct Object *ob, - CustomDataMask dataMask, int index); + const struct EvaluationContext *eval_ctx, struct Scene *scene, + struct Object *ob, CustomDataMask dataMask, int index); /* same as above but wont use render settings */ DerivedMesh *mesh_create_derived(struct Mesh *me, float (*vertCos)[3]); DerivedMesh *mesh_create_derived_view( - struct Scene *scene, struct Object *ob, - CustomDataMask dataMask); + const struct EvaluationContext *eval_ctx, struct Scene *scene, + struct Object *ob, CustomDataMask dataMask); DerivedMesh *mesh_create_derived_no_deform( - struct Scene *scene, struct Object *ob, - float (*vertCos)[3], + const struct EvaluationContext *eval_ctx, struct Scene *scene, + struct Object *ob, float (*vertCos)[3], CustomDataMask dataMask); DerivedMesh *mesh_create_derived_no_deform_render( - struct Scene *scene, struct Object *ob, - float (*vertCos)[3], + const struct EvaluationContext *eval_ctx, struct Scene *scene, + struct Object *ob, float (*vertCos)[3], CustomDataMask dataMask); /* for gameengine */ DerivedMesh *mesh_create_derived_no_virtual( - struct Scene *scene, struct Object *ob, float (*vertCos)[3], - CustomDataMask dataMask); + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, + float (*vertCos)[3], CustomDataMask dataMask); DerivedMesh *mesh_create_derived_physics( - struct Scene *scene, struct Object *ob, float (*vertCos)[3], - CustomDataMask dataMask); + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, + float (*vertCos)[3], CustomDataMask dataMask); DerivedMesh *editbmesh_get_derived_base( struct Object *ob, struct BMEditMesh *em, CustomDataMask data_mask); DerivedMesh *editbmesh_get_derived_cage( - struct Scene *scene, struct Object *, + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *, struct BMEditMesh *em, CustomDataMask dataMask); DerivedMesh *editbmesh_get_derived_cage_and_final( - struct Scene *scene, struct Object *, + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *, struct BMEditMesh *em, CustomDataMask dataMask, DerivedMesh **r_final); @@ -738,7 +720,7 @@ DerivedMesh *object_get_derived_final(struct Object *ob, const bool for_render); float (*editbmesh_get_vertex_cos(struct BMEditMesh *em, int *r_numVerts))[3]; bool editbmesh_modifier_is_enabled(struct Scene *scene, struct ModifierData *md, DerivedMesh *dm); void makeDerivedMesh( - struct Scene *scene, struct Object *ob, struct BMEditMesh *em, + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct BMEditMesh *em, CustomDataMask dataMask, const bool build_shapekey_layers); void weight_to_rgb(float r_rgb[3], const float weight); @@ -789,19 +771,15 @@ void DM_draw_attrib_vertex_uniforms(const DMVertexAttribs *attribs); void DM_calc_tangents_names_from_gpu( const struct GPUVertexAttribs *gattribs, char (*tangent_names)[MAX_NAME], int *tangent_names_count); + void DM_add_named_tangent_layer_for_uv( CustomData *uv_data, CustomData *tan_data, int numLoopData, const char *layer_name); -#define DM_TANGENT_MASK_ORCO (1 << 9) -void DM_calc_loop_tangents_step_0( - const CustomData *loopData, bool calc_active_tangent, - const char (*tangent_names)[MAX_NAME], int tangent_names_count, - bool *rcalc_act, bool *rcalc_ren, int *ract_uv_n, int *rren_uv_n, - char *ract_uv_name, char *rren_uv_name, short *rtangent_mask); void DM_calc_loop_tangents( DerivedMesh *dm, bool calc_active_tangent, const char (*tangent_names)[MAX_NAME], int tangent_names_count); + void DM_calc_auto_bump_scale(DerivedMesh *dm); /** Set object's bounding box based on DerivedMesh min/max data */ diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h index 584f0da323a..30a7bdb0a27 100644 --- a/source/blender/blenkernel/BKE_anim.h +++ b/source/blender/blenkernel/BKE_anim.h @@ -41,6 +41,7 @@ struct bAnimVizSettings; struct bMotionPath; struct bPoseChannel; struct ReportList; +struct Main; /* ---------------------------------------------------- */ /* Animation Visualization */ @@ -53,7 +54,7 @@ void animviz_free_motionpath(struct bMotionPath *mpath); struct bMotionPath *animviz_verify_motionpaths(struct ReportList *reports, struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan); void animviz_get_object_motionpaths(struct Object *ob, ListBase *targets); -void animviz_calc_motionpaths(struct Scene *scene, ListBase *targets); +void animviz_calc_motionpaths(struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *scene, ListBase *targets); /* ---------------------------------------------------- */ /* Curve Paths */ @@ -65,8 +66,8 @@ int where_on_path(struct Object *ob, float ctime, float vec[4], float dir[3], fl /* ---------------------------------------------------- */ /* Dupli-Geometry */ -struct ListBase *object_duplilist_ex(struct EvaluationContext *eval_ctx, struct Scene *sce, struct Object *ob, bool update); -struct ListBase *object_duplilist(struct EvaluationContext *eval_ctx, struct Scene *sce, struct Object *ob); +struct ListBase *object_duplilist_ex(const struct EvaluationContext *eval_ctx, struct Scene *sce, struct Object *ob, bool update); +struct ListBase *object_duplilist(const struct EvaluationContext *eval_ctx, struct Scene *sce, struct Object *ob); void free_object_duplilist(struct ListBase *lb); int count_duplilist(struct Object *ob); @@ -80,7 +81,7 @@ typedef struct DupliApplyData { DupliExtraData *extra; } DupliApplyData; -DupliApplyData *duplilist_apply(struct Object *ob, struct Scene *scene, struct ListBase *duplilist); +DupliApplyData *duplilist_apply(const struct EvaluationContext *eval_ctx, struct Object *ob, struct Scene *scene, struct ListBase *duplilist); void duplilist_restore(struct ListBase *duplilist, DupliApplyData *apply_data); void duplilist_free_apply_data(DupliApplyData *apply_data); diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h index a70690d4029..d95b4a838b8 100644 --- a/source/blender/blenkernel/BKE_animsys.h +++ b/source/blender/blenkernel/BKE_animsys.h @@ -47,6 +47,7 @@ struct ReportList; struct bAction; struct bActionGroup; struct AnimMapper; +struct FCurve; /* ************************************* */ /* AnimData API */ @@ -148,7 +149,7 @@ char *BKE_animdata_driver_path_hack(struct bContext *C, struct PointerRNA *ptr, char *base_path); /* ************************************* */ -/* Batch AnimData API */ +/* Gwn_Batch AnimData API */ /* Define for callback looper used in BKE_animdata_main_cb */ typedef void (*ID_AnimData_Edit_Callback)(struct ID *id, struct AnimData *adt, void *user_data); @@ -179,7 +180,6 @@ void BKE_animsys_evaluate_animdata(struct Scene *scene, struct ID *id, struct An void BKE_animsys_evaluate_all_animation(struct Main *main, struct Scene *scene, float ctime); /* TODO(sergey): This is mainly a temp public function. */ -struct FCurve; bool BKE_animsys_execute_fcurve(struct PointerRNA *ptr, struct AnimMapper *remap, struct FCurve *fcu, float curval); /* ------------ Specialized API --------------- */ @@ -202,8 +202,8 @@ void animsys_evaluate_action_group(struct PointerRNA *ptr, struct bAction *act, struct EvaluationContext; -void BKE_animsys_eval_animdata(struct EvaluationContext *eval_ctx, struct ID *id); -void BKE_animsys_eval_driver(struct EvaluationContext *eval_ctx, struct ID *id, struct FCurve *fcurve); +void BKE_animsys_eval_animdata(const struct EvaluationContext *eval_ctx, struct ID *id); +void BKE_animsys_eval_driver(const struct EvaluationContext *eval_ctx, struct ID *id, struct FCurve *fcurve); /* ************************************* */ diff --git a/source/blender/blenkernel/BKE_appdir.h b/source/blender/blenkernel/BKE_appdir.h index ac8f861fa56..ffbdc6972f4 100644 --- a/source/blender/blenkernel/BKE_appdir.h +++ b/source/blender/blenkernel/BKE_appdir.h @@ -82,6 +82,7 @@ enum { #define BLENDER_STARTUP_FILE "startup.blend" #define BLENDER_USERPREF_FILE "userpref.blend" +#define BLENDER_WORKSPACES_FILE "workspaces.blend" #define BLENDER_QUIT_FILE "quit.blend" #define BLENDER_BOOKMARK_FILE "bookmarks.txt" #define BLENDER_HISTORY_FILE "recent-files.txt" diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 60fb79d75d5..192690c074c 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -33,7 +33,9 @@ * \author nzc */ +struct bPose; struct Bone; +struct EvaluationContext; struct GHash; struct Main; struct bArmature; @@ -98,9 +100,8 @@ void BKE_armature_where_is(struct bArmature *arm); void BKE_armature_where_is_bone(struct Bone *bone, struct Bone *prevbone, const bool use_recursion); void BKE_pose_clear_pointers(struct bPose *pose); void BKE_pose_rebuild(struct Object *ob, struct bArmature *arm); -void BKE_pose_rebuild_ex(struct Object *ob, struct bArmature *arm, const bool sort_bones); -void BKE_pose_where_is(struct Scene *scene, struct Object *ob); -void BKE_pose_where_is_bone(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime, bool do_extra); +void BKE_pose_where_is(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); +void BKE_pose_where_is_bone(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime, bool do_extra); void BKE_pose_where_is_bone_tail(struct bPoseChannel *pchan); /* get_objectspace_bone_matrix has to be removed still */ @@ -117,7 +118,7 @@ void BKE_armature_loc_pose_to_bone(struct bPoseChannel *pchan, const float inloc void BKE_armature_mat_bone_to_pose(struct bPoseChannel *pchan, float inmat[4][4], float outmat[4][4]); void BKE_armature_mat_pose_to_delta(float delta_mat[4][4], float pose_mat[4][4], float arm_mat[4][4]); -void BKE_armature_mat_pose_to_bone_ex(struct Object *ob, struct bPoseChannel *pchan, float inmat[4][4], float outmat[4][4]); +void BKE_armature_mat_pose_to_bone_ex(const struct EvaluationContext *eval_ctx, struct Object *ob, struct bPoseChannel *pchan, float inmat[4][4], float outmat[4][4]); void BKE_pchan_mat3_to_rot(struct bPoseChannel *pchan, float mat[3][3], bool use_compat); void BKE_pchan_apply_mat4(struct bPoseChannel *pchan, float mat[4][4], bool use_comat); @@ -155,7 +156,6 @@ void b_bone_spline_setup(struct bPoseChannel *pchan, int rest, Mat4 result_array struct bKinematicConstraint; struct bPose; struct bSplineIKConstraint; -struct EvaluationContext; struct bPoseChannel *BKE_armature_ik_solver_find_root( struct bPoseChannel *pchan, @@ -165,47 +165,49 @@ struct bPoseChannel *BKE_armature_splineik_solver_find_root( struct bSplineIKConstraint *data); void BKE_pose_splineik_init_tree(struct Scene *scene, struct Object *ob, float ctime); -void BKE_splineik_execute_tree(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan_root, float ctime); +void BKE_splineik_execute_tree( + const struct EvaluationContext *eval_ctx, struct Scene *scene, + struct Object *ob, struct bPoseChannel *pchan_root, float ctime); -void BKE_pose_eval_init(struct EvaluationContext *eval_ctx, +void BKE_pose_eval_init(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct bPose *pose); -void BKE_pose_eval_init_ik(struct EvaluationContext *eval_ctx, +void BKE_pose_eval_init_ik(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct bPose *pose); -void BKE_pose_eval_bone(struct EvaluationContext *eval_ctx, +void BKE_pose_eval_bone(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan); -void BKE_pose_constraints_evaluate(struct EvaluationContext *eval_ctx, +void BKE_pose_constraints_evaluate(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan); -void BKE_pose_bone_done(struct EvaluationContext *eval_ctx, +void BKE_pose_bone_done(const struct EvaluationContext *eval_ctx, struct bPoseChannel *pchan); -void BKE_pose_iktree_evaluate(struct EvaluationContext *eval_ctx, +void BKE_pose_iktree_evaluate(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct bPoseChannel *rootchan); -void BKE_pose_splineik_evaluate(struct EvaluationContext *eval_ctx, +void BKE_pose_splineik_evaluate(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct bPoseChannel *rootchan); -void BKE_pose_eval_flush(struct EvaluationContext *eval_ctx, +void BKE_pose_eval_flush(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct bPose *pose); -void BKE_pose_eval_proxy_copy(struct EvaluationContext *eval_ctx, +void BKE_pose_eval_proxy_copy(const struct EvaluationContext *eval_ctx, struct Object *ob); #ifdef __cplusplus diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index c99da724794..ceb466ebdcd 100644 --- a/source/blender/blenkernel/BKE_blender_version.h +++ b/source/blender/blenkernel/BKE_blender_version.h @@ -27,8 +27,8 @@ /* these lines are grep'd, watch out for our not-so-awesome regex * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ -#define BLENDER_VERSION 279 -#define BLENDER_SUBVERSION 2 +#define BLENDER_VERSION 280 +#define BLENDER_SUBVERSION 4 /* Several breakages with 270, e.g. constraint deg vs rad */ #define BLENDER_MINVERSION 270 #define BLENDER_MINSUBVERSION 6 diff --git a/source/blender/blenkernel/BKE_blendfile.h b/source/blender/blenkernel/BKE_blendfile.h index 9ff164f60be..a9a7e2045f0 100644 --- a/source/blender/blenkernel/BKE_blendfile.h +++ b/source/blender/blenkernel/BKE_blendfile.h @@ -61,6 +61,10 @@ struct UserDef *BKE_blendfile_userdef_read_from_memory( bool BKE_blendfile_userdef_write(const char *filepath, struct ReportList *reports); bool BKE_blendfile_userdef_write_app_template(const char *filepath, struct ReportList *reports); +struct WorkspaceConfigFileData *BKE_blendfile_workspace_config_read(const char *filepath, struct ReportList *reports); +bool BKE_blendfile_workspace_config_write(struct Main *bmain, const char *filepath, struct ReportList *reports); +void BKE_blendfile_workspace_config_data_free(struct WorkspaceConfigFileData *workspace_config); + /* partial blend file writing */ void BKE_blendfile_write_partial_tag_ID(struct ID *id, bool set); void BKE_blendfile_write_partial_begin(struct Main *bmain_src); diff --git a/source/blender/blenkernel/BKE_cachefile.h b/source/blender/blenkernel/BKE_cachefile.h index e9712681090..e0419d0e749 100644 --- a/source/blender/blenkernel/BKE_cachefile.h +++ b/source/blender/blenkernel/BKE_cachefile.h @@ -65,7 +65,7 @@ bool BKE_cachefile_filepath_get( float BKE_cachefile_time_offset(struct CacheFile *cache_file, const float time, const float fps); -void BKE_cachefile_clean(struct Scene *scene, struct CacheFile *cache_file); +void BKE_cachefile_clean(struct Main *bmain, struct CacheFile *cache_file); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_camera.h b/source/blender/blenkernel/BKE_camera.h index 04dee70faa6..d5bf2177f71 100644 --- a/source/blender/blenkernel/BKE_camera.h +++ b/source/blender/blenkernel/BKE_camera.h @@ -39,11 +39,13 @@ extern "C" { #include "DNA_vec_types.h" struct Camera; +struct Depsgraph; struct Main; struct Object; struct RegionView3D; struct RenderData; struct Scene; +struct ViewLayer; struct rctf; struct View3D; struct GPUFXSettings; @@ -112,7 +114,7 @@ typedef struct CameraParams { void BKE_camera_params_init(CameraParams *params); void BKE_camera_params_from_object(CameraParams *params, const struct Object *camera); -void BKE_camera_params_from_view3d(CameraParams *params, const struct View3D *v3d, const struct RegionView3D *rv3d); +void BKE_camera_params_from_view3d(CameraParams *params, const struct Depsgraph *depsgraph, const struct View3D *v3d, const struct RegionView3D *rv3d); void BKE_camera_params_compute_viewplane(CameraParams *params, int winx, int winy, float aspx, float aspy); void BKE_camera_params_compute_matrix(CameraParams *params); @@ -128,7 +130,7 @@ void BKE_camera_view_frame( float r_vec[4][3]); bool BKE_camera_view_frame_fit_to_scene( - struct Scene *scene, struct View3D *v3d, struct Object *camera_ob, + struct Scene *scene, struct ViewLayer *view_layer, struct Object *camera_ob, float r_co[3], float *r_scale); bool BKE_camera_view_frame_fit_to_coords( const struct Scene *scene, @@ -147,6 +149,11 @@ float BKE_camera_multiview_shift_x(struct RenderData *rd, struct Object void BKE_camera_multiview_params(struct RenderData *rd, struct CameraParams *params, struct Object *camera, const char *viewname); bool BKE_camera_multiview_spherical_stereo(struct RenderData *rd, struct Object *camera); +/* Camera background image API */ +struct CameraBGImage *BKE_camera_background_image_new(struct Camera *cam); +void BKE_camera_background_image_remove(struct Camera *cam, struct CameraBGImage *bgpic); +void BKE_camera_background_image_clear(struct Camera *cam); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 6c517bd02df..27b928c1671 100644 --- a/source/blender/blenkernel/BKE_cloth.h +++ b/source/blender/blenkernel/BKE_cloth.h @@ -41,6 +41,7 @@ struct MFace; struct DerivedMesh; struct ClothModifierData; struct CollisionModifierData; +struct EvaluationContext; #define DO_INLINE MALWAYS_INLINE @@ -226,7 +227,7 @@ void cloth_free_contacts(ColliderContacts *collider_contacts, int totcolliders); void cloth_free_modifier_extern (struct ClothModifierData *clmd ); void cloth_free_modifier (struct ClothModifierData *clmd ); void cloth_init (struct ClothModifierData *clmd ); -void clothModifier_do (struct ClothModifierData *clmd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3]); +void clothModifier_do(struct ClothModifierData *clmd, const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3]); int cloth_uses_vgroup(struct ClothModifierData *clmd); @@ -235,7 +236,9 @@ void bvhtree_update_from_cloth(struct ClothModifierData *clmd, bool moving); void bvhselftree_update_from_cloth(struct ClothModifierData *clmd, bool moving); // needed for button_object.c -void cloth_clear_cache (struct Object *ob, struct ClothModifierData *clmd, float framenr ); +void cloth_clear_cache( + const struct EvaluationContext *eval_ctx, + struct Object *ob, struct ClothModifierData *clmd, float framenr ); void cloth_parallel_transport_hair_frame(float mat[3][3], const float dir_old[3], const float dir_new[3]); diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h new file mode 100644 index 00000000000..618e60550b7 --- /dev/null +++ b/source/blender/blenkernel/BKE_collection.h @@ -0,0 +1,108 @@ +/* + * ***** 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. + * + * Contributor(s): Dalai Felinto + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BKE_COLLECTION_H__ +#define __BKE_COLLECTION_H__ + +/** \file blender/blenkernel/BKE_collection.h + * \ingroup bke + */ + +#include "BLI_ghash.h" +#include "BLI_iterator.h" +#include "DNA_listBase.h" + +#ifdef __cplusplus +extern "C" { +#endif + +struct Base; +struct BLI_Iterator; +struct Group; +struct ID; +struct LayerCollection; +struct Main; +struct Object; +struct Scene; +struct SceneCollection; + +struct SceneCollection *BKE_collection_add( + struct ID *owner_id, struct SceneCollection *sc_parent, const int type, const char *name); +bool BKE_collection_remove(struct ID *owner_id, struct SceneCollection *sc); +void BKE_collection_copy_data(struct SceneCollection *sc_dst, struct SceneCollection *sc_src, const int flag); +struct SceneCollection *BKE_collection_duplicate(struct ID *owner_id, struct SceneCollection *scene_collection); +struct SceneCollection *BKE_collection_master(const struct ID *owner_id); +void BKE_collection_rename(const struct Scene *scene, struct SceneCollection *sc, const char *name); +void BKE_collection_master_free(struct ID *owner_id, const bool do_id_user); +bool BKE_collection_object_add(const struct ID *owner_id, struct SceneCollection *sc, struct Object *object); +void BKE_collection_object_add_from(struct Scene *scene, struct Object *ob_src, struct Object *ob_dst); +bool BKE_collection_object_remove(struct Main *bmain, struct ID *owner_id, struct SceneCollection *sc, struct Object *object, const bool free_us); +bool BKE_collections_object_remove(struct Main *bmain, struct ID *owner_id, struct Object *object, const bool free_us); +void BKE_collection_object_move(struct ID *owner_id, struct SceneCollection *sc_dst, struct SceneCollection *sc_src, struct Object *ob); + +struct Group *BKE_collection_group_create(struct Main *bmain, struct Scene *scene, struct LayerCollection *lc); + +void BKE_collection_reinsert_after(const struct Scene *scene, struct SceneCollection *sc_reinsert, struct SceneCollection *sc_after); +void BKE_collection_reinsert_into(struct SceneCollection *sc_reinsert, struct SceneCollection *sc_into); + +bool BKE_collection_move_above(const struct ID *owner_id, struct SceneCollection *sc_dst, struct SceneCollection *sc_src); +bool BKE_collection_move_below(const struct ID *owner_id, struct SceneCollection *sc_dst, struct SceneCollection *sc_src); +bool BKE_collection_move_into(const struct ID *owner_id, struct SceneCollection *sc_dst, struct SceneCollection *sc_src); + +typedef void (*BKE_scene_objects_Cb)(struct Object *ob, void *data); +typedef void (*BKE_scene_collections_Cb)(struct SceneCollection *ob, void *data); + +void BKE_scene_collections_callback(struct Scene *scene, BKE_scene_collections_Cb callback, void *data); +void BKE_scene_objects_callback(struct Scene *scene, BKE_scene_objects_Cb callback, void *data); + +/* iterators */ +void BKE_scene_collections_iterator_begin(struct BLI_Iterator *iter, void *data_in); +void BKE_scene_collections_iterator_next(struct BLI_Iterator *iter); +void BKE_scene_collections_iterator_end(struct BLI_Iterator *iter); + +void BKE_scene_objects_iterator_begin(struct BLI_Iterator *iter, void *data_in); +void BKE_scene_objects_iterator_next(struct BLI_Iterator *iter); +void BKE_scene_objects_iterator_end(struct BLI_Iterator *iter); + +#define FOREACH_SCENE_COLLECTION(_id, _instance) \ + ITER_BEGIN(BKE_scene_collections_iterator_begin, \ + BKE_scene_collections_iterator_next, \ + BKE_scene_collections_iterator_end, \ + _id, SceneCollection *, _instance) + +#define FOREACH_SCENE_COLLECTION_END \ + ITER_END + +#define FOREACH_SCENE_OBJECT(scene, _instance) \ + ITER_BEGIN(BKE_scene_objects_iterator_begin, \ + BKE_scene_objects_iterator_next, \ + BKE_scene_objects_iterator_end, \ + scene, Object *, _instance) + +#define FOREACH_SCENE_OBJECT_END \ + ITER_END + +#ifdef __cplusplus +} +#endif + +#endif /* __BKE_COLLECTION_H__ */ diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h index 8fedcd4ab06..0bf7f657f70 100644 --- a/source/blender/blenkernel/BKE_collision.h +++ b/source/blender/blenkernel/BKE_collision.h @@ -148,7 +148,7 @@ void collision_get_collider_velocity(float vel_old[3], float vel_new[3], struct ///////////////////////////////////////////////// /* explicit control over layer mask and dupli recursion */ -struct Object **get_collisionobjects_ext(struct Scene *scene, struct Object *self, struct Group *group, int layer, unsigned int *numcollobj, unsigned int modifier_type, bool dupli); +struct Object **get_collisionobjects_ext(struct Scene *scene, struct Object *self, struct Group *group, unsigned int *numcollobj, unsigned int modifier_type, bool dupli); struct Object **get_collisionobjects(struct Scene *scene, struct Object *self, struct Group *group, unsigned int *numcollobj, unsigned int modifier_type); diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h index 4e0eb5c65ac..cf7e2908360 100644 --- a/source/blender/blenkernel/BKE_constraint.h +++ b/source/blender/blenkernel/BKE_constraint.h @@ -40,6 +40,7 @@ struct ListBase; struct Object; struct Scene; struct bPoseChannel; +struct EvaluationContext; /* ---------------------------------------------------------------------------- */ #ifdef __cplusplus @@ -102,7 +103,7 @@ typedef struct bConstraintTypeInfo { /* evaluation */ /* set the ct->matrix for the given constraint target (at the given ctime) */ - void (*get_target_matrix)(struct bConstraint *con, struct bConstraintOb *cob, struct bConstraintTarget *ct, float ctime); + void (*get_target_matrix)(const struct EvaluationContext *eval_ctx, struct bConstraint *con, struct bConstraintOb *cob, struct bConstraintTarget *ct, float ctime); /* evaluate the constraint for the given time */ void (*evaluate_constraint)(struct bConstraint *con, struct bConstraintOb *cob, struct ListBase *targets); } bConstraintTypeInfo; @@ -147,9 +148,10 @@ void BKE_constraints_clear_evalob(struct bConstraintOb *cob); void BKE_constraint_mat_convertspace( struct Object *ob, struct bPoseChannel *pchan, float mat[4][4], short from, short to, const bool keep_scale); -void BKE_constraint_target_matrix_get(struct Scene *scene, struct bConstraint *con, int n, short ownertype, void *ownerdata, float mat[4][4], float ctime); -void BKE_constraint_targets_for_solving_get(struct bConstraint *con, struct bConstraintOb *ob, struct ListBase *targets, float ctime); -void BKE_constraints_solve(struct ListBase *conlist, struct bConstraintOb *cob, float ctime); +void BKE_constraint_target_matrix_get(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct bConstraint *con, + int n, short ownertype, void *ownerdata, float mat[4][4], float ctime); +void BKE_constraint_targets_for_solving_get(const struct EvaluationContext *eval_ctx, struct bConstraint *con, struct bConstraintOb *ob, struct ListBase *targets, float ctime); +void BKE_constraints_solve(const struct EvaluationContext *eval_ctx, struct ListBase *conlist, struct bConstraintOb *cob, float ctime); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h index 4da6a61cbfa..34192db318e 100644 --- a/source/blender/blenkernel/BKE_context.h +++ b/source/blender/blenkernel/BKE_context.h @@ -40,15 +40,21 @@ extern "C" { struct ARegion; struct bScreen; struct CacheFile; +struct Depsgraph; +struct LayerCollection; struct ListBase; struct Main; struct Object; +struct Base; struct PointerRNA; struct ReportList; struct Scene; +struct SceneCollection; +struct ViewLayer; struct ScrArea; struct SpaceLink; struct View3D; +struct ViewRender; struct RegionView3D; struct StructRNA; struct ToolSettings; @@ -64,10 +70,14 @@ struct bGPDpalettecolor; struct bGPDbrush; struct wmWindow; struct wmWindowManager; +struct RenderEngineType; struct SpaceText; struct SpaceImage; struct SpaceClip; struct ID; +struct EvaluationContext; + +#include "DNA_object_enums.h" /* Structs */ @@ -110,7 +120,8 @@ enum { CTX_MODE_PAINT_VERTEX, CTX_MODE_PAINT_TEXTURE, CTX_MODE_PARTICLE, - CTX_MODE_OBJECT + CTX_MODE_OBJECT, + CTX_MODE_NUM /* must be last */ }; /* Context */ @@ -140,12 +151,15 @@ void CTX_py_dict_set(bContext *C, void *value); struct wmWindowManager *CTX_wm_manager(const bContext *C); struct wmWindow *CTX_wm_window(const bContext *C); +struct WorkSpace *CTX_wm_workspace(const bContext *C); struct bScreen *CTX_wm_screen(const bContext *C); struct ScrArea *CTX_wm_area(const bContext *C); struct SpaceLink *CTX_wm_space_data(const bContext *C); struct ARegion *CTX_wm_region(const bContext *C); void *CTX_wm_region_data(const bContext *C); struct ARegion *CTX_wm_menu(const bContext *C); +struct wmManipulatorGroup *CTX_wm_manipulator_group(const bContext *C); +struct wmMsgBus *CTX_wm_message_bus(const bContext *C); struct ReportList *CTX_wm_reports(const bContext *C); struct View3D *CTX_wm_view3d(const bContext *C); @@ -173,6 +187,7 @@ void CTX_wm_screen_set(bContext *C, struct bScreen *screen); /* to be removed */ void CTX_wm_area_set(bContext *C, struct ScrArea *sa); void CTX_wm_region_set(bContext *C, struct ARegion *region); void CTX_wm_menu_set(bContext *C, struct ARegion *menu); +void CTX_wm_manipulator_group_set(bContext *C, struct wmManipulatorGroup *mgroup); const char *CTX_wm_operator_poll_msg_get(struct bContext *C); void CTX_wm_operator_poll_msg_set(struct bContext *C, const char *msg); @@ -239,9 +254,17 @@ int ctx_data_list_count(const bContext *C, int (*func)(const bContext *, ListBas struct Main *CTX_data_main(const bContext *C); struct Scene *CTX_data_scene(const bContext *C); +struct LayerCollection *CTX_data_layer_collection(const bContext *C); +struct SceneCollection *CTX_data_scene_collection(const bContext *C); +struct ViewLayer *CTX_data_view_layer(const bContext *C); +struct ViewRender *CTX_data_view_render(const bContext *C); +struct RenderEngineType *CTX_data_engine_type(const bContext *C); struct ToolSettings *CTX_data_tool_settings(const bContext *C); const char *CTX_data_mode_string(const bContext *C); +int CTX_data_mode_enum_ex( + const struct Object *obedit, const struct Object *ob, + const eObjectMode object_mode); int CTX_data_mode_enum(const bContext *C); void CTX_data_main_set(bContext *C, struct Main *bmain); @@ -296,6 +319,9 @@ 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); +struct Depsgraph *CTX_data_depsgraph(const bContext *C); + +void CTX_data_eval_ctx(const bContext *C, struct EvaluationContext *eval_ctx); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_crazyspace.h b/source/blender/blenkernel/BKE_crazyspace.h index ee6c5c57678..31542cd6f8a 100644 --- a/source/blender/blenkernel/BKE_crazyspace.h +++ b/source/blender/blenkernel/BKE_crazyspace.h @@ -38,23 +38,24 @@ struct Scene; struct Object; struct BMEditMesh; struct Mesh; +struct EvaluationContext; /* crazyspace.c */ float (*BKE_crazyspace_get_mapped_editverts( - struct Scene *scene, struct Object *obedit))[3]; + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *obedit))[3]; void BKE_crazyspace_set_quats_editmesh( struct BMEditMesh *em, float (*origcos)[3], float (*mappedcos)[3], float (*quats)[4], const bool use_select); void BKE_crazyspace_set_quats_mesh( struct Mesh *me, float (*origcos)[3], float (*mappedcos)[3], float (*quats)[4]); int BKE_crazyspace_get_first_deform_matrices_editbmesh( - struct Scene *, struct Object *, struct BMEditMesh *em, + const struct EvaluationContext *eval_ctx, struct Scene *, struct Object *, struct BMEditMesh *em, float (**deformmats)[3][3], float (**deformcos)[3]); int BKE_sculpt_get_first_deform_matrices( - struct Scene *scene, struct Object *ob, + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]); void BKE_crazyspace_build_sculpt( - struct Scene *scene, struct Object *ob, + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]); #ifdef __cplusplus diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h index 175fa1dad79..fbd05552255 100644 --- a/source/blender/blenkernel/BKE_curve.h +++ b/source/blender/blenkernel/BKE_curve.h @@ -36,6 +36,7 @@ struct BezTriple; struct Curve; struct EditNurb; +struct EvaluationContext; struct GHash; struct ListBase; struct Main; @@ -122,13 +123,14 @@ void BKE_curve_editNurb_keyIndex_free(struct GHash **keyindex); void BKE_curve_editNurb_free(struct Curve *cu); struct ListBase *BKE_curve_editNurbs_get(struct Curve *cu); -float *BKE_curve_make_orco(struct Scene *scene, struct Object *ob, int *r_numVerts); +float *BKE_curve_make_orco(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, int *r_numVerts); float *BKE_curve_surf_make_orco(struct Object *ob); void BKE_curve_bevelList_free(struct ListBase *bev); void BKE_curve_bevelList_make(struct Object *ob, struct ListBase *nurbs, bool for_render); -void BKE_curve_bevel_make(struct Scene *scene, struct Object *ob, struct ListBase *disp, - const bool for_render, const bool use_render_resolution); +void BKE_curve_bevel_make( + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *disp, + const bool for_render, const bool use_render_resolution); void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride); void BKE_curve_forward_diff_tangent_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride); @@ -215,10 +217,17 @@ void BKE_nurb_handles_test(struct Nurb *nu, const bool use_handles); /* **** Depsgraph evaluation **** */ -struct EvaluationContext; - -void BKE_curve_eval_geometry(struct EvaluationContext *eval_ctx, - struct Curve *curve); +void BKE_curve_eval_geometry( + const struct EvaluationContext *eval_ctx, + struct Curve *curve); + +/* Draw Cache */ +enum { + BKE_CURVE_BATCH_DIRTY_ALL = 0, + BKE_CURVE_BATCH_DIRTY_SELECT, +}; +void BKE_curve_batch_cache_dirty(struct Curve *cu, int mode); +void BKE_curve_batch_cache_free(struct Curve *cu); /* curve_decimate.c */ unsigned int BKE_curve_decimate_bezt_array( diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 2cdda34b9b5..51cd4da183a 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -376,15 +376,14 @@ void CustomData_validate_layer_name(const struct CustomData *data, int type, con bool CustomData_verify_versions(struct CustomData *data, int index); /*BMesh specific customdata stuff*/ -void CustomData_to_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, - struct CustomData *ldata, int totloop, int totpoly); -void CustomData_from_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata, int total); -void CustomData_bmesh_update_active_layers(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata); -void CustomData_bmesh_do_versions_update_active_layers(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata); +void CustomData_to_bmeshpoly(struct CustomData *fdata, struct CustomData *ldata, int totloop); +void CustomData_from_bmeshpoly(struct CustomData *fdata, struct CustomData *ldata, int total); +void CustomData_bmesh_update_active_layers(struct CustomData *fdata, struct CustomData *ldata); +void CustomData_bmesh_do_versions_update_active_layers(struct CustomData *fdata, struct CustomData *ldata); void CustomData_bmesh_init_pool(struct CustomData *data, int totelem, const char htype); #ifndef NDEBUG -bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *pdata, CustomData *ldata, bool fallback); +bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *ldata, bool fallback); #endif /* External file storage */ diff --git a/source/blender/blenkernel/BKE_data_transfer.h b/source/blender/blenkernel/BKE_data_transfer.h index 2ee9d8d2408..d5f0313ca64 100644 --- a/source/blender/blenkernel/BKE_data_transfer.h +++ b/source/blender/blenkernel/BKE_data_transfer.h @@ -42,6 +42,7 @@ struct Object; struct Scene; struct SpaceTransform; struct ReportList; +struct EvaluationContext; /* Warning, those def are stored in files (TransferData modifier), *DO NOT* modify those values. */ enum { @@ -129,11 +130,12 @@ enum { }; void BKE_object_data_transfer_layout( - struct Scene *scene, struct Object *ob_src, struct Object *ob_dst, const int data_types, const bool use_delete, + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob_src, + struct Object *ob_dst, const int data_types, const bool use_delete, const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX]); bool BKE_object_data_transfer_mesh( - struct Scene *scene, + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob_src, struct Object *ob_dst, const int data_types, const bool use_create, const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode, struct SpaceTransform *space_transform, const bool auto_transform, @@ -142,7 +144,7 @@ bool BKE_object_data_transfer_mesh( const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup, struct ReportList *reports); bool BKE_object_data_transfer_dm( - struct Scene *scene, + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob_src, struct Object *ob_dst, struct DerivedMesh *dm_dst, const int data_types, bool use_create, const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode, diff --git a/source/blender/blenkernel/BKE_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h deleted file mode 100644 index 40564aeabe9..00000000000 --- a/source/blender/blenkernel/BKE_depsgraph.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * ***** 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) 2004 Blender Foundation. - * All rights reserved. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifndef __BKE_DEPSGRAPH_H__ -#define __BKE_DEPSGRAPH_H__ - -/** \file BKE_depsgraph.h - * \ingroup bke - */ - -/* Dependency Graph - * - * The dependency graph tracks relations between datablocks, and is used to - * determine which datablocks need to be update based on dependencies and - * visibility. - * - * It does not itself execute changes in objects, but rather sorts the objects - * in the appropriate order and sets flags indicating they should be updated. - */ - -#ifdef __cplusplus -extern "C" { -#endif - -struct ID; -struct Main; -struct Object; -struct Scene; - -/* Dependency graph evaluation context - * - * This structure stores all the local dependency graph data, - * which is needed for it's evaluation, - */ -typedef struct EvaluationContext { - int mode; /* evaluation mode */ - float ctime; /* evaluation time */ -} EvaluationContext; - -typedef enum eEvaluationMode { - DAG_EVAL_VIEWPORT = 0, /* evaluate for OpenGL viewport */ - DAG_EVAL_PREVIEW = 1, /* evaluate for render with preview settings */ - DAG_EVAL_RENDER = 2, /* evaluate for render purposes */ -} eEvaluationMode; - -/* DagNode->eval_flags */ -enum { - /* Regardless to curve->path animation flag path is to be evaluated anyway, - * to meet dependencies with such a things as curve modifier and other guys - * who're using curve deform, where_on_path and so. - */ - DAG_EVAL_NEED_CURVE_PATH = 1, - /* Scene evaluation would need to have object's data on CPU, - * meaning no GPU shortcuts is allowed. - */ - DAG_EVAL_NEED_CPU = 2, -}; - -/* Global initialization/deinitialization */ -void DAG_init(void); -void DAG_exit(void); - -/* Build and Update - * - * DAG_scene_relations_update will rebuild the dependency graph for a given - * scene if needed, and sort objects in the scene. - * - * DAG_relations_tag_update will clear all dependency graphs and mark them to - * be rebuilt later. The graph is not rebuilt immediately to avoid slowdowns - * when this function is call multiple times from different operators. - * - * DAG_scene_relations_rebuild forces an immediaterebuild of the dependency - * graph, this is only needed in rare cases - */ - -void DAG_scene_relations_update(struct Main *bmain, struct Scene *sce); -void DAG_scene_relations_validate(struct Main *bmain, struct Scene *sce); -void DAG_relations_tag_update(struct Main *bmain); -void DAG_scene_relations_rebuild(struct Main *bmain, struct Scene *scene); -void DAG_scene_free(struct Scene *sce); - -/* Update Tagging - * - * DAG_scene_update_flags will mark all objects that depend on time (animation, - * physics, ..) to be recalculated, used when changing the current frame. - * - * DAG_on_visible_update will mark all objects that are visible for the first - * time to be updated, for example on file load or changing layer visibility. - * - * DAG_id_tag_update will mark a given datablock to be updated. The flag indicates - * a specific subset to be update (only object transform and data for now). - * - * DAG_id_type_tag marks a particular datablock type as having changing. This does - * not cause any updates but is used by external render engines to detect if for - * example a datablock was removed. */ - -void DAG_scene_update_flags(struct Main *bmain, struct Scene *sce, unsigned int lay, const bool do_time, const bool do_invisible_flush); -void DAG_on_visible_update(struct Main *bmain, const bool do_time); - -void DAG_id_tag_update(struct ID *id, short flag); -void DAG_id_tag_update_ex(struct Main *bmain, struct ID *id, short flag); -void DAG_id_type_tag(struct Main *bmain, short idtype); -int DAG_id_type_tagged(struct Main *bmain, short idtype); - -/* Flushing Tags - * - * DAG_scene_flush_update flushes object recalculation flags immediately to other - * dependencies. Do not use outside of depsgraph.c, this will be removed. - * - * DAG_ids_flush_tagged will flush datablock update flags flags to dependencies, - * use this right before updating to mark all the needed datablocks for update. - * - * DAG_ids_check_recalc and DAG_ids_clear_recalc are used for external render - * engines to detect changes. */ - -void DAG_scene_flush_update(struct Main *bmain, struct Scene *sce, unsigned int lay, const short do_time); -void DAG_ids_flush_tagged(struct Main *bmain); -void DAG_ids_check_recalc(struct Main *bmain, struct Scene *scene, bool time); -void DAG_ids_clear_recalc(struct Main *bmain); - -/* Armature: sorts the bones according to dependencies between them */ - -void DAG_pose_sort(struct Object *ob); - -/* Editors: callbacks to notify editors of datablock changes */ - -void DAG_editors_update_cb(void (*id_func)(struct Main *bmain, struct ID *id), - void (*scene_func)(struct Main *bmain, struct Scene *scene, int updated), - void (*scene_pre_func)(struct Main *bmain, struct Scene *scene, bool time)); - -void DAG_editors_update_pre(struct Main *bmain, struct Scene *scene, bool time); - -/* ** Threaded update ** */ - -/* Initialize the DAG for threaded update. */ -void DAG_threaded_update_begin(struct Scene *scene, - void (*func)(void *node, void *user_data), - void *user_data); - -void DAG_threaded_update_handle_node_updated(void *node_v, - void (*func)(void *node, void *user_data), - void *user_data); - -/* Debugging: print dependency graph for scene or armature object to console */ - -void DAG_print_dependencies(struct Main *bmain, struct Scene *scene, struct Object *ob); - -/* ************************ DAG querying ********************* */ - -struct Object *DAG_get_node_object(void *node_v); -const char *DAG_get_node_name(struct Scene *scene, void *node_v); -short DAG_get_eval_flags_for_object(struct Scene *scene, void *object); -bool DAG_is_acyclic(struct Scene *scene); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h index 9625f05192a..c2229976dd9 100644 --- a/source/blender/blenkernel/BKE_displist.h +++ b/source/blender/blenkernel/BKE_displist.h @@ -86,23 +86,30 @@ void BKE_displist_count(struct ListBase *lb, int *totvert, int *totface, int *to void BKE_displist_free(struct ListBase *lb); bool BKE_displist_has_faces(struct ListBase *lb); -void BKE_displist_make_surf(struct Scene *scene, struct Object *ob, struct ListBase *dispbase, struct DerivedMesh **r_dm_final, - const bool for_render, const bool for_orco, const bool use_render_resolution); -void BKE_displist_make_curveTypes(struct Scene *scene, struct Object *ob, const bool for_orco); -void BKE_displist_make_curveTypes_forRender(struct Scene *scene, struct Object *ob, struct ListBase *dispbase, struct DerivedMesh **r_dm_final, - const bool for_orco, const bool use_render_resolution); -void BKE_displist_make_curveTypes_forOrco(struct Scene *scene, struct Object *ob, struct ListBase *dispbase); -void BKE_displist_make_mball(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); -void BKE_displist_make_mball_forRender(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *dispbase); +void BKE_displist_make_surf( + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *dispbase, + struct DerivedMesh **r_dm_final, const bool for_render, const bool for_orco, const bool use_render_resolution); +void BKE_displist_make_curveTypes( + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, const bool for_orco); +void BKE_displist_make_curveTypes_forRender( + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *dispbase, + struct DerivedMesh **r_dm_final, const bool for_orco, const bool use_render_resolution); +void BKE_displist_make_curveTypes_forOrco( + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *dispbase); +void BKE_displist_make_mball( + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); +void BKE_displist_make_mball_forRender( + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *dispbase); bool BKE_displist_surfindex_get(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4); void BKE_displist_fill(struct ListBase *dispbase, struct ListBase *to, const float normal_proj[3], const bool flipnormal); -float BKE_displist_calc_taper(struct Scene *scene, struct Object *taperobj, int cur, int tot); +float BKE_displist_calc_taper(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *taperobj, int cur, int tot); /* add Orco layer to the displist object which has got derived mesh and return orco */ -float *BKE_displist_make_orco(struct Scene *scene, struct Object *ob, struct DerivedMesh *dm_final, - const bool for_render, const bool use_render_resolution); +float *BKE_displist_make_orco( + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm_final, + const bool for_render, const bool use_render_resolution); void BKE_displist_minmax(struct ListBase *dispbase, float min[3], float max[3]); diff --git a/source/blender/blenkernel/BKE_dynamicpaint.h b/source/blender/blenkernel/BKE_dynamicpaint.h index 5abb53d4c52..21c900a7f0d 100644 --- a/source/blender/blenkernel/BKE_dynamicpaint.h +++ b/source/blender/blenkernel/BKE_dynamicpaint.h @@ -28,6 +28,8 @@ */ struct Scene; +struct ViewLayer; +struct EvaluationContext; /* Actual surface point */ typedef struct PaintSurfaceData { @@ -60,7 +62,8 @@ typedef struct PaintWavePoint { short state; } PaintWavePoint; -struct DerivedMesh *dynamicPaint_Modifier_do(struct DynamicPaintModifierData *pmd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm); +struct DerivedMesh *dynamicPaint_Modifier_do(struct DynamicPaintModifierData *pmd, const struct EvaluationContext *eval_ctx, struct Scene *scene, + struct Object *ob, struct DerivedMesh *dm); void dynamicPaint_Modifier_free(struct DynamicPaintModifierData *pmd); void dynamicPaint_Modifier_copy(struct DynamicPaintModifierData *pmd, struct DynamicPaintModifierData *tsmd); @@ -83,7 +86,7 @@ struct DynamicPaintSurface *get_activeSurface(struct DynamicPaintCanvasSettings /* image sequence baking */ int dynamicPaint_createUVSurface(struct Scene *scene, struct DynamicPaintSurface *surface, float *progress, short *do_update); -int dynamicPaint_calculateFrame(struct DynamicPaintSurface *surface, struct Scene *scene, struct Object *cObject, int frame); +int dynamicPaint_calculateFrame(struct DynamicPaintSurface *surface, const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *cObject, int frame); void dynamicPaint_outputSurfaceImage(struct DynamicPaintSurface *surface, char *filename, short output_layer); /* PaintPoint state */ diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h index 55a9db9b1e5..af1aeff230f 100644 --- a/source/blender/blenkernel/BKE_editmesh.h +++ b/source/blender/blenkernel/BKE_editmesh.h @@ -40,6 +40,7 @@ struct Mesh; struct Scene; struct DerivedMesh; struct MeshStatVis; +struct EvaluationContext; /** * This structure is used for mesh edit-mode. @@ -88,7 +89,6 @@ BMEditMesh *BKE_editmesh_copy(BMEditMesh *em); BMEditMesh *BKE_editmesh_from_object(struct Object *ob); void BKE_editmesh_free_derivedmesh(BMEditMesh *em); void BKE_editmesh_free(BMEditMesh *em); -void BKE_editmesh_update_linked_customdata(BMEditMesh *em); void BKE_editmesh_color_free(BMEditMesh *em); void BKE_editmesh_color_ensure(BMEditMesh *em, const char htype); @@ -99,6 +99,7 @@ float (*BKE_editmesh_vertexCos_get_orco(BMEditMesh *em, int *r_numVerts))[3] void BKE_editmesh_statvis_calc(BMEditMesh *em, struct DerivedMesh *dm, const struct MeshStatVis *statvis); -float (*BKE_editmesh_vertexCos_get(struct BMEditMesh *em, struct Scene *scene, int *r_numVerts))[3]; +float (*BKE_editmesh_vertexCos_get( + const struct EvaluationContext *eval_ctx, struct BMEditMesh *em, struct Scene *scene, int *r_numVerts))[3]; #endif /* __BKE_EDITMESH_H__ */ diff --git a/source/blender/blenkernel/BKE_editmesh_tangent.h b/source/blender/blenkernel/BKE_editmesh_tangent.h new file mode 100644 index 00000000000..9553fbc1a5c --- /dev/null +++ b/source/blender/blenkernel/BKE_editmesh_tangent.h @@ -0,0 +1,40 @@ +/* + * ***** 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. + * + * Contributor(s): Joseph Eagar. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BKE_EDITMESH_TANGENT_H__ +#define __BKE_EDITMESH_TANGENT_H__ + +/** \file BKE_editmesh_tangent.h + * \ingroup bke + */ + +void BKE_editmesh_loop_tangent_calc( + BMEditMesh *em, bool calc_active_tangent, + const char (*tangent_names)[MAX_NAME], int tangent_names_len, + const float (*poly_normals)[3], + const float (*loop_normals)[3], + const float (*vert_orco)[3], + CustomData *dm_loopdata_out, + const uint dm_loopdata_out_len, + short *tangent_mask_curr_p); + +#endif /* __BKE_EDITMESH_TANGENT_H__ */ diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h index aa45132cbe9..6fa19d4aaf6 100644 --- a/source/blender/blenkernel/BKE_effect.h +++ b/source/blender/blenkernel/BKE_effect.h @@ -44,6 +44,7 @@ struct Group; struct ParticleSimulationData; struct ParticleData; struct ParticleKey; +struct EvaluationContext; struct EffectorWeights *BKE_add_effector_weights(struct Group *group); struct PartDeflect *object_add_collision_fields(int type); @@ -93,6 +94,7 @@ typedef struct EffectorData { typedef struct EffectorCache { struct EffectorCache *next, *prev; + const struct EvaluationContext *eval_ctx; struct Scene *scene; struct Object *ob; struct ParticleSystem *psys; @@ -110,9 +112,11 @@ typedef struct EffectorCache { } EffectorCache; void free_partdeflect(struct PartDeflect *pd); -struct ListBase *pdInitEffectors(struct Scene *scene, struct Object *ob_src, struct ParticleSystem *psys_src, struct EffectorWeights *weights, bool for_simulation); +struct ListBase *pdInitEffectors( + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob_src, struct ParticleSystem *psys_src, + struct EffectorWeights *weights, bool for_simulation); void pdEndEffectors(struct ListBase **effectors); -void pdPrecalculateEffectors(struct ListBase *effectors); +void pdPrecalculateEffectors(const struct EvaluationContext *eval_ctx, struct ListBase *effectors); void pdDoEffectors(struct ListBase *effectors, struct ListBase *colliders, struct EffectorWeights *weights, struct EffectedPoint *point, float *force, float *impulse); void pd_point_from_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleKey *state, struct EffectedPoint *point); diff --git a/source/blender/blenkernel/BKE_fluidsim.h b/source/blender/blenkernel/BKE_fluidsim.h index 6501c968abc..4ec58b2a0e5 100644 --- a/source/blender/blenkernel/BKE_fluidsim.h +++ b/source/blender/blenkernel/BKE_fluidsim.h @@ -36,10 +36,11 @@ struct Object; struct Scene; struct FluidsimSettings; struct MVert; +struct EvaluationContext; /* old interface */ -void initElbeemMesh(struct Scene *scene, struct Object *ob, +void initElbeemMesh(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, int *numVertices, float **vertices, int *numTriangles, int **triangles, int useGlobalCoords, int modifierIndex); diff --git a/source/blender/blenkernel/BKE_freestyle.h b/source/blender/blenkernel/BKE_freestyle.h index 1045fde0039..f7368683d93 100644 --- a/source/blender/blenkernel/BKE_freestyle.h +++ b/source/blender/blenkernel/BKE_freestyle.h @@ -49,7 +49,7 @@ typedef struct FreestyleModuleSettings FreestyleModuleSettings; /* FreestyleConfig */ void BKE_freestyle_config_init(FreestyleConfig *config); -void BKE_freestyle_config_free(FreestyleConfig *config); +void BKE_freestyle_config_free(FreestyleConfig *config, const bool do_id_user); void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *config, const int flag); /* FreestyleConfig.modules */ diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h index 790c8051ace..80a8f750d20 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -128,10 +128,11 @@ enum { G_DEBUG_DEPSGRAPH_NO_THREADS = (1 << 11), /* single threaded depsgraph */ G_DEBUG_GPU = (1 << 12), /* gpu debug */ G_DEBUG_IO = (1 << 13), /* IO Debugging (for Collada, ...)*/ + G_DEBUG_GPU_SHADERS = (1 << 14), /* GLSL shaders */ }; #define G_DEBUG_ALL (G_DEBUG | G_DEBUG_FFMPEG | G_DEBUG_PYTHON | G_DEBUG_EVENTS | G_DEBUG_WM | G_DEBUG_JOBS | \ - G_DEBUG_FREESTYLE | G_DEBUG_DEPSGRAPH | G_DEBUG_GPU_MEM | G_DEBUG_IO) + G_DEBUG_FREESTYLE | G_DEBUG_DEPSGRAPH | G_DEBUG_GPU_MEM | G_DEBUG_IO | G_DEBUG_GPU_SHADERS) /* G.fileflags */ diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h index e07dd259970..74255cfc941 100644 --- a/source/blender/blenkernel/BKE_group.h +++ b/source/blender/blenkernel/BKE_group.h @@ -41,17 +41,45 @@ struct Object; struct Scene; void BKE_group_free(struct Group *group); +void BKE_group_init(struct Group *group); struct Group *BKE_group_add(struct Main *bmain, const char *name); void BKE_group_copy_data(struct Main *bmain, struct Group *group_dst, const struct Group *group_src, const int flag); struct Group *BKE_group_copy(struct Main *bmain, const struct Group *group); void BKE_group_make_local(struct Main *bmain, struct Group *group, const bool lib_local); -bool BKE_group_object_add(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base); -bool BKE_group_object_unlink(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base); +bool BKE_group_object_add(struct Group *group, struct Object *ob); +bool BKE_group_object_unlink(struct Group *group, struct Object *ob); struct Group *BKE_group_object_find(struct Group *group, struct Object *ob); bool BKE_group_object_exists(struct Group *group, struct Object *ob); bool BKE_group_object_cyclic_check(struct Main *bmain, struct Object *object, struct Group *group); bool BKE_group_is_animated(struct Group *group, struct Object *parent); -void BKE_group_handle_recalc_and_update(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *parent, struct Group *group); +void BKE_group_handle_recalc_and_update(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *parent, struct Group *group); + +/* Dependency graph evaluation. */ + +void BKE_group_eval_view_layers(const struct EvaluationContext *eval_ctx, + struct Group *group); + +/* Helper macros. */ + +#define FOREACH_GROUP_BASE(_group, _base) \ + for (Base *_base = (Base *)(_group)->view_layer->object_bases.first; \ + _base; \ + _base = _base->next) \ + { + +#define FOREACH_GROUP_BASE_END \ + } + +#define FOREACH_GROUP_OBJECT(_group, _object) \ + for (Base *_base = (Base *)(_group)->view_layer->object_bases.first; \ + _base; \ + _base = _base->next) \ + { \ + Object *_object = _base->object; \ + BLI_assert(_object != NULL); + +#define FOREACH_GROUP_OBJECT_END \ + } #endif /* __BKE_GROUP_H__ */ diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h index 5d8cd02756d..02912739e86 100644 --- a/source/blender/blenkernel/BKE_idprop.h +++ b/source/blender/blenkernel/BKE_idprop.h @@ -32,6 +32,10 @@ #include "BLI_compiler_attrs.h" +#ifdef __cplusplus +extern "C" { +#endif + struct IDProperty; struct ID; @@ -91,6 +95,7 @@ void IDP_ReplaceGroupInGroup(struct IDProperty *dest, const struct IDProperty *s 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(); +void IDP_MergeGroup_ex(IDProperty *dest, const IDProperty *src, const bool do_overwrite, const int flag) ATTR_NONNULL(); bool IDP_AddToGroup(struct IDProperty *group, struct IDProperty *prop) ATTR_NONNULL(); bool IDP_InsertToGroup(struct IDProperty *group, struct IDProperty *previous, struct IDProperty *pnew) ATTR_NONNULL(1 /* group */, 3 /* pnew */); @@ -118,6 +123,8 @@ void IDP_ClearProperty(IDProperty *prop); void IDP_RelinkProperty(struct IDProperty *prop); +void IDP_Reset(IDProperty *prop, const IDProperty *reference); + #define IDP_Int(prop) ((prop)->data.val) #define IDP_Array(prop) ((prop)->data.pointer) /* C11 const correctness for casts */ @@ -150,4 +157,8 @@ void IDP_RelinkProperty(struct IDProperty *prop); void IDP_spit(IDProperty *prop); #endif +#ifdef __cplusplus +} +#endif + #endif /* __BKE_IDPROP_H__ */ diff --git a/source/blender/blenkernel/BKE_lamp.h b/source/blender/blenkernel/BKE_lamp.h index 3673e657b33..aa655c66477 100644 --- a/source/blender/blenkernel/BKE_lamp.h +++ b/source/blender/blenkernel/BKE_lamp.h @@ -50,8 +50,6 @@ struct Lamp *BKE_lamp_localize(struct Lamp *la) ATTR_WARN_UNUSED_RESULT; void BKE_lamp_make_local(struct Main *bmain, struct Lamp *la, const bool lib_local); void BKE_lamp_free(struct Lamp *la); -void lamp_drivers_update(struct Scene *scene, struct Lamp *la, float ctime); - #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h index f7d006785d2..1cdf193f054 100644 --- a/source/blender/blenkernel/BKE_lattice.h +++ b/source/blender/blenkernel/BKE_lattice.h @@ -43,6 +43,7 @@ struct Scene; struct DerivedMesh; struct BPoint; struct MDeformVert; +struct EvaluationContext; void BKE_lattice_resize(struct Lattice *lt, int u, int v, int w, struct Object *ltOb); void BKE_lattice_init(struct Lattice *lt); @@ -61,10 +62,11 @@ void end_latt_deform(struct LatticeDeformData *lattice_deform_data); bool object_deform_mball(struct Object *ob, struct ListBase *dispbase); void outside_lattice(struct Lattice *lt); -void curve_deform_verts(struct Scene *scene, struct Object *cuOb, struct Object *target, - struct DerivedMesh *dm, float (*vertexCos)[3], - int numVerts, const char *vgroup, short defaxis); -void curve_deform_vector(struct Scene *scene, struct Object *cuOb, struct Object *target, +void curve_deform_verts( + struct Object *cuOb, struct Object *target, + struct DerivedMesh *dm, float (*vertexCos)[3], + int numVerts, const char *vgroup, short defaxis); +void curve_deform_vector(struct Object *cuOb, struct Object *target, float orco[3], float vec[3], float mat[3][3], int no_rot_axis); void lattice_deform_verts(struct Object *laOb, struct Object *target, @@ -77,7 +79,7 @@ void armature_deform_verts(struct Object *armOb, struct Object *target, float (*BKE_lattice_vertexcos_get(struct Object *ob, int *r_numVerts))[3]; void BKE_lattice_vertexcos_apply(struct Object *ob, float (*vertexCos)[3]); -void BKE_lattice_modifiers_calc(struct Scene *scene, struct Object *ob); +void BKE_lattice_modifiers_calc(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); struct MDeformVert *BKE_lattice_deform_verts_get(struct Object *lattice); struct BPoint *BKE_lattice_active_point_get(struct Lattice *lt); @@ -101,7 +103,15 @@ void BKE_lattice_bitmap_from_flag(struct Lattice *lt, unsigned int *bitmap, cons struct EvaluationContext; -void BKE_lattice_eval_geometry(struct EvaluationContext *eval_ctx, +void BKE_lattice_eval_geometry(const struct EvaluationContext *eval_ctx, struct Lattice *latt); +/* Draw Cache */ +enum { + BKE_LATTICE_BATCH_DIRTY_ALL = 0, + BKE_LATTICE_BATCH_DIRTY_SELECT, +}; +void BKE_lattice_batch_cache_dirty(struct Lattice *lt, int mode); +void BKE_lattice_batch_cache_free(struct Lattice *lt); + #endif /* __BKE_LATTICE_H__ */ diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h new file mode 100644 index 00000000000..633cb2c6044 --- /dev/null +++ b/source/blender/blenkernel/BKE_layer.h @@ -0,0 +1,304 @@ +/* + * ***** 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. + * + * Contributor(s): Blender Foundation, Dalai Felinto + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BKE_LAYER_H__ +#define __BKE_LAYER_H__ + +/** \file blender/blenkernel/BKE_layer.h + * \ingroup bke + */ + +#include "BKE_collection.h" + +#include "DNA_scene_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define TODO_LAYER_OVERRIDE /* CollectionOverride */ +#define TODO_LAYER_OPERATORS /* collection mamanger and property panel operators */ +#define TODO_LAYER /* generic todo */ + +#define ROOT_PROP "root" + +struct Base; +struct EvaluationContext; +struct Group; +struct ID; +struct IDProperty; +struct LayerCollection; +struct ListBase; +struct Main; +struct Object; +struct RenderEngine; +struct Scene; +struct SceneCollection; +struct ViewLayer; +struct WorkSpace; + +void BKE_layer_exit(void); + +struct ViewLayer *BKE_view_layer_from_scene_get(const struct Scene *scene); +struct ViewLayer *BKE_view_layer_from_workspace_get(const struct Scene *scene, const struct WorkSpace *workspace); +struct ViewLayer *BKE_view_layer_add(struct Scene *scene, const char *name); +struct ViewLayer *BKE_view_layer_group_add(struct Group *group); + +/* DEPRECATED */ +struct ViewLayer *BKE_view_layer_context_active_PLACEHOLDER(const struct Scene *scene); + +void BKE_view_layer_free(struct ViewLayer *view_layer); +void BKE_view_layer_free_ex(struct ViewLayer *view_layer, const bool do_id_user); + +void BKE_view_layer_selected_objects_tag(struct ViewLayer *view_layer, const int tag); + +struct Object *BKE_view_layer_camera_find(struct ViewLayer *view_layer); +struct ViewLayer *BKE_view_layer_first_from_id(const struct ID *owner_id); +struct ViewLayer *BKE_view_layer_find_from_collection(const struct ID *owner_id, struct LayerCollection *lc); +struct Base *BKE_view_layer_base_find(struct ViewLayer *view_layer, struct Object *ob); +void BKE_view_layer_base_deselect_all(struct ViewLayer *view_layer); +void BKE_view_layer_base_select(struct ViewLayer *view_layer, struct Base *selbase); + +void BKE_layer_collection_sync_flags( + struct ID *owner_id, + struct SceneCollection *scene_collection_dst, + struct SceneCollection *scene_collection_src); + +void BKE_view_layer_copy_data( + struct ViewLayer *view_layer_dst, struct ViewLayer *view_layer_src, + struct SceneCollection *mc_dst, struct SceneCollection *mc_src, + const int flag); + +struct LayerCollection *BKE_layer_collection_duplicate(struct ID *owner_id, struct LayerCollection *layer_collection); + +void BKE_layer_collection_free(struct ViewLayer *view_layer, struct LayerCollection *lc); + +struct LayerCollection *BKE_layer_collection_get_active(struct ViewLayer *view_layer); +struct LayerCollection *BKE_layer_collection_get_active_ensure(struct Scene *scene, struct ViewLayer *view_layer); + +int BKE_layer_collection_count(struct ViewLayer *view_layer); + +struct LayerCollection *BKE_layer_collection_from_index(struct ViewLayer *view_layer, const int index); +int BKE_layer_collection_findindex(struct ViewLayer *view_layer, const struct LayerCollection *lc); + +bool BKE_layer_collection_move_above(const struct ID *owner_id, struct LayerCollection *lc_dst, struct LayerCollection *lc_src); +bool BKE_layer_collection_move_below(const struct ID *owner_id, struct LayerCollection *lc_dst, struct LayerCollection *lc_src); +bool BKE_layer_collection_move_into(const struct ID *owner_id, struct LayerCollection *lc_dst, struct LayerCollection *lc_src); + +void BKE_layer_collection_resync(const struct ID *owner_id, const struct SceneCollection *sc); + +struct LayerCollection *BKE_collection_link(struct ViewLayer *view_layer, struct SceneCollection *sc); + +void BKE_collection_unlink(struct ViewLayer *view_layer, struct LayerCollection *lc); + +void BKE_collection_enable(struct ViewLayer *view_layer, struct LayerCollection *lc); + +bool BKE_view_layer_has_collection(struct ViewLayer *view_layer, const struct SceneCollection *sc); +bool BKE_scene_has_object(struct Scene *scene, struct Object *ob); + +void BKE_layer_collection_objects_select(struct LayerCollection *layer_collection); + +/* syncing */ + +void BKE_layer_sync_new_scene_collection(struct ID *owner_id, const struct SceneCollection *sc_parent, struct SceneCollection *sc); +void BKE_layer_sync_object_link(const struct ID *owner_id, struct SceneCollection *sc, struct Object *ob); +void BKE_layer_sync_object_unlink(const struct ID *owner_id, struct SceneCollection *sc, struct Object *ob); + +/* override */ + +void BKE_override_view_layer_datablock_add(struct ViewLayer *view_layer, int id_type, const char *data_path, const struct ID *owner_id); +void BKE_override_view_layer_int_add(struct ViewLayer *view_layer, int id_type, const char *data_path, const int value); + +void BKE_override_layer_collection_boolean_add(struct LayerCollection *layer_collection, int id_type, const char *data_path, const bool value); + +/* engine settings */ +typedef void (*EngineSettingsCB)(struct RenderEngine *engine, struct IDProperty *props); + +struct IDProperty *BKE_layer_collection_engine_evaluated_get(struct Object *ob, const int type, const char *engine_name); +struct IDProperty *BKE_layer_collection_engine_collection_get(struct LayerCollection *lc, const int type, const char *engine_name); +struct IDProperty *BKE_layer_collection_engine_scene_get(struct Scene *scene, const int type, const char *engine_name); +void BKE_layer_collection_engine_settings_callback_register(struct Main *bmain, const char *engine_name, EngineSettingsCB func); +void BKE_layer_collection_engine_settings_callback_free(void); +void BKE_layer_collection_engine_settings_create(struct IDProperty *root); +void BKE_layer_collection_engine_settings_validate_scene(struct Scene *scene); +void BKE_layer_collection_engine_settings_validate_collection(struct LayerCollection *lc); + +struct IDProperty *BKE_view_layer_engine_evaluated_get(struct ViewLayer *view_layer, const int type, const char *engine_name); +struct IDProperty *BKE_view_layer_engine_layer_get(struct ViewLayer *view_layer, const int type, const char *engine_name); +struct IDProperty *BKE_view_layer_engine_scene_get(struct Scene *scene, const int type, const char *engine_name); +void BKE_view_layer_engine_settings_callback_register(struct Main *bmain, const char *engine_name, EngineSettingsCB func); +void BKE_view_layer_engine_settings_callback_free(void); +void BKE_view_layer_engine_settings_validate_scene(struct Scene *scene); +void BKE_view_layer_engine_settings_validate_layer(struct ViewLayer *view_layer); +void BKE_view_layer_engine_settings_create(struct IDProperty *root); + +void BKE_collection_engine_property_add_float(struct IDProperty *props, const char *name, float value); +void BKE_collection_engine_property_add_float_array( + struct IDProperty *props, const char *name, const float *values, const int array_length); +void BKE_collection_engine_property_add_int(struct IDProperty *props, const char *name, int value); +void BKE_collection_engine_property_add_bool(struct IDProperty *props, const char *name, bool value); + +int BKE_collection_engine_property_value_get_int(struct IDProperty *props, const char *name); +float BKE_collection_engine_property_value_get_float(struct IDProperty *props, const char *name); +const float *BKE_collection_engine_property_value_get_float_array(struct IDProperty *props, const char *name); +bool BKE_collection_engine_property_value_get_bool(struct IDProperty *props, const char *name); +void BKE_collection_engine_property_value_set_int(struct IDProperty *props, const char *name, int value); +void BKE_collection_engine_property_value_set_float(struct IDProperty *props, const char *name, float value); +void BKE_collection_engine_property_value_set_float_array(struct IDProperty *props, const char *name, const float *values); +void BKE_collection_engine_property_value_set_bool(struct IDProperty *props, const char *name, bool value); + +/* evaluation */ + +void BKE_layer_eval_layer_collection_pre(const struct EvaluationContext *eval_ctx, + struct ID *owner_id, + struct ViewLayer *view_layer); +void BKE_layer_eval_layer_collection(const struct EvaluationContext *eval_ctx, + struct LayerCollection *layer_collection, + struct LayerCollection *parent_layer_collection); +void BKE_layer_eval_layer_collection_post(const struct EvaluationContext *eval_ctx, + struct ViewLayer *view_layer); + +/* iterators */ + +void BKE_selected_objects_iterator_begin(BLI_Iterator *iter, void *data_in); +void BKE_selected_objects_iterator_next(BLI_Iterator *iter); +void BKE_selected_objects_iterator_end(BLI_Iterator *iter); + +void BKE_visible_objects_iterator_begin(BLI_Iterator *iter, void *data_in); +void BKE_visible_objects_iterator_next(BLI_Iterator *iter); +void BKE_visible_objects_iterator_end(BLI_Iterator *iter); + +void BKE_renderable_objects_iterator_begin(BLI_Iterator *iter, void *data_in); +void BKE_renderable_objects_iterator_next(BLI_Iterator *iter); +void BKE_renderable_objects_iterator_end(BLI_Iterator *iter); + +void BKE_selected_bases_iterator_begin(BLI_Iterator *iter, void *data_in); +void BKE_selected_bases_iterator_next(BLI_Iterator *iter); +void BKE_selected_bases_iterator_end(BLI_Iterator *iter); + +void BKE_visible_bases_iterator_begin(BLI_Iterator *iter, void *data_in); +void BKE_visible_bases_iterator_next(BLI_Iterator *iter); +void BKE_visible_bases_iterator_end(BLI_Iterator *iter); + +#define FOREACH_SELECTED_OBJECT(view_layer, _instance) \ + ITER_BEGIN(BKE_selected_objects_iterator_begin, \ + BKE_selected_objects_iterator_next, \ + BKE_selected_objects_iterator_end, \ + view_layer, Object *, _instance) + +#define FOREACH_SELECTED_OBJECT_END \ + ITER_END + +#define FOREACH_VISIBLE_OBJECT(view_layer, _instance) \ + ITER_BEGIN(BKE_visible_objects_iterator_begin, \ + BKE_visible_objects_iterator_next, \ + BKE_visible_objects_iterator_end, \ + view_layer, Object *, _instance) + +#define FOREACH_VISIBLE_OBJECT_END \ + ITER_END + +#define FOREACH_SELECTED_BASE(view_layer, _instance) \ + ITER_BEGIN(BKE_selected_bases_iterator_begin, \ + BKE_selected_bases_iterator_next, \ + BKE_selected_bases_iterator_end, \ + view_layer, Base *, _instance) + +#define FOREACH_SELECTED_BASE_END \ + ITER_END + +#define FOREACH_VISIBLE_BASE(view_layer, _instance) \ + ITER_BEGIN(BKE_visible_bases_iterator_begin, \ + BKE_visible_bases_iterator_next, \ + BKE_visible_bases_iterator_end, \ + view_layer, Base *, _instance) + +#define FOREACH_VISIBLE_BASE_END \ + ITER_END + + +#define FOREACH_OBJECT(view_layer, _instance) \ +{ \ + Object *_instance; \ + Base *base; \ + for (base = (view_layer)->object_bases.first; base; base = base->next) { \ + _instance = base->object; + +#define FOREACH_OBJECT_END \ + } \ +} + +#define FOREACH_OBJECT_FLAG(scene, view_layer, flag, _instance) \ +{ \ + IteratorBeginCb func_begin; \ + IteratorCb func_next, func_end; \ + void *data_in; \ + \ + if (flag == SELECT) { \ + func_begin = &BKE_selected_objects_iterator_begin; \ + func_next = &BKE_selected_objects_iterator_next; \ + func_end = &BKE_selected_objects_iterator_end; \ + data_in = (view_layer); \ + } \ + else { \ + func_begin = BKE_scene_objects_iterator_begin; \ + func_next = BKE_scene_objects_iterator_next; \ + func_end = BKE_scene_objects_iterator_end; \ + data_in = (scene); \ + } \ + ITER_BEGIN(func_begin, func_next, func_end, data_in, Object *, _instance) + + +#define FOREACH_OBJECT_FLAG_END \ + ITER_END \ +} + +typedef struct ObjectsRenderableIteratorData { + struct Scene *scene; + struct Base base_temp; + struct Scene scene_temp; + + struct { + struct ViewLayer *view_layer; + struct Base *base; + struct Scene *set; + } iter; +} ObjectsRenderableIteratorData; + +#define FOREACH_OBJECT_RENDERABLE(scene_, _instance) \ + ObjectsRenderableIteratorData data_ = { \ + .scene = (scene_), \ + }; \ + ITER_BEGIN(BKE_renderable_objects_iterator_begin, \ + BKE_renderable_objects_iterator_next, \ + BKE_renderable_objects_iterator_end, \ + &data_, Object *, _instance) + + +#define FOREACH_OBJECT_RENDERABLE_END \ + ITER_END + +#ifdef __cplusplus +} +#endif + +#endif /* __BKE_LAYER_H__ */ diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index 9e1bc2611fb..f3df8b9b363 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -148,6 +148,7 @@ bool id_make_local(struct Main *bmain, struct ID *id, const bool test, const boo bool id_single_user(struct bContext *C, struct ID *id, struct PointerRNA *ptr, struct PropertyRNA *prop); bool id_copy(struct Main *bmain, const struct ID *id, struct ID **newid, bool test); bool BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, const int flag, const bool test); +void BKE_id_swap(struct Main *bmain, struct ID *id_a, struct ID *id_b); void id_sort_by_name(struct ListBase *lb, struct ID *id); void BKE_id_expand_local(struct Main *bmain, struct ID *id); void BKE_id_copy_ensure_local(struct Main *bmain, const struct ID *old_id, struct ID *new_id); @@ -158,7 +159,7 @@ void id_clear_lib_data_ex(struct Main *bmain, struct ID *id, const bool id_in_ma struct ListBase *which_libbase(struct Main *mainlib, short type); -#define MAX_LIBARRAY 35 +#define MAX_LIBARRAY 37 int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]); /* Main API */ diff --git a/source/blender/blenkernel/BKE_library_override.h b/source/blender/blenkernel/BKE_library_override.h new file mode 100644 index 00000000000..35672cb5ded --- /dev/null +++ b/source/blender/blenkernel/BKE_library_override.h @@ -0,0 +1,87 @@ +/* + * ***** 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) 2016 by Blender Foundation. + * All rights reserved. + * + * Contributor(s): Bastien Montagne. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BKE_LIBRARY_OVERRIDE_H__ +#define __BKE_LIBRARY_OVERRIDE_H__ + +/** \file BKE_library_override.h + * \ingroup bke + * \since December 2016 + * \author mont29 + */ + +struct ID; +struct IDOverrideStatic; +struct IDOverrideStaticProperty; +struct IDOverrideStaticPropertyOperation; +struct Main; + +struct IDOverrideStatic *BKE_override_static_init(struct ID *local_id, struct ID *reference_id); +void BKE_override_static_copy(struct ID *dst_id, const struct ID *src_id); +void BKE_override_static_clear(struct IDOverrideStatic *override); +void BKE_override_static_free(struct IDOverrideStatic **override); + +struct ID *BKE_override_static_create_from_id(struct Main *bmain, struct ID *reference_id); +bool BKE_override_static_create_from_tag(struct Main *bmain); + +struct IDOverrideStaticProperty *BKE_override_static_property_find(struct IDOverrideStatic *override, const char *rna_path); +struct IDOverrideStaticProperty *BKE_override_static_property_get(struct IDOverrideStatic *override, const char *rna_path, bool *r_created); +void BKE_override_static_property_delete(struct IDOverrideStatic *override, struct IDOverrideStaticProperty *override_property); + +struct IDOverrideStaticPropertyOperation *BKE_override_static_property_operation_find( + struct IDOverrideStaticProperty *override_property, + const char *subitem_refname, const char *subitem_locname, + const int subitem_refindex, const int subitem_locindex, const bool strict, bool *r_strict); +struct IDOverrideStaticPropertyOperation *BKE_override_static_property_operation_get( + struct IDOverrideStaticProperty *override_property, const short operation, + const char *subitem_refname, const char *subitem_locname, + const int subitem_refindex, const int subitem_locindex, + const bool strict, bool *r_strict, bool *r_created); +void BKE_override_static_property_operation_delete( + struct IDOverrideStaticProperty *override_property, struct IDOverrideStaticPropertyOperation *override_property_operation); + +bool BKE_override_static_status_check_local(struct ID *local); +bool BKE_override_static_status_check_reference(struct ID *local); + +bool BKE_override_static_operations_create(struct ID *local); +void BKE_main_override_static_operations_create(struct Main *bmain); + +void BKE_override_static_update(struct Main *bmain, struct ID *local); +void BKE_main_override_static_update(struct Main *bmain); + + +/* Storage (.blend file writing) part. */ + +/* For now, we just use a temp main list. */ +typedef struct Main OverrideStaticStorage; + +OverrideStaticStorage *BKE_override_static_operations_store_initialize(void); +struct ID *BKE_override_static_operations_store_start(OverrideStaticStorage *override_storage, struct ID *local); +void BKE_override_static_operations_store_end(OverrideStaticStorage *override_storage, struct ID *local); +void BKE_override_static_operations_store_finalize(OverrideStaticStorage *override_storage); + + + +#endif /* __BKE_LIBRARY_OVERRIDE_H__ */ diff --git a/source/blender/blenkernel/BKE_library_query.h b/source/blender/blenkernel/BKE_library_query.h index d6e7d98f371..b66fc0aab16 100644 --- a/source/blender/blenkernel/BKE_library_query.h +++ b/source/blender/blenkernel/BKE_library_query.h @@ -56,6 +56,9 @@ enum { * How to handle that kind of cases totally depends on what caller code is doing... */ IDWALK_CB_LOOPBACK = (1 << 4), + /** That ID is used as static override's reference by its owner. */ + IDWALK_CB_STATIC_OVERRIDE_REFERENCE = (1 << 5), + /** * Adjusts #ID.us reference-count. * \note keep in sync with 'newlibadr_us' use in readfile.c diff --git a/source/blender/blenkernel/BKE_library_remap.h b/source/blender/blenkernel/BKE_library_remap.h index fd37fd762f4..3425ca011b7 100644 --- a/source/blender/blenkernel/BKE_library_remap.h +++ b/source/blender/blenkernel/BKE_library_remap.h @@ -51,6 +51,8 @@ enum { * This is needed e.g. in reload scenario, since we have to ensure remapping of Armature data of local proxy * is also performed. Usual nightmare... */ ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE = 1 << 4, + /* Do not remap static override pointers. */ + ID_REMAP_SKIP_STATIC_OVERRIDE = 1 << 5, }; /* Note: Requiring new_id to be non-null, this *may* not be the case ultimately, but makes things simpler for now. */ diff --git a/source/blender/blenkernel/BKE_lightprobe.h b/source/blender/blenkernel/BKE_lightprobe.h new file mode 100644 index 00000000000..a769b6653d7 --- /dev/null +++ b/source/blender/blenkernel/BKE_lightprobe.h @@ -0,0 +1,46 @@ +/* + * ***** 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) Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BKE_LIGHTPROBE_H__ +#define __BKE_LIGHTPROBE_H__ + +/** \file BKE_lightprobe.h + * \ingroup bke + * \brief General operations for probes. + */ + +struct Main; +struct LightProbe; + +void BKE_lightprobe_init(struct LightProbe *probe); +void *BKE_lightprobe_add(struct Main *bmain, const char *name); +void BKE_lightprobe_copy_data(struct Main *bmain, struct LightProbe *probe_dst, const struct LightProbe *probe_src, const int flag); +struct LightProbe *BKE_lightprobe_copy(struct Main *bmain, const struct LightProbe *probe); +void BKE_lightprobe_make_local(struct Main *bmain, struct LightProbe *probe, const bool lib_local); +void BKE_lightprobe_free(struct LightProbe *probe); + +#endif /* __BKE_LIGHTPROBE_H__ */ diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index d8318bfcf5d..79f56cf25ef 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -108,6 +108,7 @@ typedef struct Main { ListBase vfont; ListBase text; ListBase speaker; + ListBase lightprobe; ListBase sound; ListBase group; ListBase armature; @@ -123,6 +124,7 @@ typedef struct Main { ListBase mask; ListBase linestyle; ListBase cachefiles; + ListBase workspaces; char id_tag_update[MAX_LIBARRAY]; diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 5598f0dc473..8b9fea071b0 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -145,7 +145,6 @@ void BKE_mask_update_display(struct Mask *mask, float ctime); void BKE_mask_evaluate_all_masks(struct Main *bmain, float ctime, const bool do_newframe); void BKE_mask_evaluate(struct Mask *mask, const float ctime, const bool do_newframe); void BKE_mask_layer_evaluate(struct MaskLayer *masklay, const float ctime, const bool do_newframe); -void BKE_mask_update_scene(struct Main *bmain, struct Scene *scene); void BKE_mask_parent_init(struct MaskParent *parent); void BKE_mask_calc_handle_adjacent_interp(struct MaskSpline *spline, struct MaskSplinePoint *point, const float u); void BKE_mask_calc_tangent_polyline(struct MaskSpline *spline, struct MaskSplinePoint *point, float t[2]); diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index f7850913014..f4c98fc0aea 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -87,6 +87,10 @@ short BKE_object_material_slot_find_index(struct Object *ob, struct Material *ma bool BKE_object_material_slot_add(struct Object *ob); bool BKE_object_material_slot_remove(struct Object *ob); +struct Image *BKE_object_material_edit_image_get(struct Object *ob, short mat_nr); +struct Image **BKE_object_material_edit_image_get_array(struct Object *ob); +bool BKE_object_material_edit_image_set(struct Object *ob, short mat_nr, struct Image *image); + void BKE_texpaint_slot_refresh_cache(struct Scene *scene, struct Material *ma); void BKE_texpaint_slots_refresh_object(struct Scene *scene, struct Object *ob); @@ -106,17 +110,17 @@ bool material_in_material(struct Material *parmat, struct Material *mat); void ramp_blend(int type, float r_col[3], const float fac, const float col[3]); -/* driver update hacks */ -void material_drivers_update(struct Scene *scene, struct Material *mat, float ctime); - /* copy/paste */ void clear_matcopybuf(void); void free_matcopybuf(void); void copy_matcopybuf(struct Material *ma); void paste_matcopybuf(struct Material *ma); -/* handle backward compatibility for tface/materials called from doversion */ -int do_version_tface(struct Main *main); +/* Evaluation. */ + +struct EvaluationContext; + +void BKE_material_eval(const struct EvaluationContext *eval_ctx, struct Material *material); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h index f02704ba903..9db277f95fb 100644 --- a/source/blender/blenkernel/BKE_mball.h +++ b/source/blender/blenkernel/BKE_mball.h @@ -73,7 +73,18 @@ void BKE_mball_select_swap(struct MetaBall *mb); struct EvaluationContext; -void BKE_mball_eval_geometry(struct EvaluationContext *eval_ctx, +void BKE_mball_eval_geometry(const struct EvaluationContext *eval_ctx, struct MetaBall *mball); +/* Draw Cache */ + +void BKE_mball_element_calc_display_m3x4(float r_scale_xform[3][4], + const float obmat[4][4], + const float local_pos[3]); + +enum { + BKE_MBALL_BATCH_DIRTY_ALL = 0, +}; +void BKE_mball_batch_cache_dirty(struct MetaBall *mb, int mode); +void BKE_mball_batch_cache_free(struct MetaBall *mb); #endif diff --git a/source/blender/blenkernel/BKE_mball_tessellate.h b/source/blender/blenkernel/BKE_mball_tessellate.h index 361f31b704c..40cdc80e280 100644 --- a/source/blender/blenkernel/BKE_mball_tessellate.h +++ b/source/blender/blenkernel/BKE_mball_tessellate.h @@ -28,7 +28,7 @@ struct Object; struct Scene; void BKE_mball_polygonize( - struct EvaluationContext *eval_ctx, struct Scene *scene, + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *dispbase); void BKE_mball_cubeTable_free(void); diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index f3b2b653e3d..5ee3b9be5f9 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -35,6 +35,7 @@ struct ID; struct BMeshCreateParams; struct BoundBox; struct EdgeHash; +struct EvaluationContext; struct ListBase; struct LinkNode; struct BLI_Stack; @@ -92,6 +93,9 @@ struct Mesh *BKE_mesh_copy(struct Main *bmain, const struct Mesh *me); void BKE_mesh_update_customdata_pointers(struct Mesh *me, const bool do_ensure_tess_cd); void BKE_mesh_ensure_skin_customdata(struct Mesh *me); +bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me); +bool BKE_mesh_clear_facemap_customdata(struct Mesh *me); + void BKE_mesh_make_local(struct Main *bmain, struct Mesh *me, const bool lib_local); void BKE_mesh_boundbox_calc(struct Mesh *me, float r_loc[3], float r_size[3]); void BKE_mesh_texspace_calc(struct Mesh *me); @@ -115,7 +119,7 @@ void BKE_mesh_from_nurbs_displist( struct Object *ob, struct ListBase *dispbase, const bool use_orco_uv, const char *obdata_name); void BKE_mesh_from_nurbs(struct Object *ob); void BKE_mesh_to_curve_nurblist(struct DerivedMesh *dm, struct ListBase *nurblist, const int edge_users_test); -void BKE_mesh_to_curve(struct Scene *scene, struct Object *ob); +void BKE_mesh_to_curve(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); void BKE_mesh_material_index_remove(struct Mesh *me, short index); void BKE_mesh_material_index_clear(struct Mesh *me); void BKE_mesh_material_remap(struct Mesh *me, const unsigned int *remap, unsigned int remap_len); @@ -125,6 +129,7 @@ const char *BKE_mesh_cmp(struct Mesh *me1, struct Mesh *me2, float thresh); struct BoundBox *BKE_mesh_boundbox_get(struct Object *ob); void BKE_mesh_texspace_get(struct Mesh *me, float r_loc[3], float r_rot[3], float r_size[3]); +void BKE_mesh_texspace_get_reference(struct Mesh *me, short **r_texflag, float **r_loc, float **r_rot, float **r_size); void BKE_mesh_texspace_copy_from_object(struct Mesh *me, struct Object *ob); bool BKE_mesh_uv_cdlayer_rename_index(struct Mesh *me, const int poly_index, const int loop_index, const int face_index, @@ -135,7 +140,7 @@ float (*BKE_mesh_vertexCos_get(const struct Mesh *me, int *r_numVerts))[3]; void BKE_mesh_split_faces(struct Mesh *mesh, bool free_loop_normals); -struct Mesh *BKE_mesh_new_from_object(struct Main *bmain, struct Scene *sce, struct Object *ob, +struct Mesh *BKE_mesh_new_from_object(const struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *sce, struct Object *ob, int apply_modifiers, int settings, int calc_tessface, int calc_undeformed); /* vertex level transformations & checks (no derived mesh) */ @@ -188,13 +193,6 @@ void BKE_mesh_calc_normals_looptri( const struct MLoop *mloop, const struct MLoopTri *looptri, int looptri_num, float (*r_tri_nors)[3]); -void BKE_mesh_loop_tangents_ex( - const struct MVert *mverts, const int numVerts, const struct MLoop *mloops, - float (*r_looptangent)[4], float (*loopnors)[3], const struct MLoopUV *loopuv, - const int numLoops, const struct MPoly *mpolys, const int numPolys, - struct ReportList *reports); -void BKE_mesh_loop_tangents( - struct Mesh *mesh, const char *uvmap, float (*r_looptangents)[4], struct ReportList *reports); /** * References a contiguous loop-fan with normal offset vars. @@ -297,7 +295,7 @@ void BKE_mesh_loops_to_mface_corners( const int numTex, const int numCol, const bool hasPCol, const bool hasOrigSpace, const bool hasLNor); void BKE_mesh_loops_to_tessdata( - struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata, struct MFace *mface, + struct CustomData *fdata, struct CustomData *ldata, struct MFace *mface, int *polyindices, unsigned int (*loopindices)[4], const int num_faces); void BKE_mesh_tangent_loops_to_tessdata( struct CustomData *fdata, struct CustomData *ldata, struct MFace *mface, @@ -375,7 +373,6 @@ void BKE_mesh_calc_relative_deform( /* *** mesh_validate.c *** */ int BKE_mesh_validate(struct Mesh *me, const int do_verbose, const int cddata_check_mask); -void BKE_mesh_cd_validate(struct Mesh *me); int BKE_mesh_validate_material_indices(struct Mesh *me); bool BKE_mesh_validate_arrays( @@ -405,11 +402,20 @@ void BKE_mesh_calc_edges(struct Mesh *mesh, bool update, const bool select); /* **** Depsgraph evaluation **** */ -struct EvaluationContext; - -void BKE_mesh_eval_geometry(struct EvaluationContext *eval_ctx, +void BKE_mesh_eval_geometry(const struct EvaluationContext *eval_ctx, struct Mesh *mesh); +/* Draw Cache */ +enum { + BKE_MESH_BATCH_DIRTY_ALL = 0, + BKE_MESH_BATCH_DIRTY_MAYBE_ALL, + BKE_MESH_BATCH_DIRTY_SELECT, + BKE_MESH_BATCH_DIRTY_SHADING, + BKE_MESH_BATCH_DIRTY_SCULPT_COORDS, +}; +void BKE_mesh_batch_cache_dirty(struct Mesh *me, int mode); +void BKE_mesh_batch_cache_free(struct Mesh *me); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_mesh_tangent.h b/source/blender/blenkernel/BKE_mesh_tangent.h new file mode 100644 index 00000000000..cb3100c1c2f --- /dev/null +++ b/source/blender/blenkernel/BKE_mesh_tangent.h @@ -0,0 +1,61 @@ +/* + * ***** 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_MESH_TANGENT_H__ +#define __BKE_MESH_TANGENT_H__ + +void BKE_mesh_calc_loop_tangent_single_ex( + const struct MVert *mverts, const int numVerts, const struct MLoop *mloops, + float (*r_looptangent)[4], float (*loopnors)[3], const struct MLoopUV *loopuv, + const int numLoops, const struct MPoly *mpolys, const int numPolys, + struct ReportList *reports); +void BKE_mesh_calc_loop_tangent_single( + struct Mesh *mesh, const char *uvmap, float (*r_looptangents)[4], struct ReportList *reports); + +void BKE_mesh_calc_loop_tangent_ex( + const struct MVert *mvert, + const struct MPoly *mpoly, const uint mpoly_len, + const struct MLoop *mloop, + const struct MLoopTri *looptri, const uint looptri_len, + + struct CustomData *loopdata, + bool calc_active_tangent, + const char (*tangent_names)[64], int tangent_names_len, + const float (*poly_normals)[3], + const float (*loop_normals)[3], + const float (*vert_orco)[3], + /* result */ + struct CustomData *loopdata_out, + const uint loopdata_out_len, + short *tangent_mask_curr_p); + +/* Helpers */ +void BKE_mesh_add_loop_tangent_named_layer_for_uv( + struct CustomData *uv_data, struct CustomData *tan_data, int numLoopData, + const char *layer_name); + +#define DM_TANGENT_MASK_ORCO (1 << 9) +void BKE_mesh_calc_loop_tangent_step_0( + const struct CustomData *loopData, bool calc_active_tangent, + const char (*tangent_names)[64], int tangent_names_count, + bool *rcalc_act, bool *rcalc_ren, int *ract_uv_n, int *rren_uv_n, + char *ract_uv_name, char *rren_uv_name, short *rtangent_mask); + +#endif /* __BKE_MESH_TANGENT_H__ */ + diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h index 30c47a4b192..8ee67850e5f 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -36,8 +36,10 @@ struct ID; struct DerivedMesh; struct DagForest; struct DagNode; +struct EvaluationContext; struct Object; struct Scene; +struct ViewLayer; struct ListBase; struct bArmature; struct Main; @@ -157,25 +159,27 @@ typedef struct ModifierTypeInfo { * the object it can obtain it from the derivedData argument if non-NULL, * and otherwise the ob argument. */ - void (*deformVerts)(struct ModifierData *md, struct Object *ob, - struct DerivedMesh *derivedData, + void (*deformVerts)(struct ModifierData *md, const struct EvaluationContext *eval_ctx, + struct Object *ob, struct DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts, ModifierApplyFlag flag); /* Like deformMatricesEM but called from object mode (for supporting modifiers in sculpt mode) */ - void (*deformMatrices)(struct ModifierData *md, struct Object *ob, - struct DerivedMesh *derivedData, + void (*deformMatrices)(struct ModifierData *md, const struct EvaluationContext *eval_ctx, + struct Object *ob, struct DerivedMesh *derivedData, float (*vertexCos)[3], float (*defMats)[3][3], int numVerts); /* Like deformVerts but called during editmode (for supporting modifiers) */ - void (*deformVertsEM)(struct ModifierData *md, struct Object *ob, - struct BMEditMesh *editData, struct DerivedMesh *derivedData, + void (*deformVertsEM)(struct ModifierData *md, const struct EvaluationContext *eval_ctx, + struct Object *ob, struct BMEditMesh *editData, + struct DerivedMesh *derivedData, float (*vertexCos)[3], int numVerts); /* Set deform matrix per vertex for crazyspace correction */ - void (*deformMatricesEM)(struct ModifierData *md, struct Object *ob, - struct BMEditMesh *editData, struct DerivedMesh *derivedData, + void (*deformMatricesEM)(struct ModifierData *md, const struct EvaluationContext *eval_ctx, + struct Object *ob, struct BMEditMesh *editData, + struct DerivedMesh *derivedData, float (*vertexCos)[3], float (*defMats)[3][3], int numVerts); /********************* Non-deform modifier functions *********************/ @@ -199,8 +203,8 @@ typedef struct ModifierTypeInfo { * The modifier may reuse the derivedData argument (i.e. return it in * modified form), but must not release it. */ - struct DerivedMesh *(*applyModifier)(struct ModifierData *md, struct Object *ob, - struct DerivedMesh *derivedData, + struct DerivedMesh *(*applyModifier)(struct ModifierData *md, const struct EvaluationContext *eval_ctx, + struct Object *ob, struct DerivedMesh *derivedData, ModifierApplyFlag flag); /* Like applyModifier but called during editmode (for supporting @@ -210,10 +214,9 @@ typedef struct ModifierTypeInfo { * are expected from editmode objects. The same qualifications regarding * derivedData apply as for applyModifier. */ - struct DerivedMesh *(*applyModifierEM)(struct ModifierData *md, struct Object *ob, - struct BMEditMesh *editData, - struct DerivedMesh *derivedData, - ModifierApplyFlag flag); + struct DerivedMesh *(*applyModifierEM)(struct ModifierData *md, const struct EvaluationContext *eval_ctx, + struct Object *ob, struct BMEditMesh *editData, + struct DerivedMesh *derivedData, ModifierApplyFlag flag); /********************* Optional functions *********************/ @@ -260,20 +263,10 @@ typedef struct ModifierTypeInfo { */ bool (*isDisabled)(struct ModifierData *md, int userRenderParams); - /* Add the appropriate relations to the DEP graph depending on the - * modifier data. - * - * This function is optional. - */ - void (*updateDepgraph)(struct ModifierData *md, struct DagForest *forest, - struct Main *bmain, struct Scene *scene, - struct Object *ob, struct DagNode *obNode); - /* Add the appropriate relations to the dependency graph. * * This function is optional. */ - /* TODO(sergey): Remove once we finally switched to the new depsgraph. */ void (*updateDepsgraph)(struct ModifierData *md, struct Main *bmain, struct Scene *scene, @@ -381,7 +374,8 @@ struct Object *modifiers_isDeformedByArmature(struct Object *ob); struct Object *modifiers_isDeformedByLattice(struct Object *ob); struct Object *modifiers_isDeformedByCurve(struct Object *ob); bool modifiers_usesArmature(struct Object *ob, struct bArmature *arm); -bool modifiers_isCorrectableDeformed(struct Scene *scene, struct Object *ob); +bool modifiers_isCorrectableDeformed( + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); void modifier_freeTemporaryData(struct ModifierData *md); bool modifiers_isPreview(struct Object *ob); @@ -427,24 +421,24 @@ const char *modifier_path_relbase(struct Object *ob); /* wrappers for modifier callbacks */ struct DerivedMesh *modwrap_applyModifier( - ModifierData *md, struct Object *ob, - struct DerivedMesh *dm, + ModifierData *md, const struct EvaluationContext *eval_ctx, + struct Object *ob, struct DerivedMesh *dm, ModifierApplyFlag flag); struct DerivedMesh *modwrap_applyModifierEM( - ModifierData *md, struct Object *ob, - struct BMEditMesh *em, + ModifierData *md, const struct EvaluationContext *eval_ctx, + struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm, ModifierApplyFlag flag); void modwrap_deformVerts( - ModifierData *md, struct Object *ob, - struct DerivedMesh *dm, + ModifierData *md, const struct EvaluationContext *eval_ctx, + struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3], int numVerts, ModifierApplyFlag flag); void modwrap_deformVertsEM( - ModifierData *md, struct Object *ob, + ModifierData *md, const struct EvaluationContext *eval_ctx, struct Object *ob, struct BMEditMesh *em, struct DerivedMesh *dm, float (*vertexCos)[3], int numVerts); diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index 178751d1640..22933a093ed 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -34,6 +34,7 @@ enum MultiresModifiedFlags; struct DerivedMesh; +struct EvaluationContext; struct MDisps; struct Mesh; struct ModifierData; @@ -47,20 +48,21 @@ struct MVert; struct MPoly; struct MLoopTri; +#include "DNA_object_enums.h" + /* Delete mesh mdisps and grid paint masks */ void multires_customdata_delete(struct Mesh *me); -void multires_set_tot_level(struct Object *ob, - struct MultiresModifierData *mmd, int lvl); +void multires_set_tot_level(struct MultiresModifierData *mmd, int lvl, eObjectMode object_mode); void multires_mark_as_modified(struct Object *ob, enum MultiresModifiedFlags flags); void multires_force_update(struct Object *ob); -void multires_force_render_update(struct Object *ob); +void multires_force_render_update(struct Object *ob, eObjectMode object_mode); void multires_force_external_reload(struct Object *ob); /* internal, only called in subsurf_ccg.c */ -void multires_modifier_update_mdisps(struct DerivedMesh *dm); +void multires_modifier_update_mdisps(struct DerivedMesh *dm, eObjectMode object_mode); void multires_modifier_update_hidden(struct DerivedMesh *dm); void multiresModifier_set_levels_from_disps(struct MultiresModifierData *mmd, struct Object *ob); @@ -72,26 +74,32 @@ typedef enum { MULTIRES_IGNORE_SIMPLIFY = 8 } MultiresFlags; -struct DerivedMesh *multires_make_derived_from_derived(struct DerivedMesh *dm, - struct MultiresModifierData *mmd, - struct Object *ob, - MultiresFlags flags); +struct DerivedMesh *multires_make_derived_from_derived( + struct DerivedMesh *dm, + struct MultiresModifierData *mmd, + struct Object *ob, + MultiresFlags flags, + eObjectMode object_mode); struct MultiresModifierData *find_multires_modifier_before(struct Scene *scene, struct ModifierData *lastmd); struct MultiresModifierData *get_multires_modifier(struct Scene *scene, struct Object *ob, bool use_first); -struct DerivedMesh *get_multires_dm(struct Scene *scene, struct MultiresModifierData *mmd, +struct DerivedMesh *get_multires_dm(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct MultiresModifierData *mmd, struct Object *ob); -void multiresModifier_del_levels(struct MultiresModifierData *, struct Object *, int direction); -void multiresModifier_base_apply(struct MultiresModifierData *mmd, struct Object *ob); -void multiresModifier_subdivide(struct MultiresModifierData *mmd, struct Object *ob, int updateblock, int simple); +void multiresModifier_del_levels( + struct MultiresModifierData *, struct Object *, int direction, eObjectMode object_mode); +void multiresModifier_base_apply( + struct MultiresModifierData *mmd, struct Object *ob, eObjectMode object_mode); +void multiresModifier_subdivide( + struct MultiresModifierData *mmd, struct Object *ob, int updateblock, int simple, eObjectMode object_mode); void multiresModifier_sync_levels_ex( - struct Object *ob_dst, struct MultiresModifierData *mmd_src, struct MultiresModifierData *mmd_dst); -int multiresModifier_reshape(struct Scene *scene, struct MultiresModifierData *mmd, + struct Object *ob_dst, struct MultiresModifierData *mmd_src, struct MultiresModifierData *mmd_dst, + eObjectMode object_mode); +int multiresModifier_reshape(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct MultiresModifierData *mmd, struct Object *dst, struct Object *src); -int multiresModifier_reshapeFromDM(struct Scene *scene, struct MultiresModifierData *mmd, +int multiresModifier_reshapeFromDM(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct MultiresModifierData *mmd, struct Object *ob, struct DerivedMesh *srcdm); -int multiresModifier_reshapeFromDeformMod(struct Scene *scene, struct MultiresModifierData *mmd, +int multiresModifier_reshapeFromDeformMod(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct MultiresModifierData *mmd, struct Object *ob, struct ModifierData *md); void multires_stitch_grids(struct Object *); @@ -102,15 +110,15 @@ enum { MULTIRES_SPACE_OBJECT, MULTIRES_SPACE_ABSOLUTE }; -void multires_set_space(struct DerivedMesh *dm, struct Object *ob, int from, int to); +void multires_set_space(struct DerivedMesh *dm, struct Object *ob, int from, int to, eObjectMode object_mode); /* Related to the old multires */ void multires_free(struct Multires *mr); void multires_load_old(struct Object *ob, struct Mesh *me); void multires_load_old_250(struct Mesh *); -void multiresModifier_scale_disp(struct Scene *scene, struct Object *ob); -void multiresModifier_prepare_join(struct Scene *scene, struct Object *ob, struct Object *to_ob); +void multiresModifier_scale_disp(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); +void multiresModifier_prepare_join(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct Object *to_ob); int multires_mdisp_corners(struct MDisps *s); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 8a736c9952d..770b2b4a185 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -74,6 +74,7 @@ struct PointerRNA; struct RenderData; struct Scene; struct Tex; +struct ViewRender; struct SpaceNode; struct ARegion; struct ColorManagedViewSettings; @@ -251,8 +252,9 @@ typedef struct bNodeType { #define NODE_CLASS_LAYOUT 100 /* nodetype->compatibility */ -#define NODE_OLD_SHADING 1 -#define NODE_NEW_SHADING 2 +#define NODE_OLD_SHADING (1 << 0) +#define NODE_NEW_SHADING (1 << 1) +#define NODE_NEWER_SHADING (1 << 2) /* node resize directions */ #define NODE_RESIZE_TOP 1 @@ -281,7 +283,7 @@ typedef struct bNodeTreeType { /* callbacks */ void (*free_cache)(struct bNodeTree *ntree); void (*free_node_cache)(struct bNodeTree *ntree, struct bNode *node); - void (*foreach_nodeclass)(struct Scene *scene, void *calldata, bNodeClassCallback func); /* iteration over all node classes */ + void (*foreach_nodeclass)(struct ViewRender *view_render, void *calldata, bNodeClassCallback func); /* iteration over all node classes */ /* Check visibility in the node editor */ int (*poll)(const struct bContext *C, struct bNodeTreeType *ntreetype); /* Select a node tree from the context */ @@ -690,6 +692,13 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter, } /** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Node Tree + */ + +void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, const int layer_index); + /* -------------------------------------------------------------------- */ /** \name Shader Nodes */ @@ -789,6 +798,7 @@ struct ShadeResult; #define SH_NODE_UVALONGSTROKE 191 #define SH_NODE_TEX_POINTDENSITY 192 #define SH_NODE_BSDF_PRINCIPLED 193 +#define SH_NODE_EEVEE_SPECULAR 195 #define SH_NODE_BEVEL 197 #define SH_NODE_DISPLACEMENT 198 #define SH_NODE_VECTOR_DISPLACEMENT 199 @@ -810,6 +820,7 @@ extern void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *); void set_node_shader_lamp_loop(void (*lamp_loop_func)(struct ShadeInput *, struct ShadeResult *)); void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat, short compatibility); +void ntreeGPUMaterialDomain(struct bNodeTree *ntree, bool *has_surface_output, bool *has_volume_output); /** \} */ @@ -980,7 +991,7 @@ void ntreeCompositTagRender(struct Scene *sce); int ntreeCompositTagAnimated(struct bNodeTree *ntree); void ntreeCompositTagGenerators(struct bNodeTree *ntree); void ntreeCompositUpdateRLayers(struct bNodeTree *ntree); -void ntreeCompositRegisterPass(struct bNodeTree *ntree, struct Scene *scene, struct SceneRenderLayer *srl, const char *name, int type); +void ntreeCompositRegisterPass(struct bNodeTree *ntree, struct Scene *scene, struct ViewLayer *view_layer, const char *name, int type); void ntreeCompositClearTags(struct bNodeTree *ntree); struct bNodeSocket *ntreeCompositOutputFileAddSocket(struct bNodeTree *ntree, struct bNode *node, @@ -1045,4 +1056,16 @@ int ntreeTexExecTree(struct bNodeTree *ntree, struct TexResult *target, void init_nodesystem(void); void free_nodesystem(void); +/* -------------------------------------------------------------------- */ +/* evaluation support, */ + +struct EvaluationContext; + +void BKE_nodetree_copy_default_values(struct bNodeTree *ntree_dst, + const struct bNodeTree *ntree_src); + +void BKE_nodetree_shading_params_eval(const struct EvaluationContext *eval_ctx, + struct bNodeTree *ntree_dst, + const struct bNodeTree *ntree_src); + #endif /* __BKE_NODE_H__ */ diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index 4d232e9ed6c..536b21e83ce 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -38,6 +38,7 @@ extern "C" { struct Base; struct EvaluationContext; struct Scene; +struct ViewLayer; struct Object; struct BoundBox; struct View3D; @@ -49,8 +50,10 @@ struct RigidBodyWorld; struct HookModifierData; struct ModifierData; +#include "DNA_object_enums.h" + void BKE_object_workob_clear(struct Object *workob); -void BKE_object_workob_calc_parent(struct Scene *scene, struct Object *ob, struct Object *workob); +void BKE_object_workob_calc_parent(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct Object *workob); void BKE_object_transform_copy(struct Object *ob_tar, const struct Object *ob_src); struct SoftBody *copy_softbody(const struct SoftBody *sb, const int flag); @@ -62,7 +65,6 @@ void BKE_object_free_particlesystems(struct Object *ob); void BKE_object_free_softbody(struct Object *ob); void BKE_object_free_bulletsoftbody(struct Object *ob); void BKE_object_free_curve_cache(struct Object *ob); -void BKE_object_update_base_layer(struct Scene *scene, struct Object *ob); void BKE_object_free(struct Object *ob); void BKE_object_free_derived_caches(struct Object *ob); @@ -72,16 +74,26 @@ void BKE_object_modifier_hook_reset(struct Object *ob, struct HookModifierData * bool BKE_object_support_modifier_type_check(struct Object *ob, int modifier_type); -void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_src); +void BKE_object_link_modifiers( + struct Object *ob_dst, const struct Object *ob_src, + eObjectMode object_mode); void BKE_object_free_modifiers(struct Object *ob); void BKE_object_make_proxy(struct Object *ob, struct Object *target, struct Object *gob); void BKE_object_copy_proxy_drivers(struct Object *ob, struct Object *target); bool BKE_object_exists_check(struct Object *obtest); -bool BKE_object_is_in_editmode(struct Object *ob); +bool BKE_object_is_in_editmode(const struct Object *ob); bool BKE_object_is_in_editmode_vgroup(struct Object *ob); -bool BKE_object_is_in_wpaint_select_vert(struct Object *ob); +bool BKE_object_is_in_wpaint_select_vert(const struct Object *ob, eObjectMode object_mode); + +typedef enum eObjectVisibilityCheck { + OB_VISIBILITY_CHECK_FOR_VIEWPORT, + OB_VISIBILITY_CHECK_FOR_RENDER, + OB_VISIBILITY_CHECK_UNKNOWN_RENDER_MODE, +} eObjectVisibilityCheck; + +bool BKE_object_is_visible(struct Object *ob, const eObjectVisibilityCheck mode); void BKE_object_init(struct Object *ob); struct Object *BKE_object_add_only_object( @@ -89,9 +101,13 @@ struct Object *BKE_object_add_only_object( int type, const char *name) ATTR_NONNULL(1) ATTR_RETURNS_NONNULL; struct Object *BKE_object_add( - struct Main *bmain, struct Scene *scene, + struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, int type, const char *name) - ATTR_NONNULL(1, 2) ATTR_RETURNS_NONNULL; + ATTR_NONNULL(1, 2, 3) ATTR_RETURNS_NONNULL; +struct Object *BKE_object_add_from( + struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer, + int type, const char *name, struct Object *ob_src) + ATTR_NONNULL(1, 2, 3, 6) ATTR_RETURNS_NONNULL; void *BKE_object_obdata_add_from_type( struct Main *bmain, int type, const char *name) @@ -101,9 +117,12 @@ void BKE_object_lod_add(struct Object *ob); void BKE_object_lod_sort(struct Object *ob); bool BKE_object_lod_remove(struct Object *ob, int level); void BKE_object_lod_update(struct Object *ob, const float camera_position[3]); -bool BKE_object_lod_is_usable(struct Object *ob, struct Scene *scene); -struct Object *BKE_object_lod_meshob_get(struct Object *ob, struct Scene *scene); -struct Object *BKE_object_lod_matob_get(struct Object *ob, struct Scene *scene); +bool BKE_object_lod_is_usable( + struct Object *ob, struct ViewLayer *view_layer, const eObjectMode object_mode); +struct Object *BKE_object_lod_meshob_get( + struct Object *ob, struct ViewLayer *view_layer, const eObjectMode object_mode); +struct Object *BKE_object_lod_matob_get( + struct Object *ob, struct ViewLayer *view_layer, const eObjectMode object_mode); void BKE_object_copy_data(struct Main *bmain, struct Object *ob_dst, const struct Object *ob_src, const int flag); struct Object *BKE_object_copy(struct Main *bmain, const struct Object *ob); @@ -122,14 +141,17 @@ void BKE_object_to_mat4(struct Object *ob, float mat[4][4]); void BKE_object_apply_mat4(struct Object *ob, float mat[4][4], const bool use_compat, const bool use_parent); void BKE_object_matrix_local_get(struct Object *ob, float mat[4][4]); +bool BKE_object_pose_context_check_ex(struct Object *ob, bool selected); bool BKE_object_pose_context_check(struct Object *ob); struct Object *BKE_object_pose_armature_get(struct Object *ob); - -void BKE_object_get_parent_matrix(struct Scene *scene, struct Object *ob, struct Object *par, float parentmat[4][4]); -void BKE_object_where_is_calc(struct Scene *scene, struct Object *ob); -void BKE_object_where_is_calc_ex(struct Scene *scene, struct RigidBodyWorld *rbw, struct Object *ob, float r_originmat[3][3]); -void BKE_object_where_is_calc_time(struct Scene *scene, struct Object *ob, float ctime); -void BKE_object_where_is_calc_time_ex(struct Scene *scene, struct Object *ob, float ctime, +struct Object *BKE_object_pose_armature_get_visible(struct Object *ob, struct ViewLayer *view_layer); + +void BKE_object_get_parent_matrix(struct Scene *scene, struct Object *ob, + struct Object *par, float parentmat[4][4]); +void BKE_object_where_is_calc(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); +void BKE_object_where_is_calc_ex(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct RigidBodyWorld *rbw, struct Object *ob, float r_originmat[3][3]); +void BKE_object_where_is_calc_time(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, float ctime); +void BKE_object_where_is_calc_time_ex(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, float ctime, struct RigidBodyWorld *rbw, float r_originmat[3][3]); void BKE_object_where_is_calc_mat4(struct Scene *scene, struct Object *ob, float obmat[4][4]); @@ -152,8 +174,7 @@ bool BKE_object_minmax_dupli(struct Scene *scene, struct Object *ob, float r_min void BKE_object_foreach_display_point(struct Object *ob, float obmat[4][4], void (*func_cb)(const float[3], void *), void *user_data); void BKE_scene_foreach_display_point(struct Scene *scene, - struct View3D *v3d, - const short flag, + struct ViewLayer *view_layer, void (*func_cb)(const float[3], void *), void *user_data); bool BKE_object_parent_loop_check(const struct Object *parent, const struct Object *ob); @@ -178,41 +199,54 @@ void BKE_object_tfm_protected_restore(struct Object *ob, const short protectflag); /* Dependency graph evaluation callbacks. */ -void BKE_object_eval_local_transform(struct EvaluationContext *eval_ctx, +void BKE_object_eval_local_transform(const struct EvaluationContext *eval_ctx, struct Object *ob); -void BKE_object_eval_parent(struct EvaluationContext *eval_ctx, +void BKE_object_eval_parent(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); -void BKE_object_eval_constraints(struct EvaluationContext *eval_ctx, +void BKE_object_eval_constraints(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); -void BKE_object_eval_done(struct EvaluationContext *eval_ctx, struct Object *ob); +void BKE_object_eval_done(const struct EvaluationContext *eval_ctx, struct Object *ob); -bool BKE_object_eval_proxy_copy(struct EvaluationContext *eval_ctx, +bool BKE_object_eval_proxy_copy(const struct EvaluationContext *eval_ct, struct Object *object); -void BKE_object_eval_uber_transform(struct EvaluationContext *eval_ctx, +void BKE_object_eval_uber_transform(const struct EvaluationContext *eval_ctx, struct Object *ob); -void BKE_object_eval_uber_data(struct EvaluationContext *eval_ctx, +void BKE_object_eval_uber_data(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); -void BKE_object_eval_cloth(struct EvaluationContext *eval_ctx, +void BKE_object_eval_cloth(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *object); - -void BKE_object_eval_transform_all(struct EvaluationContext *eval_ctx, +void BKE_object_eval_transform_all(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *object); -void BKE_object_handle_data_update(struct EvaluationContext *eval_ctx, - struct Scene *scene, - struct Object *ob); -void BKE_object_handle_update(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); -void BKE_object_handle_update_ex(struct EvaluationContext *eval_ctx, - struct Scene *scene, struct Object *ob, - struct RigidBodyWorld *rbw, - const bool do_proxy_update); +void BKE_object_eval_update_shading(const struct EvaluationContext *eval_ctx, + struct Object *object); +void BKE_object_data_select_update(const struct EvaluationContext *eval_ctx, + struct ID *object_data); + +void BKE_object_eval_flush_base_flags(const struct EvaluationContext *eval_ctx, + struct Object *object, struct Base *base, + const bool is_from_set); + +void BKE_object_handle_data_update( + const struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *ob); +void BKE_object_handle_update( + const struct EvaluationContext *eval_ctx, + struct Scene *scene, struct Object *ob); +void BKE_object_handle_update_ex( + const struct EvaluationContext *eval_ctx, + struct Scene *scene, struct Object *ob, + struct RigidBodyWorld *rbw, + const bool do_proxy_update); + void BKE_object_sculpt_modifiers_changed(struct Object *ob); int BKE_object_obdata_texspace_get(struct Object *ob, short **r_texflag, float **r_loc, float **r_size, float **r_rot); @@ -255,17 +289,16 @@ typedef enum eObjectSet { OB_SET_ALL /* All Objects */ } eObjectSet; -struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter); +struct LinkNode *BKE_object_relational_superset(struct ViewLayer *view_layer, eObjectSet objectSet, eObRelationTypes includeFilter); struct LinkNode *BKE_object_groups(struct Object *ob); -void BKE_object_groups_clear(struct Scene *scene, struct Base *base, struct Object *object); +void BKE_object_groups_clear(struct Object *object); struct KDTree *BKE_object_as_kdtree(struct Object *ob, int *r_tot); bool BKE_object_modifier_use_time(struct Object *ob, struct ModifierData *md); -bool BKE_object_modifier_update_subframe(struct Scene *scene, struct Object *ob, bool update_mesh, - int parent_recursion, float frame, - int type); +bool BKE_object_modifier_update_subframe(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, + bool update_mesh, int parent_recursion, float frame, int type); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_object_facemap.h b/source/blender/blenkernel/BKE_object_facemap.h new file mode 100644 index 00000000000..2607e5aa2dd --- /dev/null +++ b/source/blender/blenkernel/BKE_object_facemap.h @@ -0,0 +1,53 @@ +/* + * ***** 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. + * + * Contributor(s): Antony Riakiotakis + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef __BKE_OBJECT_FACEMAP_H__ +#define __BKE_OBJECT_FACEMAP_H__ + +/** \file BKE_object_facemap.h + * \ingroup bke + * \brief Functions for dealing with object face-maps. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +struct bFaceMap; +struct ListBase; +struct Object; + +struct bFaceMap *BKE_object_facemap_add(struct Object *ob); +struct bFaceMap *BKE_object_facemap_add_name(struct Object *ob, const char *name); +void BKE_object_facemap_remove(struct Object *ob, struct bFaceMap *fmap); +void BKE_object_facemap_clear(struct Object *ob); + +int BKE_object_facemap_name_index(struct Object *ob, const char *name); +void BKE_object_facemap_unique_name(struct Object *ob, struct bFaceMap *fmap); +struct bFaceMap *BKE_object_facemap_find_name(struct Object *ob, const char *name); +void BKE_object_facemap_copy_list(struct ListBase *outbase, const struct ListBase *inbase); + +#ifdef __cplusplus +} +#endif + +#endif /* __BKE_OBJECT_FACEMAP_H__ */ diff --git a/source/blender/blenkernel/BKE_outliner_treehash.h b/source/blender/blenkernel/BKE_outliner_treehash.h index 454edb40c4e..b82bc692402 100644 --- a/source/blender/blenkernel/BKE_outliner_treehash.h +++ b/source/blender/blenkernel/BKE_outliner_treehash.h @@ -36,8 +36,9 @@ void *BKE_outliner_treehash_create_from_treestore(struct BLI_mempool *treestore) /* full rebuild for already allocated hashtable */ void *BKE_outliner_treehash_rebuild_from_treestore(void *treehash, struct BLI_mempool *treestore); -/* full rebuild for already allocated hashtable */ +/* Add/remove hashtable elements */ void BKE_outliner_treehash_add_element(void *treehash, struct TreeStoreElem *elem); +void BKE_outliner_treehash_remove_element(void *treehash, struct TreeStoreElem *elem); /* find first unused element with specific type, nr and id */ struct TreeStoreElem *BKE_outliner_treehash_lookup_unused(void *treehash, short type, short nr, struct ID *id); diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h index c7a4f6b2fb6..2840971f157 100644 --- a/source/blender/blenkernel/BKE_paint.h +++ b/source/blender/blenkernel/BKE_paint.h @@ -52,11 +52,13 @@ struct PaletteColor; struct PBVH; struct ReportList; struct Scene; +struct ViewLayer; struct Sculpt; struct StrokeCache; struct Tex; struct ImagePool; struct UnifiedPaintSettings; +struct EvaluationContext; enum eOverlayFlags; @@ -91,8 +93,10 @@ typedef enum eOverlayControlFlags { PAINT_OVERLAY_OVERRIDE_PRIMARY | \ PAINT_OVERLAY_OVERRIDE_CURSOR) -void BKE_paint_invalidate_overlay_tex(struct Scene *scene, const struct Tex *tex); -void BKE_paint_invalidate_cursor_overlay(struct Scene *scene, struct CurveMapping *curve); +void BKE_paint_invalidate_overlay_tex( + struct Scene *scene, struct ViewLayer *view_layer, const struct Tex *tex, eObjectMode object_mode); +void BKE_paint_invalidate_cursor_overlay( + struct Scene *scene, struct ViewLayer *view_layer, struct CurveMapping *curve, eObjectMode object_mode); void BKE_paint_invalidate_overlay_all(void); eOverlayControlFlags BKE_paint_get_overlay_flags(void); void BKE_paint_reset_overlay_invalid(eOverlayControlFlags flag); @@ -126,7 +130,8 @@ void BKE_paint_cavity_curve_preset(struct Paint *p, int preset); eObjectMode BKE_paint_object_mode_from_paint_mode(ePaintMode mode); struct Paint *BKE_paint_get_active_from_paintmode(struct Scene *sce, ePaintMode mode); -struct Paint *BKE_paint_get_active(struct Scene *sce); +struct Paint *BKE_paint_get_active( + struct Scene *sce, struct ViewLayer *view_layer, const eObjectMode object_mode); struct Paint *BKE_paint_get_active_from_context(const struct bContext *C); ePaintMode BKE_paintmode_get_active_from_context(const struct bContext *C); struct Brush *BKE_paint_brush(struct Paint *paint); @@ -142,9 +147,9 @@ bool BKE_paint_proj_mesh_data_check(struct Scene *scene, struct Object *ob, bool /* testing face select mode * Texture paint could be removed since selected faces are not used * however hiding faces is useful */ -bool BKE_paint_select_face_test(struct Object *ob); -bool BKE_paint_select_vert_test(struct Object *ob); -bool BKE_paint_select_elem_test(struct Object *ob); +bool BKE_paint_select_face_test(struct Object *ob, eObjectMode object_mode); +bool BKE_paint_select_vert_test(struct Object *ob, eObjectMode object_mode); +bool BKE_paint_select_elem_test(struct Object *ob, eObjectMode object_mode); /* partial visibility */ bool paint_is_face_hidden(const struct MLoopTri *lt, const struct MVert *mvert, const struct MLoop *mloop); @@ -249,8 +254,9 @@ void BKE_sculptsession_free_deformMats(struct SculptSession *ss); void BKE_sculptsession_free_vwpaint_data(struct SculptSession *ss); void BKE_sculptsession_bm_to_me(struct Object *ob, bool reorder); void BKE_sculptsession_bm_to_me_for_render(struct Object *object); -void BKE_sculpt_update_mesh_elements(struct Scene *scene, struct Sculpt *sd, struct Object *ob, - bool need_pmap, bool need_mask); +void BKE_sculpt_update_mesh_elements( + const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Sculpt *sd, struct Object *ob, + bool need_pmap, bool need_mask); struct MultiresModifierData *BKE_sculpt_multires_active(struct Scene *scene, struct Object *ob); int BKE_sculpt_mask_layers_ensure(struct Object *ob, struct MultiresModifierData *mmd); diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 2c72373c2a9..9492f7e32fa 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -62,6 +62,8 @@ struct RNG; struct BVHTreeRay; struct BVHTreeRayHit; struct EdgeHash; +struct EvaluationContext; +struct ViewLayer; #define PARTICLE_COLLISION_MAX_COLLISIONS 10 @@ -77,6 +79,7 @@ struct EdgeHash; /* common stuff that many particle functions need */ typedef struct ParticleSimulationData { + const struct EvaluationContext *eval_ctx; struct Scene *scene; struct Object *ob; struct ParticleSystem *psys; @@ -295,7 +298,8 @@ void psys_set_current_num(Object *ob, int index); struct LatticeDeformData *psys_create_lattice_deform_data(struct ParticleSimulationData *sim); -bool psys_in_edit_mode(struct Scene *scene, struct ParticleSystem *psys); +bool psys_in_edit_mode( + const struct EvaluationContext *eval_ctx, struct ViewLayer *view_layer, struct ParticleSystem *psys); bool psys_check_enabled(struct Object *ob, struct ParticleSystem *psys, const bool use_render_params); bool psys_check_edited(struct ParticleSystem *psys); @@ -336,9 +340,9 @@ void psys_reset(struct ParticleSystem *psys, int mode); void psys_find_parents(struct ParticleSimulationData *sim, const bool use_render_params); void psys_cache_paths(struct ParticleSimulationData *sim, float cfra, const bool use_render_params); -void psys_cache_edit_paths(struct Scene *scene, struct Object *ob, struct PTCacheEdit *edit, float cfra, const bool use_render_params); +void psys_cache_edit_paths(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct PTCacheEdit *edit, float cfra, const bool use_render_params); void psys_cache_child_paths(struct ParticleSimulationData *sim, float cfra, const bool editupdate, const bool use_render_params); -int do_guides(struct ParticleSettings *part, struct ListBase *effectors, ParticleKey *state, int pa_num, float time); +int do_guides(const struct EvaluationContext *eval_ctx, struct ParticleSettings *part, struct ListBase *effectors, ParticleKey *state, int pa_num, float time); void precalc_guides(struct ParticleSimulationData *sim, struct ListBase *effectors); float psys_get_timestep(struct ParticleSimulationData *sim); float psys_get_child_time(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *birthtime, float *dietime); @@ -370,7 +374,7 @@ void psys_tasks_create(struct ParticleThreadContext *ctx, int startpart, int end void psys_tasks_free(struct ParticleTask *tasks, int numtasks); void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3]); -void psys_apply_hair_lattice(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys); +void psys_apply_hair_lattice(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ParticleSystem *psys); /* particle_system.c */ struct ParticleSystem *psys_get_target_system(struct Object *ob, struct ParticleTarget *pt); @@ -385,7 +389,7 @@ void psys_check_boid_data(struct ParticleSystem *psys); void psys_get_birth_coords(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleKey *state, float dtime, float cfra); -void particle_system_update(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, const bool use_render_params); +void particle_system_update(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, const bool use_render_params); /* Callback format for performing operations on ID-pointers for particle systems */ typedef void (*ParticleSystemIDFunc)(struct ParticleSystem *psys, struct ID **idpoin, void *userdata, int cb_flag); @@ -477,8 +481,20 @@ typedef struct ParticleRenderData { struct EvaluationContext; -void BKE_particle_system_eval_init(struct EvaluationContext *eval_ctx, +void BKE_particle_system_settings_eval(const struct EvaluationContext *eval_ctx, + struct ParticleSystem *psys); +void BKE_particle_system_settings_recalc_clear(struct EvaluationContext *UNUSED(eval_ctx), + struct ParticleSettings *particle_settings); + +void BKE_particle_system_eval_init(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); #endif + +/* Draw Cache */ +enum { + BKE_PARTICLE_BATCH_DIRTY_ALL = 0, +}; +void BKE_particle_batch_cache_dirty(struct ParticleSystem *psys, int mode); +void BKE_particle_batch_cache_free(struct ParticleSystem *psys); diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h index f619133ee4b..5f37aa25de7 100644 --- a/source/blender/blenkernel/BKE_pbvh.h +++ b/source/blender/blenkernel/BKE_pbvh.h @@ -30,6 +30,7 @@ #include "BLI_ghash.h" #include "BLI_utildefines.h" +struct Gwn_Batch; struct CCGElem; struct CCGKey; struct CCGDerivedMesh; @@ -132,6 +133,9 @@ void BKE_pbvh_node_draw(PBVHNode *node, void *data); void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3], int (*setMaterial)(int matnr, void *attribs), bool wireframe, bool fast); void BKE_pbvh_draw_BB(PBVH *bvh); +void BKE_pbvh_draw_cb( + PBVH *bvh, float (*planes)[4], float (*fnors)[3], bool fast, + void (*draw_fn)(void *user_data, struct Gwn_Batch *batch), void *user_data); /* PBVH Access */ typedef enum { @@ -369,6 +373,7 @@ bool BKE_pbvh_node_vert_update_check_any(PBVH *bvh, PBVHNode *node); //void BKE_pbvh_node_BB_reset(PBVHNode *node); //void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3]); +bool pbvh_has_mask(PBVH *bvh); void pbvh_show_diffuse_color_set(PBVH *bvh, bool show_diffuse_color); void pbvh_show_mask_set(PBVH *bvh, bool show_mask); diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h index f31ae715539..e9be6d9f7ca 100644 --- a/source/blender/blenkernel/BKE_pointcache.h +++ b/source/blender/blenkernel/BKE_pointcache.h @@ -90,6 +90,7 @@ struct ParticleKey; struct ParticleSystem; struct PointCache; struct Scene; +struct ViewLayer; struct SmokeModifierData; struct SoftBody; struct RigidBodyWorld; @@ -186,6 +187,8 @@ typedef struct PTCacheID { typedef struct PTCacheBaker { struct Main *main; struct Scene *scene; + struct ViewLayer *view_layer; + struct Depsgraph *depsgraph; int bake; int render; int anim_init; @@ -319,7 +322,7 @@ struct PointCache *BKE_ptcache_copy_list(struct ListBase *ptcaches_new, const st /********************** Baking *********************/ /* Bakes cache with cache_step sized jumps in time, not accurate but very fast. */ -void BKE_ptcache_quick_cache_all(struct Main *bmain, struct Scene *scene); +void BKE_ptcache_quick_cache_all(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer); /* Bake cache or simulate to current frame with settings defined in the baker. */ void BKE_ptcache_bake(struct PTCacheBaker *baker); diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h index 3c7274ca3c5..6aa43665427 100644 --- a/source/blender/blenkernel/BKE_rigidbody.h +++ b/source/blender/blenkernel/BKE_rigidbody.h @@ -37,6 +37,7 @@ struct RigidBodyWorld; struct RigidBodyOb; +struct EvaluationContext; struct Scene; struct Object; @@ -99,21 +100,19 @@ void BKE_rigidbody_aftertrans_update(struct Object *ob, float loc[3], float rot[ void BKE_rigidbody_sync_transforms(struct RigidBodyWorld *rbw, struct Object *ob, float ctime); bool BKE_rigidbody_check_sim_running(struct RigidBodyWorld *rbw, float ctime); void BKE_rigidbody_cache_reset(struct RigidBodyWorld *rbw); -void BKE_rigidbody_rebuild_world(struct Scene *scene, float ctime); -void BKE_rigidbody_do_simulation(struct Scene *scene, float ctime); +void BKE_rigidbody_rebuild_world(const struct EvaluationContext *eval_ctx, struct Scene *scene, float ctime); +void BKE_rigidbody_do_simulation(const struct EvaluationContext *eval_ctx, struct Scene *scene, float ctime); /* -------------------- */ /* Depsgraph evaluation */ -struct EvaluationContext; - -void BKE_rigidbody_rebuild_sim(struct EvaluationContext *eval_ctx, +void BKE_rigidbody_rebuild_sim(const struct EvaluationContext *eval_ctx, struct Scene *scene); -void BKE_rigidbody_eval_simulation(struct EvaluationContext *eval_ctx, +void BKE_rigidbody_eval_simulation(const struct EvaluationContext *eval_ctx, struct Scene *scene); -void BKE_rigidbody_object_sync_transforms(struct EvaluationContext *eval_ctx, +void BKE_rigidbody_object_sync_transforms(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob); diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 481aff3cfa6..bb435df136d 100644 --- a/source/blender/blenkernel/BKE_scene.h +++ b/source/blender/blenkernel/BKE_scene.h @@ -38,43 +38,55 @@ extern "C" { #endif struct AviCodecData; -struct Base; +struct Depsgraph; struct EvaluationContext; struct Main; struct Object; struct RenderData; -struct SceneRenderLayer; struct Scene; +struct SceneCollection; +struct ViewLayer; struct UnitSettings; -struct Main; +struct ViewRender; +struct WorkSpace; -#define SCE_COPY_NEW 0 -#define SCE_COPY_EMPTY 1 -#define SCE_COPY_LINK_OB 2 -#define SCE_COPY_LINK_DATA 3 -#define SCE_COPY_FULL 4 +typedef enum eSceneCopyMethod { + SCE_COPY_NEW = 0, + SCE_COPY_EMPTY = 1, + SCE_COPY_LINK_OB = 2, + SCE_COPY_LINK_DATA = 3, + SCE_COPY_FULL = 4, +} eSceneCopyMethod; /* Use as the contents of a 'for' loop: for (SETLOOPER(...)) { ... */ #define SETLOOPER(_sce_basis, _sce_iter, _base) \ - _sce_iter = _sce_basis, _base = _setlooper_base_step(&_sce_iter, NULL); \ + _sce_iter = _sce_basis, _base = _setlooper_base_step(&_sce_iter, BKE_view_layer_from_scene_get(_sce_basis), NULL); \ + _base; \ + _base = _setlooper_base_step(&_sce_iter, NULL, _base) + +#define SETLOOPER_VIEW_LAYER(_sce_basis, _view_layer, _sce_iter, _base) \ + _sce_iter = _sce_basis, _base = _setlooper_base_step(&_sce_iter, _view_layer, NULL); \ _base; \ - _base = _setlooper_base_step(&_sce_iter, _base) + _base = _setlooper_base_step(&_sce_iter, NULL, _base) -struct Base *_setlooper_base_step(struct Scene **sce_iter, struct Base *base); +#define SETLOOPER_SET_ONLY(_sce_basis, _sce_iter, _base) \ + _sce_iter = _sce_basis, _base = _setlooper_base_step(&_sce_iter, NULL, NULL); \ + _base; \ + _base = _setlooper_base_step(&_sce_iter, NULL, _base) + +struct Base *_setlooper_base_step(struct Scene **sce_iter, struct ViewLayer *view_layer, struct Base *base); void free_avicodecdata(struct AviCodecData *acd); +void BKE_scene_free_ex(struct Scene *sce, const bool do_id_user); void BKE_scene_free(struct Scene *sce); void BKE_scene_init(struct Scene *sce); struct Scene *BKE_scene_add(struct Main *bmain, const char *name); -/* base functions */ -struct Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name); -struct Base *BKE_scene_base_find(struct Scene *scene, struct Object *ob); -struct Base *BKE_scene_base_add(struct Scene *sce, struct Object *ob); -void BKE_scene_base_unlink(struct Scene *sce, struct Base *base); -void BKE_scene_base_deselect_all(struct Scene *sce); -void BKE_scene_base_select(struct Scene *sce, struct Base *selbase); +void BKE_scene_remove_rigidbody_object(struct Scene *scene, struct Object *ob); + +bool BKE_scene_object_find(struct Scene *scene, struct Object *ob); +struct Object *BKE_scene_object_find_by_name(struct Scene *scene, const char *name); /* Scene base iteration function. * Define struct here, so no need to bother with alloc/free it. @@ -87,11 +99,14 @@ typedef struct SceneBaseIter { int phase; } SceneBaseIter; -int BKE_scene_base_iter_next(struct EvaluationContext *eval_ctx, struct SceneBaseIter *iter, - struct Scene **scene, int val, struct Base **base, struct Object **ob); +int BKE_scene_base_iter_next( + const struct EvaluationContext *eval_ctx, struct SceneBaseIter *iter, + struct Scene **scene, int val, struct Base **base, struct Object **ob); -void BKE_scene_base_flag_to_objects(struct Scene *scene); +void BKE_scene_base_flag_to_objects(struct ViewLayer *view_layer); void BKE_scene_base_flag_from_objects(struct Scene *scene); +void BKE_scene_object_base_flag_sync_from_base(struct Base *base); +void BKE_scene_object_base_flag_sync_from_object(struct Base *base); void BKE_scene_set_background(struct Main *bmain, struct Scene *sce); struct Scene *BKE_scene_set_name(struct Main *bmain, const char *name); @@ -102,7 +117,8 @@ void BKE_scene_groups_relink(struct Scene *sce); void BKE_scene_make_local(struct Main *bmain, struct Scene *sce, const bool lib_local); -struct Object *BKE_scene_camera_find(struct Scene *sc); +struct Scene *BKE_scene_find_from_collection(const struct Main *bmain, const struct SceneCollection *scene_collection); + #ifdef DURIAN_CAMERA_SWITCH struct Object *BKE_scene_camera_switch_find(struct Scene *scene); // DURIAN_CAMERA_SWITCH #endif @@ -119,12 +135,18 @@ float BKE_scene_frame_get_from_ctime(const struct Scene *scene, const float fram void BKE_scene_frame_set(struct Scene *scene, double cfra); /* ** Scene evaluation ** */ -void BKE_scene_update_tagged(struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *sce); -void BKE_scene_update_for_newframe(struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *sce, unsigned int lay); -void BKE_scene_update_for_newframe_ex(struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *sce, unsigned int lay, bool do_invisible_flush); -struct SceneRenderLayer *BKE_scene_add_render_layer(struct Scene *sce, const char *name); -bool BKE_scene_remove_render_layer(struct Main *main, struct Scene *scene, struct SceneRenderLayer *srl); +void BKE_scene_graph_update_tagged(struct EvaluationContext *eval_ctx, + struct Depsgraph *depsgraph, + struct Main *bmain, + struct Scene *scene, + struct ViewLayer *view_layer); + +void BKE_scene_graph_update_for_newframe(struct EvaluationContext *eval_ctx, + struct Depsgraph *depsgraph, + struct Main *bmain, + struct Scene *scene, + struct ViewLayer *view_layer); struct SceneRenderView *BKE_scene_add_render_view(struct Scene *sce, const char *name); bool BKE_scene_remove_render_view(struct Scene *scene, struct SceneRenderView *srv); @@ -142,6 +164,7 @@ bool BKE_scene_use_spherical_stereo(struct Scene *scene); bool BKE_scene_uses_blender_internal(const struct Scene *scene); bool BKE_scene_uses_blender_game(const struct Scene *scene); +bool BKE_scene_uses_blender_eevee(const struct Scene *scene); void BKE_scene_disable_color_management(struct Scene *scene); bool BKE_scene_check_color_management_enabled(const struct Scene *scene); @@ -152,6 +175,22 @@ int BKE_render_num_threads(const struct RenderData *r); int BKE_render_preview_pixel_size(const struct RenderData *r); +/**********************************/ + +struct ViewRender *BKE_viewrender_get(struct Scene *scene, struct WorkSpace *workspace); +void BKE_viewrender_init(struct ViewRender *view_render); +void BKE_viewrender_free(struct ViewRender *view_render); +void BKE_viewrender_copy(struct ViewRender *view_render_dst, const struct ViewRender *view_render_src); +bool BKE_viewrender_use_new_shading_nodes(const struct ViewRender *view_render); +bool BKE_viewrender_use_shading_nodes_custom(const struct ViewRender *view_render); +bool BKE_viewrender_use_world_space_shading(const struct ViewRender *view_render); +bool BKE_viewrender_use_spherical_stereo(const struct ViewRender *view_render); +bool BKE_viewrender_uses_blender_internal(const struct ViewRender *view_render); +bool BKE_viewrender_uses_blender_game(const struct ViewRender *view_render); +bool BKE_viewrender_uses_blender_eevee(const struct ViewRender *view_render); + +/**********************************/ + double BKE_scene_unit_scale(const struct UnitSettings *unit, const int unit_type, double value); /* multiview */ @@ -171,6 +210,13 @@ void BKE_scene_multiview_view_prefix_get(struct Scene *scene, const char void BKE_scene_multiview_videos_dimensions_get(const struct RenderData *rd, const size_t width, const size_t height, size_t *r_width, size_t *r_height); int BKE_scene_multiview_num_videos_get(const struct RenderData *rd); +/* depsgraph */ +void BKE_scene_allocate_depsgraph_hash(struct Scene *scene); +void BKE_scene_ensure_depsgraph_hash(struct Scene *scene); +void BKE_scene_free_depsgraph_hash(struct Scene *scene); + +struct Depsgraph *BKE_scene_get_depsgraph(struct Scene *scene, struct ViewLayer *view_layer, bool allocate); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 14e978b23f2..6669f3103da 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -42,6 +42,7 @@ struct Panel; struct Scene; struct ScrArea; struct SpaceType; +struct TransformOrientation; struct View3D; struct bContext; struct bContextDataResult; @@ -49,10 +50,13 @@ struct bScreen; struct uiLayout; struct uiList; struct wmKeyConfig; +struct wmManipulatorMap; struct wmNotifier; struct wmWindow; struct wmWindowManager; +struct WorkSpace; struct GPUFXSettings; +struct wmMsgBus; #include "BLI_compiler_attrs.h" @@ -81,7 +85,9 @@ typedef struct SpaceType { /* exit is called when the area is hidden or removed */ void (*exit)(struct wmWindowManager *, struct ScrArea *); /* Listeners can react to bContext changes */ - void (*listener)(struct bScreen *sc, struct ScrArea *, struct wmNotifier *); + void (*listener)(struct bScreen *sc, struct ScrArea *, + struct wmNotifier *, struct Scene *scene, + struct WorkSpace *workspace); /* refresh context, called after filereads, ED_area_tag_refresh() */ void (*refresh)(const struct bContext *, struct ScrArea *); @@ -96,6 +102,9 @@ typedef struct SpaceType { /* on startup, define dropboxes for spacetype+regions */ void (*dropboxes)(void); + /* initialize manipulator-map-types and manipulator-group-types with the region */ + void (*manipulators)(void); + /* return context data */ int (*context)(const struct bContext *, const char *, struct bContextDataResult *); @@ -129,8 +138,15 @@ typedef struct ARegionType { /* draw entirely, view changes should be handled here */ void (*draw)(const struct bContext *, struct ARegion *); /* contextual changes should be handled here */ - void (*listener)(struct bScreen *sc, struct ScrArea *, struct ARegion *, struct wmNotifier *); - + void (*listener)(struct bScreen *, struct ScrArea *, struct ARegion *, + struct wmNotifier *, const struct Scene *scene); + /* Optional callback to generate subscriptions. */ + void (*message_subscribe)( + const struct bContext *C, + struct WorkSpace *workspace, struct Scene *scene, + struct bScreen *sc, struct ScrArea *sa, struct ARegion *ar, + struct wmMsgBus *mbus); + void (*free)(struct ARegion *); /* split region, copy data optionally */ @@ -284,6 +300,9 @@ void BKE_spacedata_id_unref(struct ScrArea *sa, struct SpaceLink *sl, struct ID struct ARegion *BKE_area_region_copy(struct SpaceType *st, struct ARegion *ar); void BKE_area_region_free(struct SpaceType *st, struct ARegion *ar); void BKE_screen_area_free(struct ScrArea *sa); +/* Manipulator-maps of a region need to be freed with the region. Uses callback to avoid low-level call. */ +void BKE_region_callback_free_manipulatormap_set(void (*callback)(struct wmManipulatorMap *)); +void BKE_region_callback_refresh_tag_manipulatormap_set(void (*callback)(struct wmManipulatorMap *)); struct ARegion *BKE_area_find_region_type(struct ScrArea *sa, int type); struct ARegion *BKE_area_find_region_active_win(struct ScrArea *sa); @@ -299,12 +318,16 @@ unsigned int BKE_screen_view3d_layer_active( unsigned int BKE_screen_view3d_layer_all(const struct bScreen *sc) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1); +void BKE_screen_manipulator_tag_refresh(struct bScreen *sc); + void BKE_screen_view3d_sync(struct View3D *v3d, struct Scene *scene); -void BKE_screen_view3d_scene_sync(struct bScreen *sc); -void BKE_screen_view3d_main_sync(ListBase *screen_lb, struct Scene *scene); -void BKE_screen_view3d_twmode_remove(struct View3D *v3d, const int i); -void BKE_screen_view3d_main_twmode_remove(ListBase *screen_lb, struct Scene *scene, const int i); +void BKE_screen_view3d_scene_sync(struct bScreen *sc, struct Scene *scene); +void BKE_screen_transform_orientation_remove( + const struct bScreen *screen, const struct WorkSpace *workspace, + const struct TransformOrientation *orientation) ATTR_NONNULL(); void BKE_screen_gpu_fx_validate(struct GPUFXSettings *fx_settings); +bool BKE_screen_is_fullscreen_area(const struct bScreen *screen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); +bool BKE_screen_is_used(const struct bScreen *screen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(); /* zoom factor conversion */ float BKE_screen_view3d_zoom_to_fac(float camzoom); diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 6c9dc12b44f..2264167eca1 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -432,7 +432,8 @@ enum { }; typedef struct ImBuf *(*SequencerDrawView)( - struct Scene *scene, struct Object *camera, int width, int height, + const struct EvaluationContext *eval_ctx, struct Scene *scene, + struct ViewLayer *view_layer, struct Object *camera, int width, int height, unsigned int flag, unsigned int draw_flags, int drawtype, int alpha_mode, int samples, const char *viewname, struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]); diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h index d2ab4f3164c..0c4f2bc9c05 100644 --- a/source/blender/blenkernel/BKE_shrinkwrap.h +++ b/source/blender/blenkernel/BKE_shrinkwrap.h @@ -54,6 +54,7 @@ struct ShrinkwrapModifierData; struct MDeformVert; struct BVHTree; struct SpaceTransform; +struct EvaluationContext; typedef struct ShrinkwrapCalcData { @@ -76,8 +77,10 @@ typedef struct ShrinkwrapCalcData { } ShrinkwrapCalcData; -void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, struct Object *ob, struct DerivedMesh *dm, - float (*vertexCos)[3], int numVerts, bool for_render); +void shrinkwrapModifier_deform( + const struct EvaluationContext *eval_ctx, + struct ShrinkwrapModifierData *smd, struct Object *ob, struct DerivedMesh *dm, + float (*vertexCos)[3], int numVerts, bool for_render); /* * This function casts a ray in the given BVHTree.. but it takes into consideration the space_transform, that is: diff --git a/source/blender/blenkernel/BKE_smoke.h b/source/blender/blenkernel/BKE_smoke.h index 20366f00df6..64d70e8e209 100644 --- a/source/blender/blenkernel/BKE_smoke.h +++ b/source/blender/blenkernel/BKE_smoke.h @@ -35,7 +35,9 @@ typedef float (*bresenham_callback)(float *result, float *input, int res[3], int *pixel, float *tRay, float correct); -struct DerivedMesh *smokeModifier_do(struct SmokeModifierData *smd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm); +struct DerivedMesh *smokeModifier_do(struct SmokeModifierData *smd, const struct EvaluationContext *eval_ctx, + struct Scene *scene, + struct Object *ob, struct DerivedMesh *dm); void smoke_reallocate_fluid(struct SmokeDomainSettings *sds, float dx, int res[3], int free_old); void smoke_reallocate_highres_fluid(struct SmokeDomainSettings *sds, float dx, int res[3], int free_old); diff --git a/source/blender/blenkernel/BKE_softbody.h b/source/blender/blenkernel/BKE_softbody.h index 486fe8ed5a8..e2255bdb779 100644 --- a/source/blender/blenkernel/BKE_softbody.h +++ b/source/blender/blenkernel/BKE_softbody.h @@ -34,6 +34,7 @@ struct Object; struct Scene; struct SoftBody; +struct EvaluationContext; typedef struct BodyPoint { float origS[3], origE[3], origT[3], pos[3], vec[3], force[3]; @@ -59,7 +60,8 @@ extern void sbFree(struct SoftBody *sb); extern void sbFreeSimulation(struct SoftBody *sb); /* do one simul step, reading and writing vertex locs from given array */ -extern void sbObjectStep(struct Scene *scene, struct Object *ob, float framnr, float (*vertexCos)[3], int numVerts); +extern void sbObjectStep(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, + float framnr, float (*vertexCos)[3], int numVerts); /* makes totally fresh start situation, resets time */ extern void sbObjectToSoftbody(struct Object *ob); diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h index 6f8274fabc8..98fb4f47339 100644 --- a/source/blender/blenkernel/BKE_sound.h +++ b/source/blender/blenkernel/BKE_sound.h @@ -35,8 +35,8 @@ #define SOUND_WAVE_SAMPLES_PER_SECOND 250 -#ifdef WITH_SYSTEM_AUDASPACE -# include AUD_DEVICE_H +#if defined(WITH_AUDASPACE) +# include <AUD_Device.h> #endif struct bSound; @@ -84,7 +84,7 @@ void BKE_sound_copy_data(struct Main *bmain, struct bSound *sound_dst, const str void BKE_sound_make_local(struct Main *bmain, struct bSound *sound, const bool lib_local); -#if defined(__AUD_C_API_H__) || defined(WITH_SYSTEM_AUDASPACE) +#if defined(WITH_AUDASPACE) AUD_Device *BKE_sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume); #endif @@ -149,6 +149,4 @@ float BKE_sound_get_length(struct bSound *sound); char **BKE_sound_get_device_names(void); -bool BKE_sound_is_jack_supported(void); - #endif /* __BKE_SOUND_H__ */ diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h index 13302caa09d..5da87de1cc9 100644 --- a/source/blender/blenkernel/BKE_tracking.h +++ b/source/blender/blenkernel/BKE_tracking.h @@ -47,6 +47,7 @@ struct MovieDistortion; struct Camera; struct Object; struct Scene; +struct EvaluationContext; struct rcti; /* **** Common functions **** */ diff --git a/source/blender/blenkernel/BKE_workspace.h b/source/blender/blenkernel/BKE_workspace.h new file mode 100644 index 00000000000..f839d4cdf76 --- /dev/null +++ b/source/blender/blenkernel/BKE_workspace.h @@ -0,0 +1,139 @@ +/* + * ***** 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 ***** + */ + +/** \file BKE_workspace.h + * \ingroup bke + */ + +#ifndef __BKE_WORKSPACE_H__ +#define __BKE_WORKSPACE_H__ + +#include "BLI_compiler_attrs.h" + +struct bScreen; +struct EvaluationContext; +struct Main; +struct Scene; +struct TransformOrientation; +struct ViewLayer; + +/* -------------------------------------------------------------------- */ +/* Create, delete, init */ + +struct WorkSpace *BKE_workspace_add(struct Main *bmain, const char *name); +void BKE_workspace_free(struct WorkSpace *workspace); +void BKE_workspace_remove(struct Main *bmain, struct WorkSpace *workspace); + +struct WorkSpaceInstanceHook *BKE_workspace_instance_hook_create(const struct Main *bmain); +void BKE_workspace_instance_hook_free(const struct Main *bmain, struct WorkSpaceInstanceHook *hook); + +struct WorkSpaceLayout *BKE_workspace_layout_add( + struct WorkSpace *workspace, + struct bScreen *screen, + const char *name) ATTR_NONNULL(); +void BKE_workspace_layout_remove( + struct Main *bmain, + struct WorkSpace *workspace, struct WorkSpaceLayout *layout) ATTR_NONNULL(); + +void BKE_workspace_relations_free( + ListBase *relation_list); + + +/* -------------------------------------------------------------------- */ +/* General Utils */ + +void BKE_workspace_view_layer_remove_references( + const struct Main *bmain, + const struct ViewLayer *view_layer) ATTR_NONNULL(); + +void BKE_workspace_transform_orientation_remove( + struct WorkSpace *workspace, struct TransformOrientation *orientation) ATTR_NONNULL(); +struct TransformOrientation *BKE_workspace_transform_orientation_find( + const struct WorkSpace *workspace, const int index) ATTR_NONNULL(); +int BKE_workspace_transform_orientation_get_index( + const struct WorkSpace *workspace, const struct TransformOrientation *orientation) ATTR_NONNULL(); + +struct WorkSpaceLayout *BKE_workspace_layout_find( + const struct WorkSpace *workspace, const struct bScreen *screen) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT; +struct WorkSpaceLayout *BKE_workspace_layout_find_global( + const struct Main *bmain, const struct bScreen *screen, + struct WorkSpace **r_workspace) ATTR_NONNULL(1, 2); + +struct WorkSpaceLayout *BKE_workspace_layout_iter_circular( + const struct WorkSpace *workspace, struct WorkSpaceLayout *start, + bool (*callback)(const struct WorkSpaceLayout *layout, void *arg), + void *arg, const bool iter_backward); + + +/* -------------------------------------------------------------------- */ +/* Getters/Setters */ + +#define GETTER_ATTRS ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT +#define SETTER_ATTRS ATTR_NONNULL(1) + +struct WorkSpace *BKE_workspace_active_get(struct WorkSpaceInstanceHook *hook) GETTER_ATTRS; +void BKE_workspace_active_set(struct WorkSpaceInstanceHook *hook, struct WorkSpace *workspace) SETTER_ATTRS; +struct WorkSpaceLayout *BKE_workspace_active_layout_get(const struct WorkSpaceInstanceHook *hook) GETTER_ATTRS; +void BKE_workspace_active_layout_set(struct WorkSpaceInstanceHook *hook, struct WorkSpaceLayout *layout) SETTER_ATTRS; +struct bScreen *BKE_workspace_active_screen_get(const struct WorkSpaceInstanceHook *hook) GETTER_ATTRS; +void BKE_workspace_active_screen_set( + struct WorkSpaceInstanceHook *hook, struct WorkSpace *workspace, struct bScreen *screen) SETTER_ATTRS; +struct Base *BKE_workspace_active_base_get(const struct WorkSpace *workspace, const struct Scene *scene); +struct ListBase *BKE_workspace_transform_orientations_get(struct WorkSpace *workspace) GETTER_ATTRS; +struct ViewLayer *BKE_workspace_view_layer_get( + const struct WorkSpace *workspace, + const struct Scene *scene) GETTER_ATTRS; +void BKE_workspace_view_layer_set( + struct WorkSpace *workspace, + struct ViewLayer *layer, + struct Scene *scene) SETTER_ATTRS; +struct ListBase *BKE_workspace_layouts_get(struct WorkSpace *workspace) GETTER_ATTRS; + +const char *BKE_workspace_layout_name_get(const struct WorkSpaceLayout *layout) GETTER_ATTRS; +void BKE_workspace_layout_name_set( + struct WorkSpace *workspace, struct WorkSpaceLayout *layout, const char *new_name) ATTR_NONNULL(); +struct bScreen *BKE_workspace_layout_screen_get(const struct WorkSpaceLayout *layout) GETTER_ATTRS; +void BKE_workspace_layout_screen_set(struct WorkSpaceLayout *layout, struct bScreen *screen) SETTER_ATTRS; + +struct WorkSpaceLayout *BKE_workspace_hook_layout_for_workspace_get( + const struct WorkSpaceInstanceHook *hook, const struct WorkSpace *workspace) GETTER_ATTRS; +void BKE_workspace_hook_layout_for_workspace_set( + struct WorkSpaceInstanceHook *hook, struct WorkSpace *workspace, struct WorkSpaceLayout *layout) ATTR_NONNULL(); + +struct ViewRender *BKE_workspace_view_render_get(struct WorkSpace *workspace) GETTER_ATTRS; + +/* flags */ +bool BKE_workspace_use_scene_settings_get(const struct WorkSpace *workspace) GETTER_ATTRS; +void BKE_workspace_use_scene_settings_set(struct WorkSpace *workspace, bool value) SETTER_ATTRS; + +/* Update / evaluate */ +void BKE_workspace_update_tagged(struct EvaluationContext *eval_ctx, + struct Main *bmain, + struct WorkSpace *workspace, + struct Scene *scene); + +void BKE_workspace_update_object_mode( + struct EvaluationContext *eval_ctx, + struct WorkSpace *workspace); + +#undef GETTER_ATTRS +#undef SETTER_ATTRS + +#endif /* __BKE_WORKSPACE_H__ */ diff --git a/source/blender/blenkernel/BKE_world.h b/source/blender/blenkernel/BKE_world.h index b28bac08727..b45d7a7e6ec 100644 --- a/source/blender/blenkernel/BKE_world.h +++ b/source/blender/blenkernel/BKE_world.h @@ -44,4 +44,11 @@ struct World *BKE_world_copy(struct Main *bmain, const struct World *wrld); struct World *BKE_world_localize(struct World *wrld); void BKE_world_make_local(struct Main *bmain, struct World *wrld, const bool lib_local); -#endif /* __BKE_WORLD_H__ */ +/* Evaluation. */ + +struct EvaluationContext; + +void BKE_world_eval(const struct EvaluationContext *eval_ctx, struct World *world); + +#endif + diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 3fc2c3f8eb0..279068c440e 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -30,6 +30,7 @@ set(INC ../blenloader ../blentranslation ../depsgraph + ../draw ../gpu ../ikplugin ../imbuf @@ -86,6 +87,7 @@ set(SRC intern/camera.c intern/cdderivedmesh.c intern/cloth.c + intern/collection.c intern/collision.c intern/colorband.c intern/colortools.c @@ -98,12 +100,12 @@ set(SRC intern/customdata_file.c intern/data_transfer.c intern/deform.c - intern/depsgraph.c intern/displist.c intern/dynamicpaint.c intern/editderivedmesh.c intern/editmesh.c intern/editmesh_bvh.c + intern/editmesh_tangent.c intern/effect.c intern/fcurve.c intern/fluidsim.c @@ -123,6 +125,7 @@ set(SRC intern/lattice.c intern/library.c intern/library_idmap.c + intern/library_override.c intern/library_query.c intern/library_remap.c intern/linestyle.c @@ -136,6 +139,7 @@ set(SRC intern/mesh_evaluate.c intern/mesh_mapping.c intern/mesh_remap.c + intern/mesh_tangent.c intern/mesh_validate.c intern/modifier.c intern/modifiers_bmesh.c @@ -144,6 +148,7 @@ set(SRC intern/nla.c intern/node.c intern/object.c + intern/object_facemap.c intern/object_deform.c intern/object_dupli.c intern/object_update.c @@ -159,6 +164,8 @@ set(SRC intern/pbvh_bmesh.c intern/pointcache.c intern/property.c + intern/layer.c + intern/lightprobe.c intern/report.c intern/rigidbody.c intern/sca.c @@ -187,6 +194,7 @@ set(SRC intern/tracking_stabilize.c intern/tracking_util.c intern/unit.c + intern/workspace.c intern/world.c intern/writeavi.c intern/writeframeserver.c @@ -216,6 +224,7 @@ set(SRC BKE_ccg.h BKE_cdderivedmesh.h BKE_cloth.h + BKE_collection.h BKE_collision.h BKE_colorband.h BKE_colortools.h @@ -227,11 +236,11 @@ set(SRC BKE_customdata_file.h BKE_data_transfer.h BKE_deform.h - BKE_depsgraph.h BKE_displist.h BKE_dynamicpaint.h BKE_editmesh.h BKE_editmesh_bvh.h + BKE_editmesh_tangent.h BKE_effect.h BKE_fcurve.h BKE_fluidsim.h @@ -250,6 +259,7 @@ set(SRC BKE_lattice.h BKE_library.h BKE_library_idmap.h + BKE_library_override.h BKE_library_query.h BKE_library_remap.h BKE_linestyle.h @@ -261,12 +271,14 @@ set(SRC BKE_mesh.h BKE_mesh_mapping.h BKE_mesh_remap.h + BKE_mesh_tangent.h BKE_modifier.h BKE_movieclip.h BKE_multires.h BKE_nla.h BKE_node.h BKE_object.h + BKE_object_facemap.h BKE_object_deform.h BKE_ocean.h BKE_outliner_treehash.h @@ -276,6 +288,8 @@ set(SRC BKE_pbvh.h BKE_pointcache.h BKE_property.h + BKE_layer.h + BKE_lightprobe.h BKE_report.h BKE_rigidbody.h BKE_sca.h @@ -294,11 +308,11 @@ set(SRC BKE_texture.h BKE_tracking.h BKE_unit.h + BKE_workspace.h BKE_world.h BKE_writeavi.h BKE_writeframeserver.h - depsgraph_private.h nla_private.h tracking_private.h intern/CCGSubSurf.h @@ -324,7 +338,7 @@ if(WIN32) endif() if(WITH_AUDASPACE) - add_definitions(${AUDASPACE_DEFINITIONS}) + add_definitions(-DWITH_AUDASPACE) list(APPEND INC_SYS ${AUDASPACE_C_INCLUDE_DIRS} @@ -412,6 +426,10 @@ if(WITH_PYTHON) ) add_definitions(-DWITH_PYTHON) + if(WITH_PYTHON_SAFETY) + add_definitions(-DWITH_PYTHON_SAFETY) + endif() + if(WITH_PYTHON_SECURITY) add_definitions(-DWITH_PYTHON_SECURITY) endif() @@ -528,8 +546,4 @@ endif() # set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX") #endif() -if(WITH_LEGACY_DEPSGRAPH) - add_definitions(-DWITH_LEGACY_DEPSGRAPH) -endif() - blender_add_lib(bf_blenkernel "${SRC}" "${INC}" "${INC_SYS}") diff --git a/source/blender/blenkernel/depsgraph_private.h b/source/blender/blenkernel/depsgraph_private.h deleted file mode 100644 index 69ca75836d9..00000000000 --- a/source/blender/blenkernel/depsgraph_private.h +++ /dev/null @@ -1,169 +0,0 @@ -/* - * ***** 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) 2004 Blender Foundation. - * All rights reserved. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/blenkernel/depsgraph_private.h - * \ingroup bke - */ - -#ifndef __DEPSGRAPH_PRIVATE_H__ -#define __DEPSGRAPH_PRIVATE_H__ - -#include "BKE_depsgraph.h" -#include "DNA_constraint_types.h" -#include "BKE_constraint.h" - -struct Scene; -struct Group; -struct EffectorWeights; -struct ModifierData; - -/* **** DAG relation types *** */ - -/* scene link to object */ -#define DAG_RL_SCENE (1 << 0) -/* object link to data */ -#define DAG_RL_DATA (1 << 1) - -/* object changes object (parent, track, constraints) */ -#define DAG_RL_OB_OB (1 << 2) -/* object changes obdata (hooks, constraints) */ -#define DAG_RL_OB_DATA (1 << 3) -/* data changes object (vertex parent) */ -#define DAG_RL_DATA_OB (1 << 4) -/* data changes data (deformers) */ -#define DAG_RL_DATA_DATA (1 << 5) - -#define DAG_NO_RELATION (1 << 6) - -#define DAG_RL_ALL_BUT_DATA (DAG_RL_SCENE | DAG_RL_OB_OB | DAG_RL_OB_DATA | DAG_RL_DATA_OB | DAG_RL_DATA_DATA) -#define DAG_RL_ALL (DAG_RL_ALL_BUT_DATA | DAG_RL_DATA) - - -#define DAGQUEUEALLOC 50 - -enum { - DAG_WHITE = 0, - DAG_GRAY = 1, - DAG_BLACK = 2 -}; - -typedef struct DagAdjList { - struct DagNode *node; - short type; - int count; /* number of identical arcs */ - unsigned int lay; // for flushing redraw/rebuild events - const char *name; - struct DagAdjList *next; -} DagAdjList; - - -typedef struct DagNode { - int color; - short type; - float x, y, k; - void *ob; - void *first_ancestor; - int ancestor_count; - unsigned int lay; /* accumulated layers of its relations + itself */ - unsigned int scelay; /* layers due to being in scene */ - uint64_t customdata_mask; /* customdata mask */ - int lasttime; /* if lasttime != DagForest->time, this node was not evaluated yet for flushing */ - int BFS_dist; /* BFS distance */ - int DFS_dist; /* DFS distance */ - int DFS_dvtm; /* DFS discovery time */ - int DFS_fntm; /* DFS Finishing time */ - struct DagAdjList *child; - struct DagAdjList *parent; - struct DagNode *next; - - /* Threaded evaluation routines */ - uint32_t num_pending_parents; /* number of parents which are not updated yet - * this node has got. - * Used by threaded update for faster detect whether node could be - * updated aready. - */ - bool scheduled; - - /* Runtime flags mainly used to determine which extra data is to be evaluated - * during object_handle_update(). Such an extra data is what depends on the - * DAG topology, meaning this flags indicates the data evaluation of which - * depends on the node dependencies. - */ - short eval_flags; -} DagNode; - -typedef struct DagNodeQueueElem { - struct DagNode *node; - struct DagNodeQueueElem *next; -} DagNodeQueueElem; - -typedef struct DagNodeQueue { - DagNodeQueueElem *first; - DagNodeQueueElem *last; - int count; - int maxlevel; - struct DagNodeQueue *freenodes; -} DagNodeQueue; - -/* forest as we may have more than one DAG unconnected */ -typedef struct DagForest { - ListBase DagNode; - struct GHash *nodeHash; - int numNodes; - bool is_acyclic; - int time; /* for flushing/tagging, compare with node->lasttime */ - bool ugly_hack_sorry; /* prevent type check */ - bool need_update; -} DagForest; - -// queue operations -DagNodeQueue *queue_create(int slots); -void queue_raz(DagNodeQueue *queue); -void push_queue(DagNodeQueue *queue, DagNode *node); -void push_stack(DagNodeQueue *queue, DagNode *node); -DagNode *pop_queue(DagNodeQueue *queue); -DagNode *get_top_node_queue(DagNodeQueue *queue); -void queue_delete(DagNodeQueue *queue); - -// Dag management -DagForest *dag_init(void); -DagForest *build_dag(struct Main *bmain, struct Scene *sce, short mask); -void free_forest(struct DagForest *Dag); -DagNode *dag_find_node(DagForest *forest, void *fob); -DagNode *dag_add_node(DagForest *forest, void *fob); -DagNode *dag_get_node(DagForest *forest, void *fob); -DagNode *dag_get_sub_node(DagForest *forest, void *fob); -void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, const char *name); - -typedef bool (*DagCollobjFilterFunction)(struct Object *obj, struct ModifierData *md); - -void dag_add_collision_relations(DagForest *dag, struct Scene *scene, Object *ob, DagNode *node, struct Group *group, int layer, unsigned int modifier_type, DagCollobjFilterFunction fn, bool dupli, const char *name); -void dag_add_forcefield_relations(DagForest *dag, struct Scene *scene, Object *ob, DagNode *node, struct EffectorWeights *eff, bool add_absorption, int skip_forcefield, const char *name); - -void graph_print_queue(DagNodeQueue *nqueue); -void graph_print_queue_dist(DagNodeQueue *nqueue); -void graph_print_adj_list(DagForest *dag); - -#endif /* __DEPSGRAPH_PRIVATE_H__ */ diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c index 792e9195f12..68bcfa878ac 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf.c +++ b/source/blender/blenkernel/intern/CCGSubSurf.c @@ -42,7 +42,7 @@ # include "opensubdiv_converter_capi.h" #endif -#include "GL/glew.h" +#include "GPU_glew.h" /***/ diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c index f568bb94ac5..c26112d3724 100644 --- a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c +++ b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c @@ -43,7 +43,7 @@ #include "opensubdiv_capi.h" #include "opensubdiv_converter_capi.h" -#include "GL/glew.h" +#include "GPU_glew.h" #include "GPU_extensions.h" #define OSD_LOG if (false) printf @@ -995,7 +995,7 @@ void ccgSubSurf__sync_subdivUvs(CCGSubSurf *ss, bool subdiv_uvs) void BKE_subsurf_osd_init(void) { - openSubdiv_init(GPU_legacy_support()); + openSubdiv_init(); BLI_spin_init(&delete_spin); } diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index 26aecb526d4..67463ffe915 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -51,15 +51,19 @@ #include "BLI_linklist.h" #include "BLI_task.h" +#include "DEG_depsgraph.h" + #include "BKE_cdderivedmesh.h" #include "BKE_colorband.h" #include "BKE_editmesh.h" #include "BKE_key.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_material.h" #include "BKE_modifier.h" #include "BKE_mesh.h" #include "BKE_mesh_mapping.h" +#include "BKE_mesh_tangent.h" #include "BKE_object.h" #include "BKE_object_deform.h" #include "BKE_paint.h" @@ -76,11 +80,12 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm); #include "BLI_sys_types.h" /* for intptr_t support */ #include "GPU_buffers.h" -#include "GPU_glew.h" #include "GPU_shader.h" +#include "GPU_immediate.h" #ifdef WITH_OPENSUBDIV -# include "BKE_depsgraph.h" +# include "DEG_depsgraph.h" +# include "DEG_depsgraph_query.h" # include "DNA_userdef_types.h" #endif @@ -347,7 +352,7 @@ void DM_init( dm->numPolyData = numPolys; DM_init_funcs(dm); - + dm->needsFree = 1; dm->auto_bump_scale = -1.0f; dm->dirty = 0; @@ -407,6 +412,7 @@ int DM_release(DerivedMesh *dm) if (dm->needsFree) { bvhcache_free(&dm->bvhCache); GPU_drawobject_free(dm); + CustomData_free(&dm->vertData, dm->numVertData); CustomData_free(&dm->edgeData, dm->numEdgeData); CustomData_free(&dm->faceData, dm->numTessFaceData); @@ -552,7 +558,6 @@ void DM_update_tessface_data(DerivedMesh *dm) MLoop *ml = dm->getLoopArray(dm); CustomData *fdata = dm->getTessFaceDataLayout(dm); - CustomData *pdata = dm->getPolyDataLayout(dm); CustomData *ldata = dm->getLoopDataLayout(dm); const int totface = dm->getNumTessFaces(dm); @@ -565,7 +570,7 @@ void DM_update_tessface_data(DerivedMesh *dm) if (!polyindex) return; - CustomData_from_bmeshpoly(fdata, pdata, ldata, totface); + CustomData_from_bmeshpoly(fdata, ldata, totface); if (CustomData_has_layer(fdata, CD_MTFACE) || CustomData_has_layer(fdata, CD_MCOL) || @@ -597,7 +602,7 @@ void DM_update_tessface_data(DerivedMesh *dm) * 0 for quads (because our quads may have been rotated compared to their org poly, see tessellation code). * So we pass the MFace's, and BKE_mesh_loops_to_tessdata will use MFace->v4 index as quad test. */ - BKE_mesh_loops_to_tessdata(fdata, ldata, pdata, mface, polyindex, loopindex, totface); + BKE_mesh_loops_to_tessdata(fdata, ldata, mface, polyindex, loopindex, totface); MEM_freeN(loopindex); } @@ -615,7 +620,6 @@ void DM_generate_tangent_tessface_data(DerivedMesh *dm, bool generate) MLoop *ml = dm->getLoopArray(dm); CustomData *fdata = dm->getTessFaceDataLayout(dm); - CustomData *pdata = dm->getPolyDataLayout(dm); CustomData *ldata = dm->getLoopDataLayout(dm); const int totface = dm->getNumTessFaces(dm); @@ -632,7 +636,7 @@ void DM_generate_tangent_tessface_data(DerivedMesh *dm, bool generate) for (int j = 0; j < ldata->totlayer; j++) { if (ldata->layers[j].type == CD_TANGENT) { CustomData_add_layer_named(fdata, CD_TANGENT, CD_CALLOC, NULL, totface, ldata->layers[j].name); - CustomData_bmesh_update_active_layers(fdata, pdata, ldata); + CustomData_bmesh_update_active_layers(fdata, ldata); if (!loopindex) { loopindex = MEM_malloc_arrayN(totface, sizeof(*loopindex), __func__); @@ -662,7 +666,7 @@ void DM_generate_tangent_tessface_data(DerivedMesh *dm, bool generate) } if (loopindex) MEM_freeN(loopindex); - BLI_assert(CustomData_from_bmeshpoly_test(fdata, pdata, ldata, true)); + BLI_assert(CustomData_from_bmeshpoly_test(fdata, ldata, true)); } if (G.debug & G_DEBUG) @@ -1147,7 +1151,7 @@ DerivedMesh *mesh_create_derived(Mesh *me, float (*vertCos)[3]) } DerivedMesh *mesh_create_derived_for_modifier( - Scene *scene, Object *ob, + const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, ModifierData *md, int build_shapekey_layers) { Mesh *me = ob->data; @@ -1173,7 +1177,7 @@ DerivedMesh *mesh_create_derived_for_modifier( int numVerts; float (*deformedVerts)[3] = BKE_mesh_vertexCos_get(me, &numVerts); - modwrap_deformVerts(md, ob, NULL, deformedVerts, numVerts, 0); + modwrap_deformVerts(md, eval_ctx, ob, NULL, deformedVerts, numVerts, 0); dm = mesh_create_derived(me, deformedVerts); if (build_shapekey_layers) @@ -1187,7 +1191,7 @@ DerivedMesh *mesh_create_derived_for_modifier( if (build_shapekey_layers) add_shapekey_layers(tdm, me, ob); - dm = modwrap_applyModifier(md, ob, tdm, 0); + dm = modwrap_applyModifier(md, eval_ctx, ob, tdm, 0); ASSERT_IS_VALID_DM(dm); if (tdm != dm) tdm->release(tdm); @@ -1752,7 +1756,7 @@ static void dm_ensure_display_normals(DerivedMesh *dm) * - apply deform modifiers and input vertexco */ static void mesh_calc_modifiers( - Scene *scene, Object *ob, float (*inputVertexCos)[3], + const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float (*inputVertexCos)[3], const bool useRenderParams, int useDeform, const bool need_mapping, CustomDataMask dataMask, const int index, const bool useCache, const bool build_shapekey_layers, @@ -1774,17 +1778,19 @@ static void mesh_calc_modifiers( 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 && !useRenderParams; + const bool sculpt_mode = eval_ctx->object_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, me); /* Generic preview only in object mode! */ - const bool do_mod_mcol = (ob->mode == OB_MODE_OBJECT); + const bool do_mod_mcol = (eval_ctx->object_mode == OB_MODE_OBJECT); #if 0 /* XXX Will re-enable this when we have global mod stack options. */ const bool do_final_wmcol = (scene->toolsettings->weights_preview == WP_WPREVIEW_FINAL) && do_wmcol; #endif const bool do_final_wmcol = false; - const bool do_init_wmcol = ((dataMask & CD_MASK_PREVIEW_MLOOPCOL) && (ob->mode & OB_MODE_WEIGHT_PAINT) && !do_final_wmcol); + const bool do_init_wmcol = ( + (dataMask & CD_MASK_PREVIEW_MLOOPCOL) && + (eval_ctx->object_mode & OB_MODE_WEIGHT_PAINT) && !do_final_wmcol); /* XXX Same as above... For now, only weights preview in WPaint mode. */ const bool do_mod_wmcol = do_init_wmcol; @@ -1863,7 +1869,7 @@ static void mesh_calc_modifiers( if (!deformedVerts) deformedVerts = BKE_mesh_vertexCos_get(me, &numVerts); - modwrap_deformVerts(md, ob, NULL, deformedVerts, numVerts, deform_app_flags); + modwrap_deformVerts(md, eval_ctx, ob, NULL, deformedVerts, numVerts, deform_app_flags); } else { break; @@ -2004,7 +2010,7 @@ static void mesh_calc_modifiers( } } - modwrap_deformVerts(md, ob, dm, deformedVerts, numVerts, deform_app_flags); + modwrap_deformVerts(md, eval_ctx, ob, dm, deformedVerts, numVerts, deform_app_flags); } else { DerivedMesh *ndm; @@ -2079,7 +2085,7 @@ static void mesh_calc_modifiers( } } - ndm = modwrap_applyModifier(md, ob, dm, app_flags); + ndm = modwrap_applyModifier(md, eval_ctx, ob, dm, app_flags); ASSERT_IS_VALID_DM(ndm); if (ndm) { @@ -2106,7 +2112,7 @@ static void mesh_calc_modifiers( (mti->requiredDataMask ? mti->requiredDataMask(ob, md) : 0)); - ndm = modwrap_applyModifier(md, ob, orcodm, (app_flags & ~MOD_APPLY_USECACHE) | MOD_APPLY_ORCO); + ndm = modwrap_applyModifier(md, eval_ctx, ob, orcodm, (app_flags & ~MOD_APPLY_USECACHE) | MOD_APPLY_ORCO); ASSERT_IS_VALID_DM(ndm); if (ndm) { @@ -2124,7 +2130,7 @@ static void mesh_calc_modifiers( nextmask &= ~CD_MASK_CLOTH_ORCO; DM_set_only_copy(clothorcodm, nextmask | CD_MASK_ORIGINDEX); - ndm = modwrap_applyModifier(md, ob, clothorcodm, (app_flags & ~MOD_APPLY_USECACHE) | MOD_APPLY_ORCO); + ndm = modwrap_applyModifier(md, eval_ctx, ob, clothorcodm, (app_flags & ~MOD_APPLY_USECACHE) | MOD_APPLY_ORCO); ASSERT_IS_VALID_DM(ndm); if (ndm) { @@ -2307,8 +2313,8 @@ bool editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh * } static void editbmesh_calc_modifiers( - Scene *scene, Object *ob, BMEditMesh *em, - CustomDataMask dataMask, + const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, + BMEditMesh *em, CustomDataMask dataMask, /* return args */ DerivedMesh **r_cage, DerivedMesh **r_final) { @@ -2395,9 +2401,9 @@ static void editbmesh_calc_modifiers( } if (mti->deformVertsEM) - modwrap_deformVertsEM(md, ob, em, dm, deformedVerts, numVerts); + modwrap_deformVertsEM(md, eval_ctx, ob, em, dm, deformedVerts, numVerts); else - modwrap_deformVerts(md, ob, dm, deformedVerts, numVerts, 0); + modwrap_deformVerts(md, eval_ctx, ob, dm, deformedVerts, numVerts, 0); } else { DerivedMesh *ndm; @@ -2442,10 +2448,10 @@ static void editbmesh_calc_modifiers( DM_set_only_copy(orcodm, mask | CD_MASK_ORIGINDEX); if (mti->applyModifierEM) { - ndm = modwrap_applyModifierEM(md, ob, em, orcodm, MOD_APPLY_ORCO); + ndm = modwrap_applyModifierEM(md, eval_ctx, ob, em, orcodm, MOD_APPLY_ORCO); } else { - ndm = modwrap_applyModifier(md, ob, orcodm, MOD_APPLY_ORCO); + ndm = modwrap_applyModifier(md, eval_ctx, ob, orcodm, MOD_APPLY_ORCO); } ASSERT_IS_VALID_DM(ndm); @@ -2470,9 +2476,9 @@ static void editbmesh_calc_modifiers( } if (mti->applyModifierEM) - ndm = modwrap_applyModifierEM(md, ob, em, dm, MOD_APPLY_USECACHE | MOD_APPLY_ALLOW_GPU); + ndm = modwrap_applyModifierEM(md, eval_ctx, ob, em, dm, MOD_APPLY_USECACHE | MOD_APPLY_ALLOW_GPU); else - ndm = modwrap_applyModifier(md, ob, dm, MOD_APPLY_USECACHE | MOD_APPLY_ALLOW_GPU); + ndm = modwrap_applyModifier(md, eval_ctx, ob, dm, MOD_APPLY_USECACHE | MOD_APPLY_ALLOW_GPU); ASSERT_IS_VALID_DM(ndm); if (ndm) { @@ -2608,7 +2614,8 @@ static void editbmesh_calc_modifiers( * we'll be using GPU backend of OpenSubdiv. This is so * playback performance is kept as high as possible. */ -static bool calc_modifiers_skip_orco(Scene *scene, +static bool calc_modifiers_skip_orco(const EvaluationContext *eval_ctx, + Scene *scene, Object *ob, bool use_render_params) { @@ -2621,10 +2628,10 @@ static bool calc_modifiers_skip_orco(Scene *scene, if (U.opensubdiv_compute_type == USER_OPENSUBDIV_COMPUTE_NONE) { return false; } - else if ((ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) != 0) { + else if ((eval_ctx->object_mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) != 0) { return false; } - else if ((DAG_get_eval_flags_for_object(scene, ob) & DAG_EVAL_NEED_CPU) != 0) { + else if ((DEG_get_eval_flags_for_id(eval_ctx->depsgraph, &ob->id) & DAG_EVAL_NEED_CPU) != 0) { return false; } SubsurfModifierData *smd = (SubsurfModifierData *)last_md; @@ -2636,7 +2643,7 @@ static bool calc_modifiers_skip_orco(Scene *scene, #endif static void mesh_build_data( - Scene *scene, Object *ob, CustomDataMask dataMask, + const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, CustomDataMask dataMask, const bool build_shapekey_layers, const bool need_mapping) { BLI_assert(ob->type == OB_MESH); @@ -2645,13 +2652,13 @@ static void mesh_build_data( BKE_object_sculpt_modifiers_changed(ob); #ifdef WITH_OPENSUBDIV - if (calc_modifiers_skip_orco(scene, ob, false)) { + if (calc_modifiers_skip_orco(eval_ctx, scene, ob, false)) { dataMask &= ~(CD_MASK_ORCO | CD_MASK_PREVIEW_MCOL); } #endif mesh_calc_modifiers( - scene, ob, NULL, false, 1, need_mapping, dataMask, -1, true, build_shapekey_layers, + eval_ctx, scene, ob, NULL, false, 1, need_mapping, dataMask, -1, true, build_shapekey_layers, true, &ob->derivedDeform, &ob->derivedFinal); @@ -2662,17 +2669,19 @@ static void mesh_build_data( ob->lastDataMask = dataMask; ob->lastNeedMapping = need_mapping; - if ((ob->mode & OB_MODE_ALL_SCULPT) && ob->sculpt) { + if ((eval_ctx->object_mode & OB_MODE_ALL_SCULPT) && ob->sculpt) { /* create PBVH immediately (would be created on the fly too, * but this avoids waiting on first stroke) */ - BKE_sculpt_update_mesh_elements(scene, scene->toolsettings->sculpt, ob, false, false); + BKE_sculpt_update_mesh_elements(eval_ctx, scene, scene->toolsettings->sculpt, ob, false, false); } BLI_assert(!(ob->derivedFinal->dirty & DM_DIRTY_NORMALS)); } -static void editbmesh_build_data(Scene *scene, Object *obedit, BMEditMesh *em, CustomDataMask dataMask) +static void editbmesh_build_data( + const struct EvaluationContext *eval_ctx, Scene *scene, + Object *obedit, BMEditMesh *em, CustomDataMask dataMask) { BKE_object_free_derived_caches(obedit); BKE_object_sculpt_modifiers_changed(obedit); @@ -2680,13 +2689,13 @@ static void editbmesh_build_data(Scene *scene, Object *obedit, BMEditMesh *em, C BKE_editmesh_free_derivedmesh(em); #ifdef WITH_OPENSUBDIV - if (calc_modifiers_skip_orco(scene, obedit, false)) { + if (calc_modifiers_skip_orco(eval_ctx, scene, obedit, false)) { dataMask &= ~(CD_MASK_ORCO | CD_MASK_PREVIEW_MCOL); } #endif editbmesh_calc_modifiers( - scene, obedit, em, dataMask, + eval_ctx, scene, obedit, em, dataMask, &em->derivedCage, &em->derivedFinal); DM_set_object_boundbox(obedit, em->derivedFinal); @@ -2698,9 +2707,13 @@ static void editbmesh_build_data(Scene *scene, Object *obedit, BMEditMesh *em, C BLI_assert(!(em->derivedFinal->dirty & DM_DIRTY_NORMALS)); } -static CustomDataMask object_get_datamask(const Scene *scene, Object *ob, bool *r_need_mapping) +static CustomDataMask object_get_datamask( + const EvaluationContext *eval_ctx, + const Scene *scene, Object *ob, bool *r_need_mapping) { - Object *actob = scene->basact ? scene->basact->object : NULL; + /* TODO(sergey): Avoid this linear list lookup. */ + ViewLayer *view_layer = BKE_view_layer_context_active_PLACEHOLDER(scene); + Object *actob = view_layer->basact ? view_layer->basact->object : NULL; CustomDataMask mask = ob->customdata_mask; if (r_need_mapping) { @@ -2708,28 +2721,28 @@ static CustomDataMask object_get_datamask(const Scene *scene, Object *ob, bool * } if (ob == actob) { - bool editing = BKE_paint_select_face_test(ob); + bool editing = BKE_paint_select_face_test(ob, eval_ctx->object_mode); /* weight paint and face select need original indices because of selection buffer drawing */ if (r_need_mapping) { - *r_need_mapping = (editing || (ob->mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT))); + *r_need_mapping = (editing || (eval_ctx->object_mode & (OB_MODE_WEIGHT_PAINT | OB_MODE_VERTEX_PAINT))); } /* check if we need tfaces & mcols due to face select or texture paint */ - if ((ob->mode & OB_MODE_TEXTURE_PAINT) || editing) { + if ((eval_ctx->object_mode & OB_MODE_TEXTURE_PAINT) || editing) { mask |= CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL; } /* check if we need mcols due to vertex paint or weightpaint */ - if (ob->mode & OB_MODE_VERTEX_PAINT) { + if (eval_ctx->object_mode & OB_MODE_VERTEX_PAINT) { mask |= CD_MASK_MLOOPCOL; } - if (ob->mode & OB_MODE_WEIGHT_PAINT) { + if (eval_ctx->object_mode & OB_MODE_WEIGHT_PAINT) { mask |= CD_MASK_PREVIEW_MLOOPCOL; } - if (ob->mode & OB_MODE_EDIT) + if (eval_ctx->object_mode & OB_MODE_EDIT) mask |= CD_MASK_MVERT_SKIN; } @@ -2737,85 +2750,86 @@ static CustomDataMask object_get_datamask(const Scene *scene, Object *ob, bool * } void makeDerivedMesh( - Scene *scene, Object *ob, BMEditMesh *em, + const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, BMEditMesh *em, CustomDataMask dataMask, const bool build_shapekey_layers) { bool need_mapping; - dataMask |= object_get_datamask(scene, ob, &need_mapping); + dataMask |= object_get_datamask(eval_ctx, scene, ob, &need_mapping); if (em) { - editbmesh_build_data(scene, ob, em, dataMask); + editbmesh_build_data(eval_ctx, scene, ob, em, dataMask); } else { - mesh_build_data(scene, ob, dataMask, build_shapekey_layers, need_mapping); + mesh_build_data(eval_ctx, scene, ob, dataMask, build_shapekey_layers, need_mapping); } } /***/ -DerivedMesh *mesh_get_derived_final(Scene *scene, Object *ob, CustomDataMask dataMask) +DerivedMesh *mesh_get_derived_final( + const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, CustomDataMask dataMask) { /* if there's no derived mesh or the last data mask used doesn't include * the data we need, rebuild the derived mesh */ bool need_mapping; - dataMask |= object_get_datamask(scene, ob, &need_mapping); + dataMask |= object_get_datamask(eval_ctx, scene, ob, &need_mapping); if (!ob->derivedFinal || ((dataMask & ob->lastDataMask) != dataMask) || (need_mapping != ob->lastNeedMapping)) { - mesh_build_data(scene, ob, dataMask, false, need_mapping); + mesh_build_data(eval_ctx, scene, ob, dataMask, false, need_mapping); } if (ob->derivedFinal) { BLI_assert(!(ob->derivedFinal->dirty & DM_DIRTY_NORMALS)); } return ob->derivedFinal; } -DerivedMesh *mesh_get_derived_deform(Scene *scene, Object *ob, CustomDataMask dataMask) +DerivedMesh *mesh_get_derived_deform(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, CustomDataMask dataMask) { /* if there's no derived mesh or the last data mask used doesn't include * the data we need, rebuild the derived mesh */ bool need_mapping; - dataMask |= object_get_datamask(scene, ob, &need_mapping); + dataMask |= object_get_datamask(eval_ctx, scene, ob, &need_mapping); if (!ob->derivedDeform || ((dataMask & ob->lastDataMask) != dataMask) || (need_mapping != ob->lastNeedMapping)) { - mesh_build_data(scene, ob, dataMask, false, need_mapping); + mesh_build_data(eval_ctx, scene, ob, dataMask, false, need_mapping); } return ob->derivedDeform; } -DerivedMesh *mesh_create_derived_render(Scene *scene, Object *ob, CustomDataMask dataMask) +DerivedMesh *mesh_create_derived_render(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, CustomDataMask dataMask) { DerivedMesh *final; mesh_calc_modifiers( - scene, ob, NULL, true, 1, false, dataMask, -1, false, false, false, + eval_ctx, scene, ob, NULL, true, 1, false, dataMask, -1, false, false, false, NULL, &final); return final; } -DerivedMesh *mesh_create_derived_index_render(Scene *scene, Object *ob, CustomDataMask dataMask, int index) +DerivedMesh *mesh_create_derived_index_render(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, CustomDataMask dataMask, int index) { DerivedMesh *final; mesh_calc_modifiers( - scene, ob, NULL, true, 1, false, dataMask, index, false, false, false, + eval_ctx, scene, ob, NULL, true, 1, false, dataMask, index, false, false, false, NULL, &final); return final; } DerivedMesh *mesh_create_derived_view( - Scene *scene, Object *ob, - CustomDataMask dataMask) + const struct EvaluationContext *eval_ctx, Scene *scene, + Object *ob, CustomDataMask dataMask) { DerivedMesh *final; @@ -2826,7 +2840,7 @@ DerivedMesh *mesh_create_derived_view( ob->transflag |= OB_NO_PSYS_UPDATE; mesh_calc_modifiers( - scene, ob, NULL, false, 1, false, dataMask, -1, false, false, false, + eval_ctx, scene, ob, NULL, false, 1, false, dataMask, -1, false, false, false, NULL, &final); ob->transflag &= ~OB_NO_PSYS_UPDATE; @@ -2835,53 +2849,53 @@ DerivedMesh *mesh_create_derived_view( } DerivedMesh *mesh_create_derived_no_deform( - Scene *scene, Object *ob, float (*vertCos)[3], - CustomDataMask dataMask) + const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, + float (*vertCos)[3], CustomDataMask dataMask) { DerivedMesh *final; mesh_calc_modifiers( - scene, ob, vertCos, false, 0, false, dataMask, -1, false, false, false, + eval_ctx, scene, ob, vertCos, false, 0, false, dataMask, -1, false, false, false, NULL, &final); return final; } DerivedMesh *mesh_create_derived_no_virtual( - Scene *scene, Object *ob, float (*vertCos)[3], - CustomDataMask dataMask) + const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, + float (*vertCos)[3], CustomDataMask dataMask) { DerivedMesh *final; mesh_calc_modifiers( - scene, ob, vertCos, false, -1, false, dataMask, -1, false, false, false, + eval_ctx, scene, ob, vertCos, false, -1, false, dataMask, -1, false, false, false, NULL, &final); return final; } DerivedMesh *mesh_create_derived_physics( - Scene *scene, Object *ob, float (*vertCos)[3], - CustomDataMask dataMask) + const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, + float (*vertCos)[3], CustomDataMask dataMask) { DerivedMesh *final; mesh_calc_modifiers( - scene, ob, vertCos, false, -1, true, dataMask, -1, false, false, false, + eval_ctx, scene, ob, vertCos, false, -1, true, dataMask, -1, false, false, false, NULL, &final); return final; } DerivedMesh *mesh_create_derived_no_deform_render( - Scene *scene, Object *ob, - float (*vertCos)[3], + const struct EvaluationContext *eval_ctx, Scene *scene, + Object *ob, float (*vertCos)[3], CustomDataMask dataMask) { DerivedMesh *final; mesh_calc_modifiers( - scene, ob, vertCos, true, 0, false, dataMask, -1, false, false, false, + eval_ctx, scene, ob, vertCos, true, 0, false, dataMask, -1, false, false, false, NULL, &final); return final; @@ -2890,7 +2904,7 @@ DerivedMesh *mesh_create_derived_no_deform_render( /***/ DerivedMesh *editbmesh_get_derived_cage_and_final( - Scene *scene, Object *obedit, BMEditMesh *em, + const struct EvaluationContext *eval_ctx, Scene *scene, Object *obedit, BMEditMesh *em, CustomDataMask dataMask, /* return args */ DerivedMesh **r_final) @@ -2898,12 +2912,12 @@ DerivedMesh *editbmesh_get_derived_cage_and_final( /* if there's no derived mesh or the last data mask used doesn't include * the data we need, rebuild the derived mesh */ - dataMask |= object_get_datamask(scene, obedit, NULL); + dataMask |= object_get_datamask(eval_ctx, scene, obedit, NULL); if (!em->derivedCage || (em->lastDataMask & dataMask) != dataMask) { - editbmesh_build_data(scene, obedit, em, dataMask); + editbmesh_build_data(eval_ctx, scene, obedit, em, dataMask); } *r_final = em->derivedFinal; @@ -2911,17 +2925,19 @@ DerivedMesh *editbmesh_get_derived_cage_and_final( return em->derivedCage; } -DerivedMesh *editbmesh_get_derived_cage(Scene *scene, Object *obedit, BMEditMesh *em, CustomDataMask dataMask) +DerivedMesh *editbmesh_get_derived_cage( + const struct EvaluationContext *eval_ctx, Scene *scene, Object *obedit, BMEditMesh *em, + CustomDataMask dataMask) { /* if there's no derived mesh or the last data mask used doesn't include * the data we need, rebuild the derived mesh */ - dataMask |= object_get_datamask(scene, obedit, NULL); + dataMask |= object_get_datamask(eval_ctx, scene, obedit, NULL); if (!em->derivedCage || (em->lastDataMask & dataMask) != dataMask) { - editbmesh_build_data(scene, obedit, em, dataMask); + editbmesh_build_data(eval_ctx, scene, obedit, em, dataMask); } return em->derivedCage; @@ -3058,234 +3074,6 @@ void mesh_get_mapped_verts_coords(DerivedMesh *dm, float (*r_cos)[3], const int /* ******************* GLSL ******************** */ -/** \name Tangent Space Calculation - * \{ */ - -/* Necessary complexity to handle looptri's as quads for correct tangents */ -#define USE_LOOPTRI_DETECT_QUADS - -typedef struct { - float (*precomputedFaceNormals)[3]; - float (*precomputedLoopNormals)[3]; - const MLoopTri *looptri; - MLoopUV *mloopuv; /* texture coordinates */ - MPoly *mpoly; /* indices */ - MLoop *mloop; /* indices */ - MVert *mvert; /* vertices & normals */ - float (*orco)[3]; - float (*tangent)[4]; /* destination */ - int numTessFaces; - -#ifdef USE_LOOPTRI_DETECT_QUADS - /* map from 'fake' face index to looptri, - * quads will point to the first looptri of the quad */ - const int *face_as_quad_map; - int num_face_as_quad_map; -#endif - -} SGLSLMeshToTangent; - -/* interface */ -#include "mikktspace.h" - -static int dm_ts_GetNumFaces(const SMikkTSpaceContext *pContext) -{ - SGLSLMeshToTangent *pMesh = pContext->m_pUserData; - -#ifdef USE_LOOPTRI_DETECT_QUADS - return pMesh->num_face_as_quad_map; -#else - return pMesh->numTessFaces; -#endif -} - -static int dm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num) -{ -#ifdef USE_LOOPTRI_DETECT_QUADS - SGLSLMeshToTangent *pMesh = pContext->m_pUserData; - if (pMesh->face_as_quad_map) { - const MLoopTri *lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]]; - const MPoly *mp = &pMesh->mpoly[lt->poly]; - if (mp->totloop == 4) { - return 4; - } - } - return 3; -#else - UNUSED_VARS(pContext, face_num); - return 3; -#endif -} - -static void dm_ts_GetPosition( - const SMikkTSpaceContext *pContext, float r_co[3], - const int face_num, const int vert_index) -{ - //assert(vert_index >= 0 && vert_index < 4); - SGLSLMeshToTangent *pMesh = pContext->m_pUserData; - const MLoopTri *lt; - int loop_index; - const float *co; - -#ifdef USE_LOOPTRI_DETECT_QUADS - if (pMesh->face_as_quad_map) { - lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]]; - const MPoly *mp = &pMesh->mpoly[lt->poly]; - if (mp->totloop == 4) { - loop_index = mp->loopstart + vert_index; - goto finally; - } - /* fall through to regular triangle */ - } - else { - lt = &pMesh->looptri[face_num]; - } -#else - lt = &pMesh->looptri[face_num]; -#endif - loop_index = lt->tri[vert_index]; - -finally: - co = pMesh->mvert[pMesh->mloop[loop_index].v].co; - copy_v3_v3(r_co, co); -} - -static void dm_ts_GetTextureCoordinate( - const SMikkTSpaceContext *pContext, float r_uv[2], - const int face_num, const int vert_index) -{ - //assert(vert_index >= 0 && vert_index < 4); - SGLSLMeshToTangent *pMesh = pContext->m_pUserData; - const MLoopTri *lt; - int loop_index; - -#ifdef USE_LOOPTRI_DETECT_QUADS - if (pMesh->face_as_quad_map) { - lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]]; - const MPoly *mp = &pMesh->mpoly[lt->poly]; - if (mp->totloop == 4) { - loop_index = mp->loopstart + vert_index; - goto finally; - } - /* fall through to regular triangle */ - } - else { - lt = &pMesh->looptri[face_num]; - } -#else - lt = &pMesh->looptri[face_num]; -#endif - loop_index = lt->tri[vert_index]; - -finally: - if (pMesh->mloopuv != NULL) { - const float *uv = pMesh->mloopuv[loop_index].uv; - copy_v2_v2(r_uv, uv); - } - else { - const float *orco = pMesh->orco[pMesh->mloop[loop_index].v]; - map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]); - } -} - -static void dm_ts_GetNormal( - const SMikkTSpaceContext *pContext, float r_no[3], - const int face_num, const int vert_index) -{ - //assert(vert_index >= 0 && vert_index < 4); - SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; - const MLoopTri *lt; - int loop_index; - -#ifdef USE_LOOPTRI_DETECT_QUADS - if (pMesh->face_as_quad_map) { - lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]]; - const MPoly *mp = &pMesh->mpoly[lt->poly]; - if (mp->totloop == 4) { - loop_index = mp->loopstart + vert_index; - goto finally; - } - /* fall through to regular triangle */ - } - else { - lt = &pMesh->looptri[face_num]; - } -#else - lt = &pMesh->looptri[face_num]; -#endif - loop_index = lt->tri[vert_index]; - -finally: - if (pMesh->precomputedLoopNormals) { - copy_v3_v3(r_no, pMesh->precomputedLoopNormals[loop_index]); - } - else if ((pMesh->mpoly[lt->poly].flag & ME_SMOOTH) == 0) { /* flat */ - if (pMesh->precomputedFaceNormals) { - copy_v3_v3(r_no, pMesh->precomputedFaceNormals[lt->poly]); - } - else { -#ifdef USE_LOOPTRI_DETECT_QUADS - const MPoly *mp = &pMesh->mpoly[lt->poly]; - if (mp->totloop == 4) { - normal_quad_v3( - r_no, - pMesh->mvert[pMesh->mloop[mp->loopstart + 0].v].co, - pMesh->mvert[pMesh->mloop[mp->loopstart + 1].v].co, - pMesh->mvert[pMesh->mloop[mp->loopstart + 2].v].co, - pMesh->mvert[pMesh->mloop[mp->loopstart + 3].v].co); - } - else -#endif - { - normal_tri_v3( - r_no, - pMesh->mvert[pMesh->mloop[lt->tri[0]].v].co, - pMesh->mvert[pMesh->mloop[lt->tri[1]].v].co, - pMesh->mvert[pMesh->mloop[lt->tri[2]].v].co); - } - } - } - else { - const short *no = pMesh->mvert[pMesh->mloop[loop_index].v].no; - normal_short_to_float_v3(r_no, no); - } -} - -static void dm_ts_SetTSpace( - const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign, - const int face_num, const int vert_index) -{ - //assert(vert_index >= 0 && vert_index < 4); - SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; - const MLoopTri *lt; - int loop_index; - -#ifdef USE_LOOPTRI_DETECT_QUADS - if (pMesh->face_as_quad_map) { - lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]]; - const MPoly *mp = &pMesh->mpoly[lt->poly]; - if (mp->totloop == 4) { - loop_index = mp->loopstart + vert_index; - goto finally; - } - /* fall through to regular triangle */ - } - else { - lt = &pMesh->looptri[face_num]; - } -#else - lt = &pMesh->looptri[face_num]; -#endif - loop_index = lt->tri[vert_index]; - - float *pRes; - -finally: - pRes = pMesh->tangent[loop_index]; - copy_v3_v3(pRes, fvTangent); - pRes[3] = fSign; -} - void DM_calc_tangents_names_from_gpu( const GPUVertexAttribs *gattribs, char (*tangent_names)[MAX_NAME], int *r_tangent_names_count) @@ -3299,28 +3087,6 @@ void DM_calc_tangents_names_from_gpu( *r_tangent_names_count = count; } -static void DM_calc_loop_tangents_thread(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid)) -{ - struct SGLSLMeshToTangent *mesh2tangent = taskdata; - /* new computation method */ - { - SMikkTSpaceContext sContext = {NULL}; - SMikkTSpaceInterface sInterface = {NULL}; - - sContext.m_pUserData = mesh2tangent; - sContext.m_pInterface = &sInterface; - sInterface.m_getNumFaces = dm_ts_GetNumFaces; - sInterface.m_getNumVerticesOfFace = dm_ts_GetNumVertsOfFace; - sInterface.m_getPosition = dm_ts_GetPosition; - sInterface.m_getTexCoord = dm_ts_GetTextureCoordinate; - sInterface.m_getNormal = dm_ts_GetNormal; - sInterface.m_setTSpaceBasic = dm_ts_SetTSpace; - - /* 0 if failed */ - genTangSpaceDefault(&sContext); - } -} - void DM_add_named_tangent_layer_for_uv( CustomData *uv_data, CustomData *tan_data, int numLoopData, const char *layer_name) @@ -3334,213 +3100,26 @@ void DM_add_named_tangent_layer_for_uv( } } -/** - * Here we get some useful information such as active uv layer name and search if it is already in tangent_names. - * Also, we calculate tangent_mask that works as a descriptor of tangents state. - * If tangent_mask has changed, then recalculate tangents. - */ -void DM_calc_loop_tangents_step_0( - const CustomData *loopData, bool calc_active_tangent, - const char (*tangent_names)[MAX_NAME], int tangent_names_count, - bool *rcalc_act, bool *rcalc_ren, int *ract_uv_n, int *rren_uv_n, - char *ract_uv_name, char *rren_uv_name, short *rtangent_mask) -{ - /* Active uv in viewport */ - int layer_index = CustomData_get_layer_index(loopData, CD_MLOOPUV); - *ract_uv_n = CustomData_get_active_layer(loopData, CD_MLOOPUV); - ract_uv_name[0] = 0; - if (*ract_uv_n != -1) { - strcpy(ract_uv_name, loopData->layers[*ract_uv_n + layer_index].name); - } - - /* Active tangent in render */ - *rren_uv_n = CustomData_get_render_layer(loopData, CD_MLOOPUV); - rren_uv_name[0] = 0; - if (*rren_uv_n != -1) { - strcpy(rren_uv_name, loopData->layers[*rren_uv_n + layer_index].name); - } - - /* If active tangent not in tangent_names we take it into account */ - *rcalc_act = false; - *rcalc_ren = false; - for (int i = 0; i < tangent_names_count; i++) { - if (tangent_names[i][0] == 0) { - calc_active_tangent = true; - } - } - if (calc_active_tangent) { - *rcalc_act = true; - *rcalc_ren = true; - for (int i = 0; i < tangent_names_count; i++) { - if (STREQ(ract_uv_name, tangent_names[i])) - *rcalc_act = false; - if (STREQ(rren_uv_name, tangent_names[i])) - *rcalc_ren = false; - } - } - *rtangent_mask = 0; - - const int uv_layer_num = CustomData_number_of_layers(loopData, CD_MLOOPUV); - for (int n = 0; n < uv_layer_num; n++) { - const char *name = CustomData_get_layer_name(loopData, CD_MLOOPUV, n); - bool add = false; - for (int i = 0; i < tangent_names_count; i++) { - if (tangent_names[i][0] && STREQ(tangent_names[i], name)) { - add = true; - break; - } - } - if ((*rcalc_act && ract_uv_name[0] && STREQ(ract_uv_name, name)) || - (*rcalc_ren && rren_uv_name[0] && STREQ(rren_uv_name, name))) - { - add = true; - } - if (add) - *rtangent_mask |= 1 << n; - } - - if (uv_layer_num == 0) - *rtangent_mask |= DM_TANGENT_MASK_ORCO; -} - void DM_calc_loop_tangents( DerivedMesh *dm, bool calc_active_tangent, - const char (*tangent_names)[MAX_NAME], int tangent_names_count) -{ - int act_uv_n = -1; - int ren_uv_n = -1; - bool calc_act = false; - bool calc_ren = false; - char act_uv_name[MAX_NAME]; - char ren_uv_name[MAX_NAME]; - short tangent_mask = 0; - DM_calc_loop_tangents_step_0( - &dm->loopData, calc_active_tangent, tangent_names, tangent_names_count, - &calc_act, &calc_ren, &act_uv_n, &ren_uv_n, act_uv_name, ren_uv_name, &tangent_mask); - if ((dm->tangent_mask | tangent_mask) != dm->tangent_mask) { - /* Check we have all the needed layers */ - MPoly *mpoly = dm->getPolyArray(dm); - const MLoopTri *looptri = dm->getLoopTriArray(dm); - int totface = dm->getNumLoopTri(dm); - /* Allocate needed tangent layers */ - for (int i = 0; i < tangent_names_count; i++) - if (tangent_names[i][0]) - DM_add_named_tangent_layer_for_uv(&dm->loopData, &dm->loopData, dm->numLoopData, tangent_names[i]); - if ((tangent_mask & DM_TANGENT_MASK_ORCO) && CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, "") == -1) - CustomData_add_layer_named(&dm->loopData, CD_TANGENT, CD_CALLOC, NULL, dm->numLoopData, ""); - if (calc_act && act_uv_name[0]) - DM_add_named_tangent_layer_for_uv(&dm->loopData, &dm->loopData, dm->numLoopData, act_uv_name); - if (calc_ren && ren_uv_name[0]) - DM_add_named_tangent_layer_for_uv(&dm->loopData, &dm->loopData, dm->numLoopData, ren_uv_name); - -#ifdef USE_LOOPTRI_DETECT_QUADS - int num_face_as_quad_map; - int *face_as_quad_map = NULL; - - /* map faces to quads */ - if (totface != dm->getNumPolys(dm)) { - /* over alloc, since we dont know how many ngon or quads we have */ - - /* map fake face index to looptri */ - face_as_quad_map = MEM_malloc_arrayN(totface, sizeof(int), __func__); - int k, j; - for (k = 0, j = 0; j < totface; k++, j++) { - face_as_quad_map[k] = j; - /* step over all quads */ - if (mpoly[looptri[j].poly].totloop == 4) { - j++; /* skips the nest looptri */ - } - } - num_face_as_quad_map = k; - } - else { - num_face_as_quad_map = totface; - } -#endif - - /* Calculation */ - { - TaskScheduler *scheduler = BLI_task_scheduler_get(); - TaskPool *task_pool; - task_pool = BLI_task_pool_create(scheduler, NULL); - - dm->tangent_mask = 0; - /* Calculate tangent layers */ - SGLSLMeshToTangent data_array[MAX_MTFACE]; - const int tangent_layer_num = CustomData_number_of_layers(&dm->loopData, CD_TANGENT); - for (int n = 0; n < tangent_layer_num; n++) { - int index = CustomData_get_layer_index_n(&dm->loopData, CD_TANGENT, n); - BLI_assert(n < MAX_MTFACE); - SGLSLMeshToTangent *mesh2tangent = &data_array[n]; - mesh2tangent->numTessFaces = totface; -#ifdef USE_LOOPTRI_DETECT_QUADS - mesh2tangent->face_as_quad_map = face_as_quad_map; - mesh2tangent->num_face_as_quad_map = num_face_as_quad_map; -#endif - mesh2tangent->mvert = dm->getVertArray(dm); - mesh2tangent->mpoly = dm->getPolyArray(dm); - mesh2tangent->mloop = dm->getLoopArray(dm); - mesh2tangent->looptri = dm->getLoopTriArray(dm); - /* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled), - * have to check this is valid... - */ - mesh2tangent->precomputedLoopNormals = dm->getLoopDataArray(dm, CD_NORMAL); - mesh2tangent->precomputedFaceNormals = CustomData_get_layer(&dm->polyData, CD_NORMAL); - - mesh2tangent->orco = NULL; - mesh2tangent->mloopuv = CustomData_get_layer_named(&dm->loopData, CD_MLOOPUV, dm->loopData.layers[index].name); - - /* Fill the resulting tangent_mask */ - if (!mesh2tangent->mloopuv) { - mesh2tangent->orco = dm->getVertDataArray(dm, CD_ORCO); - if (!mesh2tangent->orco) - continue; - - dm->tangent_mask |= DM_TANGENT_MASK_ORCO; - } - else { - int uv_ind = CustomData_get_named_layer_index(&dm->loopData, CD_MLOOPUV, dm->loopData.layers[index].name); - int uv_start = CustomData_get_layer_index(&dm->loopData, CD_MLOOPUV); - BLI_assert(uv_ind != -1 && uv_start != -1); - BLI_assert(uv_ind - uv_start < MAX_MTFACE); - dm->tangent_mask |= 1 << (uv_ind - uv_start); - } - - mesh2tangent->tangent = dm->loopData.layers[index].data; - BLI_task_pool_push(task_pool, DM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW); - } - - BLI_assert(dm->tangent_mask == tangent_mask); - BLI_task_pool_work_and_wait(task_pool); - BLI_task_pool_free(task_pool); - } -#ifdef USE_LOOPTRI_DETECT_QUADS - if (face_as_quad_map) { - MEM_freeN(face_as_quad_map); - } -#undef USE_LOOPTRI_DETECT_QUADS - -#endif - - /* Update active layer index */ - int act_uv_index = CustomData_get_layer_index_n(&dm->loopData, CD_MLOOPUV, act_uv_n); - if (act_uv_index != -1) { - int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, dm->loopData.layers[act_uv_index].name); - CustomData_set_layer_active_index(&dm->loopData, CD_TANGENT, tan_index); - } /* else tangent has been built from orco */ - - /* Update render layer index */ - int ren_uv_index = CustomData_get_layer_index_n(&dm->loopData, CD_MLOOPUV, ren_uv_n); - if (ren_uv_index != -1) { - int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, dm->loopData.layers[ren_uv_index].name); - CustomData_set_layer_render_index(&dm->loopData, CD_TANGENT, tan_index); - } /* else tangent has been built from orco */ - } + const char (*tangent_names)[MAX_NAME], int tangent_names_len) +{ + BKE_mesh_calc_loop_tangent_ex( + dm->getVertArray(dm), + dm->getPolyArray(dm), dm->getNumPolys(dm), + dm->getLoopArray(dm), + dm->getLoopTriArray(dm), dm->getNumLoopTri(dm), + &dm->loopData, + calc_active_tangent, + tangent_names, tangent_names_len, + CustomData_get_layer(&dm->polyData, CD_NORMAL), + dm->getLoopDataArray(dm, CD_NORMAL), + dm->getVertDataArray(dm, CD_ORCO), /* may be NULL */ + /* result */ + &dm->loopData, dm->getNumLoops(dm), + &dm->tangent_mask); } -/** \} */ - - void DM_calc_auto_bump_scale(DerivedMesh *dm) { /* int totvert = dm->getNumVerts(dm); */ /* UNUSED */ @@ -3969,7 +3548,6 @@ BLI_INLINE void navmesh_intToCol(int i, float col[3]) static void navmesh_drawColored(DerivedMesh *dm) { - int a, glmode; MVert *mvert = (MVert *)CustomData_get_layer(&dm->vertData, CD_MVERT); MFace *mface = (MFace *)CustomData_get_layer(&dm->faceData, CD_MFACE); int *polygonIdx = (int *)CustomData_get_layer(&dm->polyData, CD_RECAST); @@ -3984,43 +3562,42 @@ static void navmesh_drawColored(DerivedMesh *dm) dm->drawEdges(dm, 0, 1); #endif - /* if (GPU_buffer_legacy(dm) ) */ /* TODO - VBO draw code, not high priority - campbell */ - { - DEBUG_VBO("Using legacy code. drawNavMeshColored\n"); - glBegin(glmode = GL_QUADS); - for (a = 0; a < dm->numTessFaceData; a++, mface++) { - int new_glmode = mface->v4 ? GL_QUADS : GL_TRIANGLES; - int pi = polygonIdx[a]; - if (pi <= 0) { - zero_v3(col); - } - else { - navmesh_intToCol(pi, col); - } + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); - if (new_glmode != glmode) { - glEnd(); - glBegin(glmode = new_glmode); - } - glColor3fv(col); - glVertex3fv(mvert[mface->v1].co); - glVertex3fv(mvert[mface->v2].co); - glVertex3fv(mvert[mface->v3].co); - if (mface->v4) { - glVertex3fv(mvert[mface->v4].co); - } + immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR); + + /* Note: batch drawing API would let us share vertices */ + immBeginAtMost(GWN_PRIM_TRIS, dm->numTessFaceData * 6); + for (int a = 0; a < dm->numTessFaceData; a++, mface++) { + int pi = polygonIdx[a]; + if (pi <= 0) { + zero_v3(col); + } + else { + navmesh_intToCol(pi, col); } - glEnd(); - } -} -static void navmesh_DM_drawFacesTex( - DerivedMesh *dm, - DMSetDrawOptionsTex UNUSED(setDrawOptions), - DMCompareDrawOptions UNUSED(compareDrawOptions), - void *UNUSED(userData), DMDrawFlag UNUSED(flag)) -{ - navmesh_drawColored(dm); + immSkipAttrib(color); + immVertex3fv(pos, mvert[mface->v1].co); + immSkipAttrib(color); + immVertex3fv(pos, mvert[mface->v2].co); + immAttrib3fv(color, col); + immVertex3fv(pos, mvert[mface->v3].co); + + if (mface->v4) { + /* this tess face is a quad, so draw the other triangle */ + immSkipAttrib(color); + immVertex3fv(pos, mvert[mface->v1].co); + immSkipAttrib(color); + immVertex3fv(pos, mvert[mface->v3].co); + immAttrib3fv(color, col); + immVertex3fv(pos, mvert[mface->v4].co); + } + } + immEnd(); + immUnbindProgram(); } static void navmesh_DM_drawFacesSolid( @@ -4056,7 +3633,6 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm) recastData = (int *)CustomData_get_layer(&result->polyData, CD_RECAST); /* note: This is not good design! - really should not be doing this */ - result->drawFacesTex = navmesh_DM_drawFacesTex; result->drawFacesSolid = navmesh_DM_drawFacesSolid; diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 034248df8d5..acb2db8d7ad 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -55,7 +55,6 @@ #include "BKE_animsys.h" #include "BKE_constraint.h" #include "BKE_deform.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_idprop.h" @@ -65,6 +64,8 @@ #include "BKE_main.h" #include "BKE_object.h" +#include "DEG_depsgraph_build.h" + #include "BIK_api.h" #include "RNA_access.h" @@ -587,6 +588,8 @@ void BKE_pose_copy_data_ex(bPose **dst, const bPose *src, const int flag, const if (pchan->prop) { pchan->prop = IDP_CopyProperty_ex(pchan->prop, flag); } + + pchan->draw_data = NULL; /* Drawing cache, no need to copy. */ } /* for now, duplicate Bone Groups too when doing this */ @@ -780,6 +783,9 @@ void BKE_pose_channel_free_ex(bPoseChannel *pchan, bool do_id_user) IDP_FreeProperty(pchan->prop); MEM_freeN(pchan->prop); } + + /* Cached data, for new draw manager rendering code. */ + MEM_SAFE_FREE(pchan->draw_data); } void BKE_pose_channel_free(bPoseChannel *pchan) @@ -1428,7 +1434,7 @@ void BKE_pose_tag_recalc(Main *bmain, bPose *pose) /* Depsgraph components depends on actual pose state, * if pose was changed depsgraph is to be updated as well. */ - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); } /* For the calculation of the effects of an Action at the given frame on an object diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 2f65e71c6d2..62df97c6afa 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -43,8 +43,8 @@ #include "DNA_key_types.h" #include "DNA_scene_types.h" +#include "BKE_context.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_key.h" #include "BKE_main.h" @@ -54,6 +54,9 @@ #include "BKE_anim.h" #include "BKE_report.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + // XXX bad level call... /* --------------------- */ @@ -273,88 +276,23 @@ void animviz_get_object_motionpaths(Object *ob, ListBase *targets) /* ........ */ -/* Note on evaluation optimizations: - * Optimization's currently used here play tricks with the depsgraph in order to try and - * evaluate as few objects as strictly necessary to get nicer performance under standard - * production conditions. For those people who really need the accurate version, - * disable the ifdef (i.e. 1 -> 0) and comment out the call to motionpaths_calc_optimise_depsgraph() - */ - -/* tweak the object ordering to trick depsgraph into making MotionPath calculations run faster */ -static void motionpaths_calc_optimise_depsgraph(Scene *scene, ListBase *targets) -{ - Base *base, *baseNext; - MPathTarget *mpt; - - /* make sure our temp-tag isn't already in use */ - for (base = scene->base.first; base; base = base->next) - base->object->flag &= ~BA_TEMP_TAG; - - /* for each target, dump its object to the start of the list if it wasn't moved already */ - for (mpt = targets->first; mpt; mpt = mpt->next) { - for (base = scene->base.first; base; base = baseNext) { - baseNext = base->next; - - if ((base->object == mpt->ob) && !(mpt->ob->flag & BA_TEMP_TAG)) { - BLI_remlink(&scene->base, base); - BLI_addhead(&scene->base, base); - - mpt->ob->flag |= BA_TEMP_TAG; - - /* we really don't need to continue anymore once this happens, but this line might really 'break' */ - break; - } - } - } - - /* "brew me a list that's sorted a bit faster now depsy" */ - DAG_scene_relations_rebuild(G.main, scene); -} - /* update scene for current frame */ -static void motionpaths_calc_update_scene(Scene *scene) +static void motionpaths_calc_update_scene(Main *bmain, + Scene *scene, + ViewLayer *view_layer, + struct Depsgraph *depsgraph) { -#if 1 // 'production' optimizations always on - /* rigid body simulation needs complete update to work correctly for now */ - /* RB_TODO investigate if we could avoid updating everything */ - if (BKE_scene_check_rigidbody_active(scene)) { - BKE_scene_update_for_newframe(G.main->eval_ctx, G.main, scene, scene->lay); - } - else { /* otherwise we can optimize by restricting updates */ - Base *base, *last = NULL; - - /* only stuff that moves or needs display still */ - DAG_scene_update_flags(G.main, scene, scene->lay, true, false); - - /* find the last object with the tag - * - all those afterwards are assumed to not be relevant for our calculations - */ - /* optimize further by moving out... */ - for (base = scene->base.first; base; base = base->next) { - if (base->object->flag & BA_TEMP_TAG) - last = base; - } - - /* perform updates for tagged objects */ - /* XXX: this will break if rigs depend on scene or other data that - * is animated but not attached to/updatable from objects */ - for (base = scene->base.first; base; base = base->next) { - /* update this object */ - BKE_object_handle_update(G.main->eval_ctx, scene, base->object); - - /* if this is the last one we need to update, let's stop to save some time */ - if (base == last) - break; - } - } -#else // original, 'always correct' version - /* do all updates + /* Do all updates * - if this is too slow, resort to using a more efficient way * that doesn't force complete update, but for now, this is the * most accurate way! + * + * TODO(segey): Bring back partial updates, which became impossible + * with the new depsgraph due to unsorted nature of bases. + * + * TODO(sergey): Use evaluation context dedicated to motion paths. */ - BKE_scene_update_for_newframe(G.main->eval_ctx, G.main, scene, scene->lay); /* XXX this is the best way we can get anything moving */ -#endif + BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer); } /* ........ */ @@ -404,7 +342,7 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets) * - recalc: whether we need to */ /* TODO: include reports pointer? */ -void animviz_calc_motionpaths(Scene *scene, ListBase *targets) + void animviz_calc_motionpaths(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, ListBase *targets) { MPathTarget *mpt; int sfra, efra; @@ -428,14 +366,10 @@ void animviz_calc_motionpaths(Scene *scene, ListBase *targets) } if (efra <= sfra) return; - /* optimize the depsgraph for faster updates */ - /* TODO: whether this is used should depend on some setting for the level of optimizations used */ - motionpaths_calc_optimise_depsgraph(scene, targets); - /* calculate path over requested range */ for (CFRA = sfra; CFRA <= efra; CFRA++) { /* update relevant data for new frame */ - motionpaths_calc_update_scene(scene); + motionpaths_calc_update_scene(bmain, scene, eval_ctx->view_layer, eval_ctx->depsgraph); /* perform baking for targets */ motionpaths_calc_bake_targets(scene, targets); @@ -443,7 +377,7 @@ void animviz_calc_motionpaths(Scene *scene, ListBase *targets) /* reset original environment */ CFRA = cfra; - motionpaths_calc_update_scene(scene); + motionpaths_calc_update_scene(bmain, scene, eval_ctx->view_layer, eval_ctx->depsgraph); /* clear recalc flags from targets */ for (mpt = targets->first; mpt; mpt = mpt->next) { diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 9037122c4f8..844a2a50bb3 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -60,7 +60,6 @@ #include "BKE_animsys.h" #include "BKE_action.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_nla.h" #include "BKE_global.h" @@ -70,6 +69,8 @@ #include "BKE_report.h" #include "BKE_texture.h" +#include "DEG_depsgraph.h" + #include "RNA_access.h" #include "nla_private.h" @@ -95,6 +96,7 @@ bool id_type_can_have_animdata(const short id_type) case ID_MA: case ID_TE: case ID_NT: case ID_LA: case ID_CA: case ID_WO: case ID_LS: + case ID_LP: case ID_SPK: case ID_SCE: case ID_MC: @@ -1563,12 +1565,6 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val /* caller must ensure this is animatable */ BLI_assert(RNA_property_animateable(ptr, prop) || ptr->id.data == NULL); - /* set value for animatable numerical values only - * HACK: some local F-Curves (e.g. those on NLA Strips) are evaluated - * without an ID provided, which causes the animateable test to fail! - */ - bool written = false; - switch (RNA_property_type(prop)) { case PROP_BOOLEAN: { @@ -1576,13 +1572,11 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val if (array_index != -1) { if (RNA_property_boolean_get_index(ptr, prop, array_index) != value_coerce) { RNA_property_boolean_set_index(ptr, prop, array_index, value_coerce); - written = true; } } else { if (RNA_property_boolean_get(ptr, prop) != value_coerce) { RNA_property_boolean_set(ptr, prop, value_coerce); - written = true; } } break; @@ -1594,13 +1588,11 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val if (array_index != -1) { if (RNA_property_int_get_index(ptr, prop, array_index) != value_coerce) { RNA_property_int_set_index(ptr, prop, array_index, value_coerce); - written = true; } } else { if (RNA_property_int_get(ptr, prop) != value_coerce) { RNA_property_int_set(ptr, prop, value_coerce); - written = true; } } break; @@ -1612,13 +1604,11 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val if (array_index != -1) { if (RNA_property_float_get_index(ptr, prop, array_index) != value_coerce) { RNA_property_float_set_index(ptr, prop, array_index, value_coerce); - written = true; } } else { if (RNA_property_float_get(ptr, prop) != value_coerce) { RNA_property_float_set(ptr, prop, value_coerce); - written = true; } } break; @@ -1628,7 +1618,6 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val const int value_coerce = (int)value; if (RNA_property_enum_get(ptr, prop) != value_coerce) { RNA_property_enum_set(ptr, prop, value_coerce); - written = true; } break; } @@ -1657,23 +1646,6 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val } #endif - /* as long as we don't do property update, we still tag datablock - * as having been updated. this flag does not cause any updates to - * be run, it's for e.g. render engines to synchronize data */ - if (written && ptr->id.data) { - ID *id = ptr->id.data; - - /* for cases like duplifarmes it's only a temporary so don't - * notify anyone of updates */ - if (!(id->recalc & ID_RECALC_SKIP_ANIM_TAG)) { - /* NOTE: This is a bit annoying to use atomic API here, but this - * code is at it's EOL and removed already in 2.8 branch. - */ - atomic_fetch_and_or_int32(&id->recalc, ID_RECALC); - DAG_id_type_tag(G.main, GS(id->name)); - } - } - /* successful */ return true; } @@ -2617,17 +2589,6 @@ static void animsys_evaluate_nla(ListBase *echannels, PointerRNA *ptr, AnimData /* 3. free temporary evaluation data that's not used elsewhere */ BLI_freelistN(&estrips); - - /* Tag ID as updated so render engines will recognize changes in data - * which is animated but doesn't have actions. - */ - if (ptr->id.data != NULL) { - ID *id = ptr->id.data; - if (!(id->recalc & ID_RECALC_SKIP_ANIM_TAG)) { - id->recalc |= ID_RECALC; - DAG_id_type_tag(G.main, GS(id->name)); - } - } } /* NLA Evaluation function (mostly for use through do_animdata) @@ -2920,7 +2881,7 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime) #define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf -void BKE_animsys_eval_animdata(EvaluationContext *eval_ctx, ID *id) +void BKE_animsys_eval_animdata(const EvaluationContext *eval_ctx, ID *id) { AnimData *adt = BKE_animdata_from_id(id); Scene *scene = NULL; /* XXX: this is only needed for flushing RNA updates, @@ -2930,7 +2891,7 @@ void BKE_animsys_eval_animdata(EvaluationContext *eval_ctx, ID *id) BKE_animsys_evaluate_animdata(scene, id, adt, eval_ctx->ctime, ADT_RECALC_ANIM); } -void BKE_animsys_eval_driver(EvaluationContext *eval_ctx, +void BKE_animsys_eval_driver(const EvaluationContext *eval_ctx, ID *id, FCurve *fcu) { diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 2edbd088334..953fef067b4 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -60,7 +60,6 @@ #include "BKE_anim.h" #include "BKE_constraint.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_DerivedMesh.h" #include "BKE_deform.h" #include "BKE_displist.h" @@ -1464,13 +1463,13 @@ void BKE_armature_loc_pose_to_bone(bPoseChannel *pchan, const float inloc[3], fl copy_v3_v3(outloc, nLocMat[3]); } -void BKE_armature_mat_pose_to_bone_ex(Object *ob, bPoseChannel *pchan, float inmat[4][4], float outmat[4][4]) +void BKE_armature_mat_pose_to_bone_ex(const struct EvaluationContext *eval_ctx, Object *ob, bPoseChannel *pchan, float inmat[4][4], float outmat[4][4]) { bPoseChannel work_pchan = *pchan; /* recalculate pose matrix with only parent transformations, * bone loc/sca/rot is ignored, scene and frame are not used. */ - BKE_pose_where_is_bone(NULL, ob, &work_pchan, 0.0f, false); + BKE_pose_where_is_bone(eval_ctx, NULL, ob, &work_pchan, 0.0f, false); /* find the matrix, need to remove the bone transforms first so this is * calculated as a matrix to set rather then a difference ontop of whats @@ -1953,7 +1952,7 @@ void BKE_pose_clear_pointers(bPose *pose) /* only after leave editmode, duplicating, validating older files, library syncing */ /* NOTE: pose->flag is set for it */ -void BKE_pose_rebuild_ex(Object *ob, bArmature *arm, const bool sort_bones) +void BKE_pose_rebuild(Object *ob, bArmature *arm) { Bone *bone; bPose *pose; @@ -1997,27 +1996,12 @@ void BKE_pose_rebuild_ex(Object *ob, bArmature *arm, const bool sort_bones) BKE_pose_update_constraint_flags(ob->pose); /* for IK detection for example */ -#ifdef WITH_LEGACY_DEPSGRAPH - /* the sorting */ - /* Sorting for new dependnecy graph is done on the scene graph level. */ - if (counter > 1 && sort_bones) { - DAG_pose_sort(ob); - } -#else - UNUSED_VARS(sort_bones); -#endif - ob->pose->flag &= ~POSE_RECALC; ob->pose->flag |= POSE_WAS_REBUILT; BKE_pose_channels_hash_make(ob->pose); } -void BKE_pose_rebuild(Object *ob, bArmature *arm) -{ - BKE_pose_rebuild_ex(ob, arm, true); -} - /* ********************** THE POSE SOLVER ******************* */ /* loc/rot/size to given mat4 */ @@ -2128,7 +2112,7 @@ static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseCha if (STREQ(pchan->name, amod->channel)) { float mat4[4][4], mat3[3][3]; - curve_deform_vector(scene, amod->ob, armob, bone->arm_mat[3], pchan->pose_mat[3], mat3, amod->no_rot_axis); + curve_deform_vector(amod->ob, armob, bone->arm_mat[3], pchan->pose_mat[3], mat3, amod->no_rot_axis); copy_m4_m4(mat4, pchan->pose_mat); mul_m4_m3m4(pchan->pose_mat, mat3, mat4); @@ -2212,7 +2196,9 @@ void BKE_pose_where_is_bone_tail(bPoseChannel *pchan) /* pchan is validated, as having bone and parent pointer * 'do_extra': when zero skips loc/size/rot, constraints and strip modifiers. */ -void BKE_pose_where_is_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float ctime, bool do_extra) +void BKE_pose_where_is_bone( + const struct EvaluationContext *eval_ctx, Scene *scene, + Object *ob, bPoseChannel *pchan, float ctime, bool do_extra) { /* This gives a chan_mat with actions (ipos) results. */ if (do_extra) @@ -2251,7 +2237,7 @@ void BKE_pose_where_is_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float cob = BKE_constraints_make_evalob(scene, ob, pchan, CONSTRAINT_OBTYPE_BONE); /* Solve PoseChannel's Constraints */ - BKE_constraints_solve(&pchan->constraints, cob, ctime); /* ctime doesnt alter objects */ + BKE_constraints_solve(eval_ctx, &pchan->constraints, cob, ctime); /* ctime doesnt alter objects */ /* cleanup after Constraint Solving * - applies matrix back to pchan, and frees temporary struct used @@ -2273,7 +2259,7 @@ void BKE_pose_where_is_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float /* This only reads anim data from channels, and writes to channels */ /* This is the only function adding poses */ -void BKE_pose_where_is(Scene *scene, Object *ob) +void BKE_pose_where_is(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob) { bArmature *arm; Bone *bone; @@ -2312,7 +2298,7 @@ void BKE_pose_where_is(Scene *scene, Object *ob) } /* 2a. construct the IK tree (standard IK) */ - BIK_initialize_tree(scene, ob, ctime); + BIK_initialize_tree(eval_ctx, scene, ob, ctime); /* 2b. construct the Spline IK trees * - this is not integrated as an IK plugin, since it should be able @@ -2324,15 +2310,15 @@ void BKE_pose_where_is(Scene *scene, Object *ob) for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { /* 4a. if we find an IK root, we handle it separated */ if (pchan->flag & POSE_IKTREE) { - BIK_execute_tree(scene, ob, pchan, ctime); + BIK_execute_tree(eval_ctx, scene, ob, pchan, ctime); } /* 4b. if we find a Spline IK root, we handle it separated too */ else if (pchan->flag & POSE_IKSPLINE) { - BKE_splineik_execute_tree(scene, ob, pchan, ctime); + BKE_splineik_execute_tree(eval_ctx, scene, ob, pchan, ctime); } /* 5. otherwise just call the normal solver */ else if (!(pchan->flag & POSE_DONE)) { - BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1); + BKE_pose_where_is_bone(eval_ctx, scene, ob, pchan, ctime, 1); } } /* 6. release the IK tree */ diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c index cc1bd9716b1..de0dfe2530d 100644 --- a/source/blender/blenkernel/intern/armature_update.c +++ b/source/blender/blenkernel/intern/armature_update.c @@ -41,7 +41,6 @@ #include "BKE_anim.h" #include "BKE_armature.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_displist.h" #include "BKE_fcurve.h" #include "BKE_scene.h" @@ -51,13 +50,7 @@ #include "BKE_global.h" #include "BKE_main.h" -#include "DEG_depsgraph.h" - -#ifdef WITH_LEGACY_DEPSGRAPH -# define DEBUG_PRINT if (!DEG_depsgraph_use_legacy() && G.debug & G_DEBUG_DEPSGRAPH) printf -#else -# define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf -#endif +#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf /* ********************** SPLINE IK SOLVER ******************* */ @@ -120,9 +113,11 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos * currently for paths to work it needs to go through the bevlist/displist system (ton) */ + /* TODO: Make sure this doesn't crash. */ +#if 0 /* only happens on reload file, but violates depsgraph still... fix! */ if (ELEM(NULL, ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) { - BKE_displist_make_curveTypes(scene, ikData->tar, 0); + BKE_displist_make_curveTypes(eval_ctx, scene, ikData->tar, 0); /* path building may fail in EditMode after removing verts [#33268]*/ if (ELEM(NULL, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) { @@ -130,6 +125,9 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos return; } } +#else + (void) scene; +#endif } /* find the root bone and the chain of bones from the root to the tip @@ -268,15 +266,16 @@ static void splineik_init_tree(Scene *scene, Object *ob, float UNUSED(ctime)) /* ----------- */ /* Evaluate spline IK for a given bone */ -static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *ob, bPoseChannel *pchan, - int index, float ctime) +static void splineik_evaluate_bone( + const struct EvaluationContext *eval_ctx, tSplineIK_Tree *tree, Scene *scene, Object *ob, bPoseChannel *pchan, + int index, float ctime) { bSplineIKConstraint *ikData = tree->ikData; float poseHead[3], poseTail[3], poseMat[4][4]; float splineVec[3], scaleFac, radius = 1.0f; /* firstly, calculate the bone matrix the standard way, since this is needed for roll control */ - BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1); + BKE_pose_where_is_bone(eval_ctx, scene, ob, pchan, ctime, 1); copy_v3_v3(poseHead, pchan->pose_head); copy_v3_v3(poseTail, pchan->pose_tail); @@ -518,7 +517,7 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o } /* Evaluate the chain starting from the nominated bone */ -static void splineik_execute_tree(Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime) +static void splineik_execute_tree(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime) { tSplineIK_Tree *tree; @@ -532,7 +531,7 @@ static void splineik_execute_tree(Scene *scene, Object *ob, bPoseChannel *pchan_ */ for (i = tree->chainlen - 1; i >= 0; i--) { bPoseChannel *pchan = tree->chain[i]; - splineik_evaluate_bone(tree, scene, ob, pchan, i, ctime); + splineik_evaluate_bone(eval_ctx, tree, scene, ob, pchan, i, ctime); } /* free the tree info specific to SplineIK trees now */ @@ -551,14 +550,16 @@ void BKE_pose_splineik_init_tree(Scene *scene, Object *ob, float ctime) splineik_init_tree(scene, ob, ctime); } -void BKE_splineik_execute_tree(Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime) +void BKE_splineik_execute_tree( + const struct EvaluationContext *eval_ctx, Scene *scene, + Object *ob, bPoseChannel *pchan_root, float ctime) { - splineik_execute_tree(scene, ob, pchan_root, ctime); + splineik_execute_tree(eval_ctx, scene, ob, pchan_root, ctime); } /* *************** Depsgraph evaluation callbacks ************ */ -void BKE_pose_eval_init(EvaluationContext *UNUSED(eval_ctx), +void BKE_pose_eval_init(const struct EvaluationContext *UNUSED(eval_ctx), Scene *UNUSED(scene), Object *ob, bPose *pose) @@ -582,7 +583,7 @@ void BKE_pose_eval_init(EvaluationContext *UNUSED(eval_ctx), } } -void BKE_pose_eval_init_ik(EvaluationContext *UNUSED(eval_ctx), +void BKE_pose_eval_init_ik(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, bPose *UNUSED(pose)) @@ -595,7 +596,7 @@ void BKE_pose_eval_init_ik(EvaluationContext *UNUSED(eval_ctx), return; } /* 2a. construct the IK tree (standard IK) */ - BIK_initialize_tree(scene, ob, ctime); + BIK_initialize_tree(eval_ctx, scene, ob, ctime); /* 2b. construct the Spline IK trees * - this is not integrated as an IK plugin, since it should be able * to function in conjunction with standard IK @@ -603,7 +604,7 @@ void BKE_pose_eval_init_ik(EvaluationContext *UNUSED(eval_ctx), BKE_pose_splineik_init_tree(scene, ob, ctime); } -void BKE_pose_eval_bone(EvaluationContext *UNUSED(eval_ctx), +void BKE_pose_eval_bone(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, bPoseChannel *pchan) @@ -631,14 +632,14 @@ void BKE_pose_eval_bone(EvaluationContext *UNUSED(eval_ctx), if ((pchan->flag & POSE_DONE) == 0) { /* TODO(sergey): Use time source node for time. */ float ctime = BKE_scene_frame_get(scene); /* not accurate... */ - BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1); + BKE_pose_where_is_bone(eval_ctx, scene, ob, pchan, ctime, 1); } } } } } -void BKE_pose_constraints_evaluate(EvaluationContext *UNUSED(eval_ctx), +void BKE_pose_constraints_evaluate(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, bPoseChannel *pchan) @@ -654,12 +655,12 @@ void BKE_pose_constraints_evaluate(EvaluationContext *UNUSED(eval_ctx), else { if ((pchan->flag & POSE_DONE) == 0) { float ctime = BKE_scene_frame_get(scene); /* not accurate... */ - BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1); + BKE_pose_where_is_bone(eval_ctx, scene, ob, pchan, ctime, 1); } } } -void BKE_pose_bone_done(EvaluationContext *UNUSED(eval_ctx), +void BKE_pose_bone_done(const struct EvaluationContext *UNUSED(eval_ctx), bPoseChannel *pchan) { float imat[4][4]; @@ -670,7 +671,7 @@ void BKE_pose_bone_done(EvaluationContext *UNUSED(eval_ctx), } } -void BKE_pose_iktree_evaluate(EvaluationContext *UNUSED(eval_ctx), +void BKE_pose_iktree_evaluate(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, bPoseChannel *rootchan) @@ -682,10 +683,10 @@ void BKE_pose_iktree_evaluate(EvaluationContext *UNUSED(eval_ctx), if (arm->flag & ARM_RESTPOS) { return; } - BIK_execute_tree(scene, ob, rootchan, ctime); + BIK_execute_tree(eval_ctx, scene, ob, rootchan, ctime); } -void BKE_pose_splineik_evaluate(EvaluationContext *UNUSED(eval_ctx), +void BKE_pose_splineik_evaluate(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, bPoseChannel *rootchan) @@ -697,10 +698,10 @@ void BKE_pose_splineik_evaluate(EvaluationContext *UNUSED(eval_ctx), if (arm->flag & ARM_RESTPOS) { return; } - BKE_splineik_execute_tree(scene, ob, rootchan, ctime); + BKE_splineik_execute_tree(eval_ctx, scene, ob, rootchan, ctime); } -void BKE_pose_eval_flush(EvaluationContext *UNUSED(eval_ctx), +void BKE_pose_eval_flush(const struct EvaluationContext *UNUSED(eval_ctx), Scene *scene, Object *ob, bPose *UNUSED(pose)) @@ -711,11 +712,9 @@ void BKE_pose_eval_flush(EvaluationContext *UNUSED(eval_ctx), /* 6. release the IK tree */ BIK_release_tree(scene, ob, ctime); - - ob->recalc &= ~OB_RECALC_ALL; } -void BKE_pose_eval_proxy_copy(EvaluationContext *UNUSED(eval_ctx), Object *ob) +void BKE_pose_eval_proxy_copy(const struct EvaluationContext *UNUSED(eval_ctx), Object *ob) { BLI_assert(ID_IS_LINKED(ob) && ob->proxy_from != NULL); DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); @@ -723,8 +722,4 @@ void BKE_pose_eval_proxy_copy(EvaluationContext *UNUSED(eval_ctx), Object *ob) printf("Proxy copy error, lib Object: %s proxy Object: %s\n", ob->id.name + 2, ob->proxy_from->id.name + 2); } - /* Rest of operations are NO-OP in depsgraph, so can clear - * flag now. - */ - ob->recalc &= ~OB_RECALC_ALL; } diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c index a27f075a346..e9a6d0fe5a5 100644 --- a/source/blender/blenkernel/intern/blender.c +++ b/source/blender/blenkernel/intern/blender.c @@ -52,10 +52,10 @@ #include "BKE_brush.h" #include "BKE_cachefile.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_idprop.h" #include "BKE_image.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_node.h" #include "BKE_report.h" @@ -63,6 +63,8 @@ #include "BKE_screen.h" #include "BKE_sequencer.h" +#include "DEG_depsgraph.h" + #include "RE_pipeline.h" #include "RE_render_ext.h" @@ -88,7 +90,7 @@ void BKE_blender_free(void) IMB_exit(); BKE_cachefiles_exit(); BKE_images_exit(); - DAG_exit(); + DEG_free_node_types(); BKE_brush_system_exit(); RE_texture_rng_exit(); @@ -97,6 +99,8 @@ void BKE_blender_free(void) BKE_sequencer_cache_destruct(); IMB_moviecache_destruct(); + + BKE_layer_exit(); free_nodesystem(); } @@ -277,11 +281,13 @@ void BKE_blender_userdef_app_template_data_swap(UserDef *userdef_a, UserDef *use DATA_SWAP(font_path_ui_mono); DATA_SWAP(keyconfigstr); + DATA_SWAP(manipulator_flag); DATA_SWAP(app_flag); /* We could add others. */ FLAG_SWAP(uiflag, int, USER_QUIT_PROMPT); +#undef SWAP_TYPELESS #undef DATA_SWAP #undef LIST_SWAP #undef FLAG_SWAP diff --git a/source/blender/blenkernel/intern/blender_copybuffer.c b/source/blender/blenkernel/intern/blender_copybuffer.c index e57524af546..b0c571bf159 100644 --- a/source/blender/blenkernel/intern/blender_copybuffer.c +++ b/source/blender/blenkernel/intern/blender_copybuffer.c @@ -44,12 +44,15 @@ #include "BKE_blender_copybuffer.h" /* own include */ #include "BKE_blendfile.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_scene.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "BLO_readfile.h" #include "BLO_writefile.h" @@ -117,7 +120,7 @@ bool BKE_copybuffer_paste(bContext *C, const char *libname, const short flag, Re { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); - View3D *v3d = CTX_wm_view3d(C); + ViewLayer *view_layer = CTX_data_view_layer(C); Main *mainl = NULL; Library *lib; BlendHandle *bh; @@ -129,7 +132,7 @@ bool BKE_copybuffer_paste(bContext *C, const char *libname, const short flag, Re return false; } - BKE_scene_base_deselect_all(scene); + BKE_view_layer_base_deselect_all(view_layer); /* tag everything, all untagged data can be made local * its also generally useful to know what is new @@ -142,7 +145,7 @@ bool BKE_copybuffer_paste(bContext *C, const char *libname, const short flag, Re BLO_library_link_copypaste(mainl, bh); - BLO_library_link_end(mainl, &bh, flag, scene, v3d); + BLO_library_link_end(mainl, &bh, flag, scene, view_layer); /* mark all library linked objects to be updated */ BKE_main_lib_objects_recalc_all(bmain); @@ -157,7 +160,11 @@ bool BKE_copybuffer_paste(bContext *C, const char *libname, const short flag, Re BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false); /* recreate dependency graph to include new objects */ - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); + + /* Tag update the scene to flush base collection settings, since the new object is added to a + * new (active) collection, not its original collection, thus need recalculation. */ + DEG_id_tag_update(&scene->id, 0); BLO_blendhandle_close(bh); /* remove library... */ diff --git a/source/blender/blenkernel/intern/blender_undo.c b/source/blender/blenkernel/intern/blender_undo.c index e3a5edb2049..b8f46756445 100644 --- a/source/blender/blenkernel/intern/blender_undo.c +++ b/source/blender/blenkernel/intern/blender_undo.c @@ -56,7 +56,6 @@ #include "BKE_appdir.h" #include "BKE_brush.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_image.h" #include "BKE_main.h" @@ -66,6 +65,8 @@ #include "BLO_readfile.h" #include "BLO_writefile.h" +#include "DEG_depsgraph.h" + /* -------------------------------------------------------------------- */ /** \name Global Undo @@ -118,7 +119,7 @@ static int read_undosave(bContext *C, UndoElem *uel) if (success) { /* important not to update time here, else non keyed tranforms are lost */ - DAG_on_visible_update(G.main, false); + DEG_on_visible_update(G.main, false); } return success; diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c index cc992a4a520..8d61b6723c6 100644 --- a/source/blender/blenkernel/intern/blendfile.c +++ b/source/blender/blenkernel/intern/blendfile.c @@ -32,6 +32,7 @@ #include "DNA_scene_types.h" #include "DNA_screen_types.h" +#include "DNA_workspace_types.h" #include "BLI_listbase.h" #include "BLI_string.h" @@ -48,11 +49,13 @@ #include "BKE_context.h" #include "BKE_global.h" #include "BKE_ipo.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_screen.h" +#include "BKE_workspace.h" #include "BLO_readfile.h" #include "BLO_writefile.h" @@ -93,7 +96,7 @@ static bool wm_scene_is_visible(wmWindowManager *wm, Scene *scene) { wmWindow *win; for (win = wm->windows.first; win; win = win->next) { - if (win->screen->scene == scene) { + if (win->scene == scene) { return true; } } @@ -163,17 +166,22 @@ static void setup_app_data( * (otherwise we'd be undoing on an off-screen scene which isn't acceptable). * see: T43424 */ + wmWindow *win; bScreen *curscreen = NULL; + ViewLayer *cur_view_layer; bool track_undo_scene; /* comes from readfile.c */ SWAP(ListBase, G.main->wm, bfd->main->wm); + SWAP(ListBase, G.main->workspaces, bfd->main->workspaces); SWAP(ListBase, G.main->screen, bfd->main->screen); - /* we re-use current screen */ + /* we re-use current window and screen */ + win = CTX_wm_window(C); curscreen = CTX_wm_screen(C); - /* but use new Scene pointer */ + /* but use Scene pointer from new file */ curscene = bfd->curscene; + cur_view_layer = bfd->cur_view_layer; track_undo_scene = (mode == LOAD_UNDO && curscreen && curscene && bfd->main->wm.first); @@ -184,34 +192,41 @@ static void setup_app_data( if (curscene == NULL) { curscene = BKE_scene_add(bfd->main, "Empty"); } + if (cur_view_layer == NULL) { + /* fallback to scene layer */ + cur_view_layer = BKE_view_layer_from_scene_get(curscene); + } if (track_undo_scene) { /* keep the old (free'd) scene, let 'blo_lib_link_screen_restore' * replace it with 'curscene' if its needed */ } - else { - /* and we enforce curscene to be in current screen */ - if (curscreen) { - /* can run in bgmode */ - curscreen->scene = curscene; - } + /* and we enforce curscene to be in current screen */ + else if (win) { /* can run in bgmode */ + win->scene = curscene; } /* BKE_blender_globals_clear will free G.main, here we can still restore pointers */ - blo_lib_link_screen_restore(bfd->main, curscreen, curscene); - /* curscreen might not be set when loading without ui (see T44217) so only re-assign if available */ - if (curscreen) { - curscene = curscreen->scene; + blo_lib_link_restore(bfd->main, CTX_wm_manager(C), curscene, cur_view_layer); + if (win) { + curscene = win->scene; } if (track_undo_scene) { wmWindowManager *wm = bfd->main->wm.first; if (wm_scene_is_visible(wm, bfd->curscene) == false) { curscene = bfd->curscene; - curscreen->scene = curscene; - BKE_screen_view3d_scene_sync(curscreen); + win->scene = curscene; + BKE_screen_view3d_scene_sync(curscreen, curscene); } } + + /* We need to tag this here because events may be handled immediately after. + * only the current screen is important because we wont have to handle + * events from multiple screens at once.*/ + { + BKE_screen_manipulator_tag_refresh(curscreen); + } } /* free G.main Main database */ @@ -226,6 +241,7 @@ static void setup_app_data( CTX_data_main_set(C, G.main); if (bfd->user) { + /* only here free userdef themes... */ BKE_blender_userdef_data_set_and_free(bfd->user); bfd->user = NULL; @@ -261,12 +277,14 @@ static void setup_app_data( /* this can happen when active scene was lib-linked, and doesn't exist anymore */ if (CTX_data_scene(C) == NULL) { + wmWindow *win = CTX_wm_window(C); + /* in case we don't even have a local scene, add one */ if (!G.main->scene.first) BKE_scene_add(G.main, "Empty"); CTX_data_scene_set(C, G.main->scene.first); - CTX_wm_screen(C)->scene = CTX_data_scene(C); + win->scene = CTX_data_scene(C); curscene = CTX_data_scene(C); } @@ -315,20 +333,27 @@ static void setup_app_data( wmWindowManager *wm = G.main->wm.first; if (wm) { - wmWindow *win; - - for (win = wm->windows.first; win; win = win->next) { - if (win->screen && win->screen->scene) /* zealous check... */ - if (win->screen->scene != curscene) - BKE_scene_set_background(G.main, win->screen->scene); + for (wmWindow *win = wm->windows.first; win; win = win->next) { + if (win->scene && win->scene != curscene) { + BKE_scene_set_background(G.main, win->scene); + } } } } + + /* Setting scene might require having a dependency graph, with copy on write + * we need to make sure we ensure scene has correct color management before + * constructing dependency graph. + */ + if (mode != LOAD_UNDO) { + IMB_colormanagement_check_file_config(G.main); + } + BKE_scene_set_background(G.main, curscene); if (mode != LOAD_UNDO) { + /* TODO(sergey): Can this be also move above? */ RE_FreeAllPersistentData(); - IMB_colormanagement_check_file_config(G.main); } MEM_freeN(bfd); @@ -534,6 +559,48 @@ bool BKE_blendfile_userdef_write_app_template(const char *filepath, ReportList * return ok; } +WorkspaceConfigFileData *BKE_blendfile_workspace_config_read(const char *filepath, ReportList *reports) +{ + BlendFileData *bfd; + WorkspaceConfigFileData *workspace_config = NULL; + + bfd = BLO_read_from_file(filepath, reports, BLO_READ_SKIP_USERDEF); + if (bfd) { + workspace_config = MEM_mallocN(sizeof(*workspace_config), __func__); + workspace_config->main = bfd->main; + workspace_config->workspaces = bfd->main->workspaces; + + MEM_freeN(bfd); + } + + return workspace_config; +} + +bool BKE_blendfile_workspace_config_write(Main *bmain, const char *filepath, ReportList *reports) +{ + int fileflags = G.fileflags & ~(G_FILE_NO_UI | G_FILE_AUTOPLAY | G_FILE_HISTORY); + bool retval = false; + + BKE_blendfile_write_partial_begin(bmain); + + for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) { + BKE_blendfile_write_partial_tag_ID(&workspace->id, true); + } + + if (BKE_blendfile_write_partial(bmain, filepath, fileflags, reports)) { + retval = true; + } + + BKE_blendfile_write_partial_end(bmain); + + return retval; +} + +void BKE_blendfile_workspace_config_data_free(WorkspaceConfigFileData *workspace_config) +{ + BKE_main_free(workspace_config->main); + MEM_freeN(workspace_config); +} /** \} */ diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c index a2a242e7519..f440ce711ff 100644 --- a/source/blender/blenkernel/intern/boids.c +++ b/source/blender/blenkernel/intern/boids.c @@ -132,6 +132,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val, if (eff == NULL && gabr->ob) { memset(&temp_eff, 0, sizeof(EffectorCache)); temp_eff.ob = gabr->ob; + temp_eff.eval_ctx = bbd->sim->eval_ctx; temp_eff.scene = bbd->sim->scene; eff = &temp_eff; get_effector_data(eff, &efd, &epoint, 0); diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c index e821a14da2e..f8215668034 100644 --- a/source/blender/blenkernel/intern/cachefile.c +++ b/source/blender/blenkernel/intern/cachefile.c @@ -176,7 +176,7 @@ void BKE_cachefile_update_frame(Main *bmain, Scene *scene, const float ctime, co const float time = BKE_cachefile_time_offset(cache_file, ctime, fps); if (BKE_cachefile_filepath_get(bmain, cache_file, time, filename)) { - BKE_cachefile_clean(scene, cache_file); + BKE_cachefile_clean(bmain, cache_file); #ifdef WITH_ALEMBIC ABC_free_handle(cache_file->handle); cache_file->handle = ABC_create_handle(filename, NULL); @@ -217,11 +217,9 @@ float BKE_cachefile_time_offset(CacheFile *cache_file, const float time, const f } /* TODO(kevin): replace this with some depsgraph mechanism, or something similar. */ -void BKE_cachefile_clean(Scene *scene, CacheFile *cache_file) +void BKE_cachefile_clean(struct Main *bmain, CacheFile *cache_file) { - for (Base *base = scene->base.first; base; base = base->next) { - Object *ob = base->object; - + for (Object *ob = bmain->object.first; ob; ob = ob->id.next) { ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache); if (md) { diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c index 719125b3317..869e312614e 100644 --- a/source/blender/blenkernel/intern/camera.c +++ b/source/blender/blenkernel/intern/camera.c @@ -40,6 +40,7 @@ #include "DNA_ID.h" #include "BLI_math.h" +#include "BLI_listbase.h" #include "BLI_rect.h" #include "BLI_string.h" #include "BLI_utildefines.h" @@ -48,6 +49,7 @@ #include "BKE_camera.h" #include "BKE_object.h" #include "BKE_global.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_library_remap.h" @@ -55,6 +57,10 @@ #include "BKE_scene.h" #include "BKE_screen.h" +#include "DEG_depsgraph_query.h" + +#include "MEM_guardedalloc.h" + #include "GPU_compositing.h" /****************************** Camera Datablock *****************************/ @@ -101,9 +107,19 @@ void *BKE_camera_add(Main *bmain, const char *name) * * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). */ -void BKE_camera_copy_data(Main *UNUSED(bmain), Camera *UNUSED(cam_dst), const Camera *UNUSED(cam_src), const int UNUSED(flag)) +void BKE_camera_copy_data(Main *UNUSED(bmain), Camera *cam_dst, const Camera *cam_src, const int flag) { - /* Nothing to do! */ + BLI_duplicatelist(&cam_dst->bg_images, &cam_src->bg_images); + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + for (CameraBGImage *bgpic = cam_dst->bg_images.first; bgpic; bgpic = bgpic->next) { + if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) { + id_us_plus((ID *)bgpic->ima); + } + else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) { + id_us_plus((ID *)bgpic->clip); + } + } + } } Camera *BKE_camera_copy(Main *bmain, const Camera *cam) @@ -121,6 +137,16 @@ void BKE_camera_make_local(Main *bmain, Camera *cam, const bool lib_local) /** Free (or release) any data used by this camera (does not free the camera itself). */ void BKE_camera_free(Camera *ca) { + for (CameraBGImage *bgpic = ca->bg_images.first; bgpic; bgpic = bgpic->next) { + if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) { + id_us_min((ID *)bgpic->ima); + } + else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) { + id_us_min((ID *)bgpic->clip); + } + } + BLI_freelistN(&ca->bg_images); + BKE_animdata_free((ID *)ca, false); } @@ -238,7 +264,7 @@ void BKE_camera_params_from_object(CameraParams *params, const Object *ob) } } -void BKE_camera_params_from_view3d(CameraParams *params, const View3D *v3d, const RegionView3D *rv3d) +void BKE_camera_params_from_view3d(CameraParams *params, const Depsgraph *depsgraph, const View3D *v3d, const RegionView3D *rv3d) { /* common */ params->lens = v3d->lens; @@ -247,7 +273,8 @@ void BKE_camera_params_from_view3d(CameraParams *params, const View3D *v3d, cons if (rv3d->persp == RV3D_CAMOB) { /* camera view */ - BKE_camera_params_from_object(params, v3d->camera); + Object *camera_object = DEG_get_evaluated_object(depsgraph, v3d->camera); + BKE_camera_params_from_object(params, camera_object); params->zoom = BKE_screen_view3d_zoom_to_fac(rv3d->camzoom); @@ -642,7 +669,7 @@ static bool camera_frame_fit_calc_from_data( /* don't move the camera, just yield the fit location */ /* r_scale only valid/useful for ortho cameras */ bool BKE_camera_view_frame_fit_to_scene( - Scene *scene, struct View3D *v3d, Object *camera_ob, float r_co[3], float *r_scale) + Scene *scene, ViewLayer *view_layer, Object *camera_ob, float r_co[3], float *r_scale) { CameraParams params; CameraViewFrameData data_cb; @@ -653,7 +680,7 @@ bool BKE_camera_view_frame_fit_to_scene( camera_frame_fit_data_init(scene, camera_ob, ¶ms, &data_cb); /* run callback on all visible points */ - BKE_scene_foreach_display_point(scene, v3d, BA_SELECT, camera_to_frame_view_cb, &data_cb); + BKE_scene_foreach_display_point(scene, view_layer, camera_to_frame_view_cb, &data_cb); return camera_frame_fit_calc_from_data(¶ms, &data_cb, r_co, r_scale); } @@ -862,9 +889,9 @@ static Object *camera_multiview_advanced(Scene *scene, Object *camera, const cha } if (name[0] != '\0') { - Base *base = BKE_scene_base_find_by_name(scene, name); - if (base) { - return base->object; + Object *ob = BKE_scene_object_find_by_name(scene, name); + if (ob != NULL) { + return ob; } } @@ -961,3 +988,38 @@ void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_set r_fx_settings->dof->focus_distance = BKE_camera_object_dof_distance(camera); } } + +CameraBGImage *BKE_camera_background_image_new(Camera *cam) +{ + CameraBGImage *bgpic = MEM_callocN(sizeof(CameraBGImage), "Background Image"); + + bgpic->scale = 1.0f; + bgpic->alpha = 0.5f; + bgpic->iuser.fie_ima = 2; + bgpic->iuser.ok = 1; + bgpic->flag |= CAM_BGIMG_FLAG_EXPANDED; + + BLI_addtail(&cam->bg_images, bgpic); + + return bgpic; +} + +void BKE_camera_background_image_remove(Camera *cam, CameraBGImage *bgpic) +{ + BLI_remlink(&cam->bg_images, bgpic); + + MEM_freeN(bgpic); +} + +void BKE_camera_background_image_clear(Camera *cam) +{ + CameraBGImage *bgpic = cam->bg_images.first; + + while (bgpic) { + CameraBGImage *next_bgpic = bgpic->next; + + BKE_camera_background_image_remove(cam, bgpic); + + bgpic = next_bgpic; + } +} diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index d3b106835ef..c4e9ace2d5d 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -60,9 +60,12 @@ #include "GPU_buffers.h" #include "GPU_draw.h" #include "GPU_glew.h" +#include "GPU_immediate.h" #include "GPU_shader.h" #include "GPU_basic_shader.h" +#include "DEG_depsgraph.h" + #include <string.h> #include <limits.h> #include <math.h> @@ -259,7 +262,8 @@ static bool can_pbvh_draw(Object *ob, DerivedMesh *dm) return cddm->mvert == me->mvert || ob->sculpt->kb; } -static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm) +static PBVH *cdDM_getPBVH( + Object *ob, DerivedMesh *dm, eObjectMode UNUSED(object_mode)) { CDDerivedMesh *cddm = (CDDerivedMesh *) dm; @@ -376,40 +380,10 @@ static void cdDM_drawVerts(DerivedMesh *dm) GPU_buffers_unbind(); } -static void cdDM_drawUVEdges(DerivedMesh *dm) +static void cdDM_drawEdges(DerivedMesh *dm, bool UNUSED(drawLooseEdges), bool UNUSED(drawAllEdges)) { CDDerivedMesh *cddm = (CDDerivedMesh *) dm; - const MPoly *mpoly = cddm->mpoly; - int totpoly = dm->getNumPolys(dm); - int prevstart = 0; - bool prevdraw = true; - int curpos = 0; - int i; - - GPU_uvedge_setup(dm); - for (i = 0; i < totpoly; i++, mpoly++) { - const bool draw = (mpoly->flag & ME_HIDE) == 0; - - if (prevdraw != draw) { - if (prevdraw && (curpos != prevstart)) { - glDrawArrays(GL_LINES, prevstart, curpos - prevstart); - } - prevstart = curpos; - } - curpos += 2 * mpoly->totloop; - prevdraw = draw; - } - if (prevdraw && (curpos != prevstart)) { - glDrawArrays(GL_LINES, prevstart, curpos - prevstart); - } - GPU_buffers_unbind(); -} - -static void cdDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdges) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *) dm; - GPUDrawObject *gdo; if (cddm->pbvh && cddm->pbvh_draw && BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH) { @@ -417,22 +391,37 @@ static void cdDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdg return; } - - GPU_edge_setup(dm); - gdo = dm->drawObject; - if (gdo->edges && gdo->points) { - if (drawAllEdges && drawLooseEdges) { - GPU_buffer_draw_elements(gdo->edges, GL_LINES, 0, gdo->totedge * 2); - } - else if (drawAllEdges) { - GPU_buffer_draw_elements(gdo->edges, GL_LINES, 0, gdo->loose_edge_offset * 2); - } - else { - GPU_buffer_draw_elements(gdo->edges, GL_LINES, 0, gdo->tot_edge_drawn * 2); - GPU_buffer_draw_elements(gdo->edges, GL_LINES, gdo->loose_edge_offset * 2, dm->drawObject->tot_loose_edge_drawn * 2); + + MVert *vert = cddm->mvert; + MEdge *edge = cddm->medge; + + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + + /* NOTE: This is active object color, which is not really perfect. + * But we can't query color set by glColor() :( + */ + float color[4] = {1.0f, 0.667f, 0.251f, 1.0f}; + + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); + immUniformColor4fv(color); + + const int chunk_size = 1024; + const int num_chunks = (dm->numEdgeData + chunk_size - 1) / chunk_size; + + for (int chunk = 0; chunk < num_chunks; ++chunk) { + const int num_current_edges = (chunk < num_chunks - 1) + ? chunk_size + : dm->numEdgeData - chunk_size * (num_chunks - 1); + immBeginAtMost(GWN_PRIM_LINES, num_current_edges * 2); + for (int i = 0; i < num_current_edges; i++, edge++) { + immVertex3fv(pos, vert[edge->v1].co); + immVertex3fv(pos, vert[edge->v2].co); } + immEnd(); } - GPU_buffers_unbind(); + + immUnbindProgram(); } static void cdDM_drawLooseEdges(DerivedMesh *dm) @@ -455,8 +444,9 @@ static void cdDM_drawLooseEdges(DerivedMesh *dm) static void cdDM_drawFacesSolid( DerivedMesh *dm, float (*partial_redraw_planes)[4], - bool UNUSED(fast), DMSetMaterial setMaterial) + bool fast, DMSetMaterial setMaterial) { + UNUSED_VARS(partial_redraw_planes, fast, setMaterial); CDDerivedMesh *cddm = (CDDerivedMesh *) dm; int a; @@ -469,177 +459,79 @@ static void cdDM_drawFacesSolid( return; } } - - GPU_vertex_setup(dm); - GPU_normal_setup(dm); - GPU_triangle_setup(dm); - for (a = 0; a < dm->drawObject->totmaterial; a++) { - if (!setMaterial || setMaterial(dm->drawObject->materials[a].mat_nr + 1, NULL)) { - GPU_buffer_draw_elements( - dm->drawObject->triangles, GL_TRIANGLES, - dm->drawObject->materials[a].start, dm->drawObject->materials[a].totelements); - } - } - GPU_buffers_unbind(); -} -static void cdDM_drawFacesTex_common( - DerivedMesh *dm, - DMSetDrawOptionsTex drawParams, - DMSetDrawOptionsMappedTex drawParamsMapped, - DMCompareDrawOptions compareDrawOptions, - void *userData, DMDrawFlag flag) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *) dm; + const MVert *mvert = cddm->mvert; + const MLoop *mloop = cddm->mloop; const MPoly *mpoly = cddm->mpoly; - MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY); - const MLoopCol *mloopcol = NULL; - int i; - int colType, start_element, tot_drawn; - const bool use_hide = (flag & DM_DRAW_SKIP_HIDDEN) != 0; - const bool use_tface = (flag & DM_DRAW_USE_ACTIVE_UV) != 0; - const bool use_colors = (flag & DM_DRAW_USE_COLORS) != 0; - int totpoly; - int next_actualFace; - int mat_index; - int tot_element; - - /* double lookup */ - const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); - - /* TODO: not entirely correct, but currently dynamic topology will - * destroy UVs anyway, so textured display wouldn't work anyway - * - * this will do more like solid view with lights set up for - * textured view, but object itself will be displayed gray - * (the same as it'll display without UV maps in textured view) - */ - if (cddm->pbvh) { - if (cddm->pbvh_draw && - BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH && - BKE_pbvh_has_faces(cddm->pbvh)) - { - GPU_set_tpage(NULL, false, false); - BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false, false); - return; - } - else { - cdDM_update_normals_from_pbvh(dm); - } - } + const int num_looptris = dm->getNumLoopTri(dm); + const MLoopTri *looptri = dm->getLoopTriArray(dm); + const float (*nors)[3] = dm->getPolyDataArray(dm, CD_NORMAL); + const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL); - if (use_colors) { - colType = CD_TEXTURE_MLOOPCOL; - mloopcol = dm->getLoopDataArray(dm, colType); - if (!mloopcol) { - colType = CD_PREVIEW_MLOOPCOL; - mloopcol = dm->getLoopDataArray(dm, colType); - } - if (!mloopcol) { - colType = CD_MLOOPCOL; - mloopcol = dm->getLoopDataArray(dm, colType); - } - } + Gwn_VertFormat *format = immVertexFormat(); + unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + unsigned int nor = GWN_vertformat_attr_add(format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); - GPU_vertex_setup(dm); - GPU_normal_setup(dm); - GPU_triangle_setup(dm); - if (flag & DM_DRAW_USE_TEXPAINT_UV) - GPU_texpaint_uv_setup(dm); - else - GPU_uv_setup(dm); - if (mloopcol) { - GPU_color_setup(dm, colType); - } + float color[4] = {0.8f, 0.8f, 0.8f, 1.0f}; + const float light_vec[3] = {0.0f, 0.0f, 1.0f}; - /* lastFlag = 0; */ /* UNUSED */ - for (mat_index = 0; mat_index < dm->drawObject->totmaterial; mat_index++) { - GPUBufferMaterial *bufmat = dm->drawObject->materials + mat_index; - next_actualFace = bufmat->polys[0]; - totpoly = bufmat->totpolys; + immBindBuiltinProgram(GPU_SHADER_SIMPLE_LIGHTING); + immUniformColor4fv(color); + immUniform3fv("light", light_vec); - tot_element = 0; - tot_drawn = 0; - start_element = 0; + const int chunk_size = 1024; + const int num_chunks = (num_looptris + chunk_size - 1) / chunk_size; - for (i = 0; i < totpoly; i++) { - int actualFace = bufmat->polys[i]; - DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL; - int flush = 0; - int tot_tri_verts; + for (int chunk = 0; chunk < num_chunks; ++chunk) { + const int num_current_looptris = (chunk < num_chunks - 1) + ? chunk_size + : num_looptris - chunk_size * (num_chunks - 1); - if (i != totpoly - 1) - next_actualFace = bufmat->polys[i + 1]; + immBeginAtMost(GWN_PRIM_TRIS, num_current_looptris * 3); - if (use_hide && (mpoly[actualFace].flag & ME_HIDE)) { - draw_option = DM_DRAW_OPTION_SKIP; - } - else if (drawParams) { - MTexPoly *tp = use_tface && mtexpoly ? &mtexpoly[actualFace] : NULL; - draw_option = drawParams(tp, (mloopcol != NULL), mpoly[actualFace].mat_nr); - } - else { - if (index_mp_to_orig) { - const int orig = 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, mpoly[actualFace].mat_nr); - } + for (a = 0; a < num_current_looptris; a++, looptri++) { + const MPoly *mp = &mpoly[looptri->poly]; + const bool smoothnormal = (lnors != NULL) || (mp->flag & ME_SMOOTH); + const unsigned int vtri[3] = {mloop[looptri->tri[0]].v, + mloop[looptri->tri[1]].v, + mloop[looptri->tri[2]].v}; + const unsigned int *ltri = looptri->tri; + float normals[3][3]; + if (!smoothnormal) { + if (nors != NULL) { + copy_v3_v3(normals[0], nors[looptri->poly]); } - else if (drawParamsMapped) { - draw_option = drawParamsMapped(userData, actualFace, mpoly[actualFace].mat_nr); + else { + normal_tri_v3(normals[0], + mvert[vtri[0]].co, + mvert[vtri[1]].co, + mvert[vtri[2]].co); } + copy_v3_v3(normals[1], normals[0]); + copy_v3_v3(normals[2], normals[0]); } - - /* flush buffer if current triangle isn't drawable or it's last triangle */ - flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == totpoly - 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; - } - - tot_tri_verts = ME_POLY_TRI_TOT(&mpoly[actualFace]) * 3; - tot_element += tot_tri_verts; - - if (flush) { - if (draw_option != DM_DRAW_OPTION_SKIP) - tot_drawn += tot_tri_verts; - - if (tot_drawn) { - if (mloopcol && draw_option != DM_DRAW_OPTION_NO_MCOL) - GPU_color_switch(1); - else - GPU_color_switch(0); - - GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, bufmat->start + start_element, tot_drawn); - tot_drawn = 0; - } - start_element = tot_element; + else if (lnors != NULL) { + copy_v3_v3(normals[0], lnors[ltri[0]]); + copy_v3_v3(normals[1], lnors[ltri[1]]); + copy_v3_v3(normals[2], lnors[ltri[2]]); } else { - tot_drawn += tot_tri_verts; + normal_short_to_float_v3(normals[0], mvert[vtri[0]].no); + normal_short_to_float_v3(normals[1], mvert[vtri[1]].no); + normal_short_to_float_v3(normals[2], mvert[vtri[2]].no); } + + immAttrib3fv(nor, normals[0]); + immVertex3fv(pos, mvert[vtri[0]].co); + immAttrib3fv(nor, normals[1]); + immVertex3fv(pos, mvert[vtri[1]].co); + immAttrib3fv(nor, normals[2]); + immVertex3fv(pos, mvert[vtri[2]].co); } + immEnd(); } - GPU_buffers_unbind(); - -} - -static void cdDM_drawFacesTex( - DerivedMesh *dm, - DMSetDrawOptionsTex setDrawOptions, - DMCompareDrawOptions compareDrawOptions, - void *userData, DMDrawFlag flag) -{ - cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData, flag); + immUnbindProgram(); } static void cdDM_drawMappedFaces( @@ -851,15 +743,6 @@ static void cdDM_drawMappedFaces( } -static void cdDM_drawMappedFacesTex( - DerivedMesh *dm, - DMSetDrawOptionsMappedTex setDrawOptions, - DMCompareDrawOptions compareDrawOptions, - void *userData, DMDrawFlag flag) -{ - cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag); -} - static void cddm_draw_attrib_vertex( DMVertexAttribs *attribs, const MVert *mvert, int a, int index, int loop, int vert, const float *lnor, const bool smoothnormal) @@ -1913,7 +1796,7 @@ void CDDM_recalc_tessellation_ex(DerivedMesh *dm, const bool do_face_nor_cpy) /* Tessellation recreated faceData, and the active layer indices need to get re-propagated * from loops and polys to faces */ - CustomData_bmesh_update_active_layers(&dm->faceData, &dm->polyData, &dm->loopData); + CustomData_bmesh_update_active_layers(&dm->faceData, &dm->loopData); } void CDDM_recalc_tessellation(DerivedMesh *dm) @@ -2007,16 +1890,13 @@ static CDDerivedMesh *cdDM_create(const char *desc) dm->drawVerts = cdDM_drawVerts; - dm->drawUVEdges = cdDM_drawUVEdges; dm->drawEdges = cdDM_drawEdges; dm->drawLooseEdges = cdDM_drawLooseEdges; dm->drawMappedEdges = cdDM_drawMappedEdges; dm->drawFacesSolid = cdDM_drawFacesSolid; - dm->drawFacesTex = cdDM_drawFacesTex; dm->drawFacesGLSL = cdDM_drawFacesGLSL; dm->drawMappedFaces = cdDM_drawMappedFaces; - dm->drawMappedFacesTex = cdDM_drawMappedFacesTex; dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL; dm->drawMappedFacesMat = cdDM_drawMappedFacesMat; @@ -2153,7 +2033,6 @@ DerivedMesh *CDDM_from_curve_displist(Object *ob, ListBase *dispbase) if (alluv) { const char *uvname = "Orco"; - CustomData_add_layer_named(&cddm->dm.polyData, CD_MTEXPOLY, CD_DEFAULT, NULL, totpoly, uvname); CustomData_add_layer_named(&cddm->dm.loopData, CD_MLOOPUV, CD_ASSIGN, alluv, totloop, uvname); } @@ -2168,22 +2047,18 @@ DerivedMesh *CDDM_from_curve_displist(Object *ob, ListBase *dispbase) static void loops_to_customdata_corners( BMesh *bm, CustomData *facedata, int cdindex, const BMLoop *l3[3], - int numCol, int numTex) + int numCol, int numUV) { const BMLoop *l; - BMFace *f = l3[0]->f; +// BMFace *f = l3[0]->f; MTFace *texface; - MTexPoly *texpoly; MCol *mcol; MLoopCol *mloopcol; MLoopUV *mloopuv; int i, j, hasPCol = CustomData_has_layer(&bm->ldata, CD_PREVIEW_MLOOPCOL); - for (i = 0; i < numTex; i++) { + for (i = 0; i < numUV; i++) { texface = CustomData_get_n(facedata, CD_MTFACE, cdindex, i); - texpoly = CustomData_bmesh_get_n(&bm->pdata, f->head.data, CD_MTEXPOLY, i); - - ME_MTEXFACE_CPY(texface, texpoly); for (j = 0; j < 3; j++) { l = l3[j]; @@ -2237,7 +2112,7 @@ static DerivedMesh *cddm_from_bmesh_ex( MLoop *mloop = cddm->mloop; MPoly *mpoly = cddm->mpoly; int numCol = CustomData_number_of_layers(&bm->ldata, CD_MLOOPCOL); - int numTex = CustomData_number_of_layers(&bm->pdata, CD_MTEXPOLY); + int numUV = CustomData_number_of_layers(&bm->ldata, CD_MLOOPUV); int *index, add_orig; CustomDataMask mask; unsigned int i, j; @@ -2267,7 +2142,7 @@ static DerivedMesh *cddm_from_bmesh_ex( /* add tessellation mface layers */ if (use_tessface) { - CustomData_from_bmeshpoly(&dm->faceData, &dm->polyData, &dm->loopData, em_tottri); + CustomData_from_bmeshpoly(&dm->faceData, &dm->loopData, em_tottri); } index = dm->getVertDataArray(dm, CD_ORIGINDEX); @@ -2339,7 +2214,7 @@ static DerivedMesh *cddm_from_bmesh_ex( /* map mfaces to polygons in the same cddm intentionally */ *index++ = BM_elem_index_get(efa); - loops_to_customdata_corners(bm, &dm->faceData, i, l, numCol, numTex); + loops_to_customdata_corners(bm, &dm->faceData, i, l, numCol, numUV); test_index_face(mf, &dm->faceData, i, 3); } } diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index dd93606a67c..22fd0bbfa9c 100644 --- a/source/blender/blenkernel/intern/cloth.c +++ b/source/blender/blenkernel/intern/cloth.c @@ -40,6 +40,8 @@ #include "BLI_edgehash.h" #include "BLI_linklist.h" +#include "DEG_depsgraph.h" + #include "BKE_cdderivedmesh.h" #include "BKE_cloth.h" #include "BKE_effect.h" @@ -304,14 +306,14 @@ void bvhselftree_update_from_cloth(ClothModifierData *clmd, bool moving) } } -void cloth_clear_cache(Object *ob, ClothModifierData *clmd, float framenr) +void cloth_clear_cache(const EvaluationContext *eval_ctx, Object *ob, ClothModifierData *clmd, float framenr) { PTCacheID pid; BKE_ptcache_id_from_cloth(&pid, ob, clmd); // don't do anything as long as we're in editmode! - if (pid.cache->edit && ob->mode & OB_MODE_PARTICLE_EDIT) + if (pid.cache->edit && eval_ctx->object_mode & OB_MODE_PARTICLE_EDIT) return; BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_AFTER, framenr); @@ -345,7 +347,7 @@ static int do_init_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul return 1; } -static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *result, int framenr) +static int do_step_cloth(const struct EvaluationContext *eval_ctx, Object *ob, ClothModifierData *clmd, DerivedMesh *result, int framenr) { ClothVertex *verts = NULL; Cloth *cloth; @@ -370,7 +372,7 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul mul_m4_v3(ob->obmat, verts->xconst); } - effectors = pdInitEffectors(clmd->scene, ob, NULL, clmd->sim_parms->effector_weights, true); + effectors = pdInitEffectors(eval_ctx, clmd->scene, ob, NULL, clmd->sim_parms->effector_weights, true); if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_DYNAMIC_BASEMESH ) cloth_update_verts ( ob, clmd, result ); @@ -400,7 +402,7 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul /************************************************ * clothModifier_do - main simulation function ************************************************/ -void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, DerivedMesh *dm, float (*vertexCos)[3]) +void clothModifier_do(ClothModifierData *clmd, const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, DerivedMesh *dm, float (*vertexCos)[3]) { PointCache *cache; PTCacheID pid; @@ -478,7 +480,6 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived return; } - if (!can_simulate) return; /* if on second frame, write cache for first frame */ @@ -490,7 +491,7 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived /* do simulation */ BKE_ptcache_validate(cache, framenr); - if (!do_step_cloth(ob, clmd, dm, framenr)) { + if (!do_step_cloth(eval_ctx, ob, clmd, dm, framenr)) { BKE_ptcache_invalidate(cache); } else @@ -922,7 +923,7 @@ static void cloth_from_mesh ( ClothModifierData *clmd, DerivedMesh *dm ) } /*************************************************************************************** - * SPRING NETWORK BUILDING IMPLEMENTATION BEGIN + * SPRING NETWORK GWN_BATCH_BUILDING IMPLEMENTATION BEGIN ***************************************************************************************/ BLI_INLINE void spring_verts_ordered_set(ClothSpring *spring, int v0, int v1) @@ -1504,6 +1505,6 @@ static int cloth_build_springs ( ClothModifierData *clmd, DerivedMesh *dm ) } /* cloth_build_springs */ /*************************************************************************************** - * SPRING NETWORK BUILDING IMPLEMENTATION END + * SPRING NETWORK GWN_BATCH_BUILDING IMPLEMENTATION END ***************************************************************************************/ diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c new file mode 100644 index 00000000000..69168c4dd3d --- /dev/null +++ b/source/blender/blenkernel/intern/collection.c @@ -0,0 +1,909 @@ +/* + * ***** 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. + * + * Contributor(s): Dalai Felinto + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/collection.c + * \ingroup bke + */ + +#include <string.h> + +#include "BLI_blenlib.h" +#include "BLI_ghash.h" +#include "BLI_iterator.h" +#include "BLI_listbase.h" +#include "BLI_math_base.h" +#include "BLT_translation.h" +#include "BLI_string_utils.h" + +#include "BKE_collection.h" +#include "BKE_group.h" +#include "BKE_idprop.h" +#include "BKE_layer.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_scene.h" + +#include "DNA_group_types.h" +#include "DNA_ID.h" +#include "DNA_layer_types.h" +#include "DNA_object_types.h" +#include "DNA_scene_types.h" + +#include "MEM_guardedalloc.h" + +/* Prototypes. */ +static SceneCollection *find_collection_parent(const struct SceneCollection *sc_child, struct SceneCollection *sc_parent); +static bool is_collection_in_tree(const struct SceneCollection *sc_reference, struct SceneCollection *sc_parent); + +static SceneCollection *collection_master_from_id(const ID *owner_id) +{ + switch (GS(owner_id->name)) { + case ID_SCE: + return ((Scene *)owner_id)->collection; + case ID_GR: + return ((Group *)owner_id)->collection; + default: + BLI_assert(!"ID doesn't support collections"); + return NULL; + } +} + +/** + * Add a new collection, but don't handle syncing with layer collections + */ +static SceneCollection *collection_add(ID *owner_id, SceneCollection *sc_parent, const int type, const char *name_custom) +{ + SceneCollection *sc_master = collection_master_from_id(owner_id); + SceneCollection *sc = MEM_callocN(sizeof(SceneCollection), "New Collection"); + sc->type = type; + const char *name = name_custom; + + if (!sc_parent) { + sc_parent = sc_master; + } + + if (!name) { + if (sc_parent == sc_master) { + name = BLI_sprintfN("Collection %d", BLI_listbase_count(&sc_master->scene_collections) + 1); + } + else { + const int number = BLI_listbase_count(&sc_parent->scene_collections) + 1; + const int digits = integer_digits_i(number); + const int max_len = sizeof(sc_parent->name) + - 1 /* NULL terminator */ + - (1 + digits) /* " %d" */; + name = BLI_sprintfN("%.*s %d", max_len, sc_parent->name, number); + } + } + + BLI_addtail(&sc_parent->scene_collections, sc); + BKE_collection_rename((Scene *)owner_id, sc, name); + + if (name != name_custom) { + MEM_freeN((char *)name); + } + + return sc; +} + +/** + * Add a collection to a collection ListBase and syncronize all render layers + * The ListBase is NULL when the collection is to be added to the master collection + */ +SceneCollection *BKE_collection_add(ID *owner_id, SceneCollection *sc_parent, const int type, const char *name_custom) +{ + if (sc_parent == NULL) { + sc_parent = BKE_collection_master(owner_id); + } + + SceneCollection *scene_collection = collection_add(owner_id, sc_parent, type, name_custom); + BKE_layer_sync_new_scene_collection(owner_id, sc_parent, scene_collection); + return scene_collection; +} + +/** + * Free the collection items recursively + */ +static void collection_free(SceneCollection *sc, const bool do_id_user) +{ + if (do_id_user) { + for (LinkData *link = sc->objects.first; link; link = link->next) { + id_us_min(link->data); + } + } + + BLI_freelistN(&sc->objects); + + for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { + collection_free(nsc, do_id_user); + } + BLI_freelistN(&sc->scene_collections); +} + +/** + * Unlink the collection recursively + * \return true if unlinked. + */ +static bool collection_remlink(SceneCollection *sc_parent, SceneCollection *sc_gone) +{ + for (SceneCollection *sc = sc_parent->scene_collections.first; sc; sc = sc->next) { + if (sc == sc_gone) { + BLI_remlink(&sc_parent->scene_collections, sc_gone); + return true; + } + + if (collection_remlink(sc, sc_gone)) { + return true; + } + } + return false; +} + +/** + * Recursively remove any instance of this SceneCollection + */ +static void layer_collection_remove(ViewLayer *view_layer, ListBase *lb, const SceneCollection *sc) +{ + LayerCollection *lc = lb->first; + while (lc) { + if (lc->scene_collection == sc) { + BKE_layer_collection_free(view_layer, lc); + BLI_remlink(lb, lc); + + LayerCollection *lc_next = lc->next; + MEM_freeN(lc); + lc = lc_next; + + /* only the "top-level" layer collections may have the + * same SceneCollection in a sibling tree. + */ + if (lb != &view_layer->layer_collections) { + return; + } + } + + else { + layer_collection_remove(view_layer, &lc->layer_collections, sc); + lc = lc->next; + } + } +} + +/** + * Remove a collection from the scene, and syncronize all render layers + * + * If an object is in any other collection, link the object to the master collection. + */ +bool BKE_collection_remove(ID *owner_id, SceneCollection *sc) +{ + SceneCollection *sc_master = collection_master_from_id(owner_id); + + /* The master collection cannot be removed. */ + if (sc == sc_master) { + return false; + } + + /* We need to do bottom up removal, otherwise we get a crash when we remove a collection that + * has one of its nested collections linked to a view layer. */ + SceneCollection *scene_collection_nested = sc->scene_collections.first; + while (scene_collection_nested != NULL) { + SceneCollection *scene_collection_next = scene_collection_nested->next; + BKE_collection_remove(owner_id, scene_collection_nested); + scene_collection_nested = scene_collection_next; + } + + /* Unlink from the respective collection tree. */ + if (!collection_remlink(sc_master, sc)) { + BLI_assert(false); + } + + /* If an object is no longer in any collection, we add it to the master collection. */ + ListBase collection_objects; + BLI_duplicatelist(&collection_objects, &sc->objects); + + FOREACH_SCENE_COLLECTION(owner_id, scene_collection_iter) + { + if (scene_collection_iter == sc) { + continue; + } + + LinkData *link_next, *link = collection_objects.first; + while (link) { + link_next = link->next; + + if (BLI_findptr(&scene_collection_iter->objects, link->data, offsetof(LinkData, data))) { + BLI_remlink(&collection_objects, link); + MEM_freeN(link); + } + + link = link_next; + } + } + FOREACH_SCENE_COLLECTION_END + + for (LinkData *link = collection_objects.first; link; link = link->next) { + BKE_collection_object_add(owner_id, sc_master, link->data); + } + + BLI_freelistN(&collection_objects); + + /* Clear the collection items. */ + collection_free(sc, true); + + /* check all layers that use this collection and clear them */ + for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) { + layer_collection_remove(view_layer, &view_layer->layer_collections, sc); + view_layer->active_collection = 0; + } + + MEM_freeN(sc); + return true; +} + +/** + * Copy SceneCollection tree but keep pointing to the same objects + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_collection_copy_data(SceneCollection *sc_dst, SceneCollection *sc_src, const int flag) +{ + BLI_duplicatelist(&sc_dst->objects, &sc_src->objects); + if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { + for (LinkData *link = sc_dst->objects.first; link; link = link->next) { + id_us_plus(link->data); + } + } + + BLI_duplicatelist(&sc_dst->scene_collections, &sc_src->scene_collections); + for (SceneCollection *nsc_src = sc_src->scene_collections.first, *nsc_dst = sc_dst->scene_collections.first; + nsc_src; + nsc_src = nsc_src->next, nsc_dst = nsc_dst->next) + { + BKE_collection_copy_data(nsc_dst, nsc_src, flag); + } +} + +/** + * Makes a shallow copy of a SceneCollection + * + * Add a new collection in the same level as the old one, copy any nested collections + * but link the objects to the new collection (as oppose to copy them). + */ +SceneCollection *BKE_collection_duplicate(ID *owner_id, SceneCollection *scene_collection) +{ + SceneCollection *scene_collection_master = BKE_collection_master(owner_id); + SceneCollection *scene_collection_parent = find_collection_parent(scene_collection, scene_collection_master); + + /* It's not allowed to copy the master collection. */ + if (scene_collection_master == scene_collection) { + return NULL; + } + + SceneCollection *scene_collection_new = collection_add( + owner_id, + scene_collection_parent, + scene_collection->type, + scene_collection->name); + + if (scene_collection_new != scene_collection->next) { + BLI_remlink(&scene_collection_parent->scene_collections, scene_collection_new); + BLI_insertlinkafter(&scene_collection_parent->scene_collections, scene_collection, scene_collection_new); + } + + BKE_collection_copy_data(scene_collection_new, scene_collection, 0); + BKE_layer_sync_new_scene_collection(owner_id, scene_collection_parent, scene_collection_new); + + /* Make sure every linked instance of the new collection has the same values (flags, overrides, ...) as the + * corresponding original collection. */ + BKE_layer_collection_sync_flags(owner_id, scene_collection_new, scene_collection); + + return scene_collection_new; +} + +static SceneCollection *master_collection_from_id(const ID *owner_id) +{ + switch (GS(owner_id->name)) { + case ID_SCE: + return ((const Scene *)owner_id)->collection; + case ID_GR: + return ((const Group *)owner_id)->collection; + default: + BLI_assert(!"ID doesn't support scene collection"); + return NULL; + } +} + +/** + * Returns the master collection of the scene or group + */ +SceneCollection *BKE_collection_master(const ID *owner_id) +{ + return master_collection_from_id(owner_id); +} + +static void collection_rename(const ID *owner_id, SceneCollection *sc, const char *name) +{ + SceneCollection *sc_parent = find_collection_parent(sc, collection_master_from_id(owner_id)); + BLI_strncpy(sc->name, name, sizeof(sc->name)); + BLI_uniquename(&sc_parent->scene_collections, sc, DATA_("Collection"), '.', offsetof(SceneCollection, name), sizeof(sc->name)); +} + +void BKE_collection_rename(const Scene *scene, SceneCollection *sc, const char *name) +{ + collection_rename(&scene->id, sc, name); +} + +/** + * Make sure the collection name is still unique within its siblings. + */ +static void collection_name_check(const ID *owner_id, SceneCollection *sc) +{ + /* It's a bit of a hack, we simply try to make sure the collection name is valid. */ + collection_rename(owner_id, sc, sc->name); +} + +/** + * Free (or release) any data used by the master collection (does not free the master collection itself). + * Used only to clear the entire scene or group data since it's not doing re-syncing of the LayerCollection tree + */ +void BKE_collection_master_free(ID *owner_id, const bool do_id_user) +{ + collection_free(BKE_collection_master(owner_id), do_id_user); +} + +static void collection_object_add(const ID *owner_id, SceneCollection *sc, Object *ob) +{ + BLI_addtail(&sc->objects, BLI_genericNodeN(ob)); + + if (GS(owner_id->name) == ID_SCE) { + id_us_plus((ID *)ob); + } + else { + BLI_assert(GS(owner_id->name) == ID_GR); + if ((ob->flag & OB_FROMGROUP) == 0) { + ob->flag |= OB_FROMGROUP; + } + } + + BKE_layer_sync_object_link(owner_id, sc, ob); +} + +/** + * Add object to collection + */ +bool BKE_collection_object_add(const ID *owner_id, SceneCollection *sc, Object *ob) +{ + if (BLI_findptr(&sc->objects, ob, offsetof(LinkData, data))) { + /* don't add the same object twice */ + return false; + } + + collection_object_add(owner_id, sc, ob); + return true; +} + +/** + * Add object to all collections that reference objects is in + * (used to copy objects) + */ +void BKE_collection_object_add_from(Scene *scene, Object *ob_src, Object *ob_dst) +{ + FOREACH_SCENE_COLLECTION(scene, sc) + { + if (BLI_findptr(&sc->objects, ob_src, offsetof(LinkData, data))) { + collection_object_add(&scene->id, sc, ob_dst); + } + } + FOREACH_SCENE_COLLECTION_END + + for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + Base *base_src = BKE_view_layer_base_find(view_layer, ob_src); + if (base_src != NULL) { + if (base_src->collection_properties == NULL) { + continue; + } + Base *base_dst = BKE_view_layer_base_find(view_layer, ob_dst); + IDP_MergeGroup(base_dst->collection_properties, base_src->collection_properties, true); + } + } +} + +/** + * Remove object from collection. + * \param bmain: Can be NULL if free_us is false. + */ +bool BKE_collection_object_remove(Main *bmain, ID *owner_id, SceneCollection *sc, Object *ob, const bool free_us) +{ + LinkData *link = BLI_findptr(&sc->objects, ob, offsetof(LinkData, data)); + + if (link == NULL) { + return false; + } + + BLI_remlink(&sc->objects, link); + MEM_freeN(link); + + BKE_layer_sync_object_unlink(owner_id, sc, ob); + + if (GS(owner_id->name) == ID_SCE) { + if (free_us) { + BKE_libblock_free_us(bmain, ob); + } + else { + id_us_min(&ob->id); + } + } + else { + BLI_assert(GS(owner_id->name) == ID_GR); + } + + return true; +} + +/** + * Move object from a collection into another + */ +void BKE_collection_object_move(ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src, Object *ob) +{ + if (BKE_collection_object_add(owner_id, sc_dst, ob)) { + BKE_collection_object_remove(NULL, owner_id, sc_src, ob, false); + } +} + +/** + * Remove object from all collections of scene + */ +bool BKE_collections_object_remove(Main *bmain, ID *owner_id, Object *ob, const bool free_us) +{ + bool removed = false; + if (GS(owner_id->name) == ID_SCE) { + BKE_scene_remove_rigidbody_object((Scene *)owner_id, ob); + } + else { + BLI_assert(GS(owner_id->name) == ID_GR); + } + + FOREACH_SCENE_COLLECTION(owner_id, sc) + { + removed |= BKE_collection_object_remove(bmain, owner_id, sc, ob, free_us); + } + FOREACH_SCENE_COLLECTION_END + return removed; +} + +static void layer_collection_sync(LayerCollection *lc_dst, LayerCollection *lc_src) +{ + lc_dst->flag = lc_src->flag; + + /* Pending: sync overrides. */ + IDP_MergeGroup(lc_dst->properties, lc_src->properties, true); + + /* Continue recursively. */ + LayerCollection *lc_dst_nested, *lc_src_nested; + lc_src_nested = lc_src->layer_collections.first; + for (lc_dst_nested = lc_dst->layer_collections.first; + lc_dst_nested && lc_src_nested; + lc_dst_nested = lc_dst_nested->next, lc_src_nested = lc_src_nested->next) + { + layer_collection_sync(lc_dst_nested, lc_src_nested); + } +} + +/** + * Leave only the master collection in, remove everything else. + * @param group + */ +static void collection_group_cleanup(Group *group) +{ + /* Unlink all the LayerCollections. */ + while (group->view_layer->layer_collections.last != NULL) { + BKE_collection_unlink(group->view_layer, group->view_layer->layer_collections.last); + } + + /* Remove all the SceneCollections but the master. */ + collection_free(group->collection, false); +} + +/** + * Create a group from a collection + * + * Any ViewLayer that may have this the related SceneCollection linked is converted + * to a Group Collection. + */ +Group *BKE_collection_group_create(Main *bmain, Scene *scene, LayerCollection *lc_src) +{ + SceneCollection *sc_dst, *sc_src = lc_src->scene_collection; + LayerCollection *lc_dst; + + /* The master collection can't be converted. */ + if (sc_src == BKE_collection_master(&scene->id)) { + return NULL; + } + + /* If a sub-collection of sc_dst is directly linked into a ViewLayer we can't convert. */ + for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + for (LayerCollection *lc_child = view_layer->layer_collections.first; lc_child; lc_child = lc_child->next) { + if (is_collection_in_tree(lc_child->scene_collection, sc_src)) { + return NULL; + } + } + } + + /* Create new group with the same data as the original collection. */ + Group *group = BKE_group_add(bmain, sc_src->name); + collection_group_cleanup(group); + + sc_dst = BKE_collection_add(&group->id, NULL, COLLECTION_TYPE_GROUP_INTERNAL, sc_src->name); + BKE_collection_copy_data(sc_dst, sc_src, 0); + FOREACH_SCENE_COLLECTION(&group->id, sc_group) + { + sc_group->type = COLLECTION_TYPE_GROUP_INTERNAL; + } + FOREACH_SCENE_COLLECTION_END + + lc_dst = BKE_collection_link(group->view_layer, sc_dst); + layer_collection_sync(lc_dst, lc_src); + + return group; +} + +/* ---------------------------------------------------------------------- */ +/* Outliner drag and drop */ + +/** + * Find and return the SceneCollection that has \a sc_child as one of its directly + * nested SceneCollection. + * + * \param sc_parent Initial SceneCollection to look into recursively, usually the master collection + */ +static SceneCollection *find_collection_parent(const SceneCollection *sc_child, SceneCollection *sc_parent) +{ + for (SceneCollection *sc_nested = sc_parent->scene_collections.first; sc_nested; sc_nested = sc_nested->next) { + if (sc_nested == sc_child) { + return sc_parent; + } + + SceneCollection *found = find_collection_parent(sc_child, sc_nested); + if (found) { + return found; + } + } + + return NULL; +} + +/** + * Check if \a sc_reference is nested to \a sc_parent SceneCollection + */ +static bool is_collection_in_tree(const SceneCollection *sc_reference, SceneCollection *sc_parent) +{ + return find_collection_parent(sc_reference, sc_parent) != NULL; +} + +bool BKE_collection_move_above(const ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src) +{ + /* Find the SceneCollection the sc_src belongs to */ + SceneCollection *sc_master = master_collection_from_id(owner_id); + + /* Master Layer can't be moved around*/ + if (ELEM(sc_master, sc_src, sc_dst)) { + return false; + } + + /* collection is already where we wanted it to be */ + if (sc_dst->prev == sc_src) { + return false; + } + + /* We can't move a collection fs the destiny collection + * is nested to the source collection */ + if (is_collection_in_tree(sc_dst, sc_src)) { + return false; + } + + SceneCollection *sc_src_parent = find_collection_parent(sc_src, sc_master); + SceneCollection *sc_dst_parent = find_collection_parent(sc_dst, sc_master); + BLI_assert(sc_src_parent); + BLI_assert(sc_dst_parent); + + /* Remove sc_src from its parent */ + BLI_remlink(&sc_src_parent->scene_collections, sc_src); + + /* Re-insert it where it belongs */ + BLI_insertlinkbefore(&sc_dst_parent->scene_collections, sc_dst, sc_src); + + /* Update the tree */ + BKE_layer_collection_resync(owner_id, sc_src_parent); + BKE_layer_collection_resync(owner_id, sc_dst_parent); + + /* Keep names unique. */ + collection_name_check(owner_id, sc_src); + + return true; +} + +bool BKE_collection_move_below(const ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src) +{ + /* Find the SceneCollection the sc_src belongs to */ + SceneCollection *sc_master = master_collection_from_id(owner_id); + + /* Master Layer can't be moved around*/ + if (ELEM(sc_master, sc_src, sc_dst)) { + return false; + } + + /* Collection is already where we wanted it to be */ + if (sc_dst->next == sc_src) { + return false; + } + + /* We can't move a collection if the destiny collection + * is nested to the source collection */ + if (is_collection_in_tree(sc_dst, sc_src)) { + return false; + } + + SceneCollection *sc_src_parent = find_collection_parent(sc_src, sc_master); + SceneCollection *sc_dst_parent = find_collection_parent(sc_dst, sc_master); + BLI_assert(sc_src_parent); + BLI_assert(sc_dst_parent); + + /* Remove sc_src from its parent */ + BLI_remlink(&sc_src_parent->scene_collections, sc_src); + + /* Re-insert it where it belongs */ + BLI_insertlinkafter(&sc_dst_parent->scene_collections, sc_dst, sc_src); + + /* Update the tree */ + BKE_layer_collection_resync(owner_id, sc_src_parent); + BKE_layer_collection_resync(owner_id, sc_dst_parent); + + /* Keep names unique. */ + collection_name_check(owner_id, sc_src); + + return true; +} + +bool BKE_collection_move_into(const ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src) +{ + /* Find the SceneCollection the sc_src belongs to */ + SceneCollection *sc_master = master_collection_from_id(owner_id); + if (sc_src == sc_master) { + return false; + } + + /* We can't move a collection if the destiny collection + * is nested to the source collection */ + if (is_collection_in_tree(sc_dst, sc_src)) { + return false; + } + + SceneCollection *sc_src_parent = find_collection_parent(sc_src, sc_master); + BLI_assert(sc_src_parent); + + /* collection is already where we wanted it to be */ + if (sc_dst->scene_collections.last == sc_src) { + return false; + } + + /* Remove sc_src from it */ + BLI_remlink(&sc_src_parent->scene_collections, sc_src); + + /* Insert sc_src into sc_dst */ + BLI_addtail(&sc_dst->scene_collections, sc_src); + + /* Update the tree */ + BKE_layer_collection_resync(owner_id, sc_src_parent); + BKE_layer_collection_resync(owner_id, sc_dst); + + /* Keep names unique. */ + collection_name_check(owner_id, sc_src); + + return true; +} + +/* ---------------------------------------------------------------------- */ +/* Iteractors */ +/* scene collection iteractor */ + +typedef struct SceneCollectionsIteratorData { + ID *owner_id; + void **array; + int tot, cur; +} SceneCollectionsIteratorData; + +static void scene_collection_callback(SceneCollection *sc, BKE_scene_collections_Cb callback, void *data) +{ + callback(sc, data); + + for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { + scene_collection_callback(nsc, callback, data); + } +} + +static void scene_collections_count(SceneCollection *UNUSED(sc), void *data) +{ + int *tot = data; + (*tot)++; +} + +static void scene_collections_build_array(SceneCollection *sc, void *data) +{ + SceneCollection ***array = data; + **array = sc; + (*array)++; +} + +static void scene_collections_array(ID *owner_id, SceneCollection ***collections_array, int *tot) +{ + SceneCollection *sc; + SceneCollection **array; + + *collections_array = NULL; + *tot = 0; + + if (owner_id == NULL) { + return; + } + + sc = master_collection_from_id(owner_id); + BLI_assert(sc != NULL); + scene_collection_callback(sc, scene_collections_count, tot); + + if (*tot == 0) + return; + + *collections_array = array = MEM_mallocN(sizeof(SceneCollection *) * (*tot), "SceneCollectionArray"); + scene_collection_callback(sc, scene_collections_build_array, &array); +} + +/** + * Only use this in non-performance critical situations + * (it iterates over all scene collections twice) + */ +void BKE_scene_collections_iterator_begin(BLI_Iterator *iter, void *data_in) +{ + ID *owner_id = data_in; + SceneCollectionsIteratorData *data = MEM_callocN(sizeof(SceneCollectionsIteratorData), __func__); + + data->owner_id = owner_id; + iter->data = data; + iter->valid = true; + + scene_collections_array(owner_id, (SceneCollection ***)&data->array, &data->tot); + BLI_assert(data->tot != 0); + + data->cur = 0; + iter->current = data->array[data->cur]; +} + +void BKE_scene_collections_iterator_next(struct BLI_Iterator *iter) +{ + SceneCollectionsIteratorData *data = iter->data; + + if (++data->cur < data->tot) { + iter->current = data->array[data->cur]; + } + else { + iter->valid = false; + } +} + +void BKE_scene_collections_iterator_end(struct BLI_Iterator *iter) +{ + SceneCollectionsIteratorData *data = iter->data; + + if (data) { + if (data->array) { + MEM_freeN(data->array); + } + MEM_freeN(data); + } + iter->valid = false; +} + + +/* scene objects iteractor */ + +typedef struct SceneObjectsIteratorData { + GSet *visited; + LinkData *link_next; + BLI_Iterator scene_collection_iter; +} SceneObjectsIteratorData; + +void BKE_scene_objects_iterator_begin(BLI_Iterator *iter, void *data_in) +{ + Scene *scene = data_in; + SceneObjectsIteratorData *data = MEM_callocN(sizeof(SceneObjectsIteratorData), __func__); + iter->data = data; + + /* lookup list ot make sure each object is object called once */ + data->visited = BLI_gset_ptr_new(__func__); + + /* we wrap the scenecollection iterator here to go over the scene collections */ + BKE_scene_collections_iterator_begin(&data->scene_collection_iter, scene); + + SceneCollection *sc = data->scene_collection_iter.current; + if (sc->objects.first != NULL) { + iter->current = ((LinkData *)sc->objects.first)->data; + } + else { + BKE_scene_objects_iterator_next(iter); + } +} + +/** + * Gets the first unique object in the sequence + */ +static LinkData *object_base_unique(GSet *gs, LinkData *link) +{ + for (; link != NULL; link = link->next) { + Object *ob = link->data; + void **ob_key_p; + if (!BLI_gset_ensure_p_ex(gs, ob, &ob_key_p)) { + *ob_key_p = ob; + return link; + } + } + return NULL; +} + +void BKE_scene_objects_iterator_next(BLI_Iterator *iter) +{ + SceneObjectsIteratorData *data = iter->data; + LinkData *link = data->link_next ? object_base_unique(data->visited, data->link_next) : NULL; + + if (link) { + data->link_next = link->next; + iter->current = link->data; + } + else { + /* if this is the last object of this ListBase look at the next SceneCollection */ + SceneCollection *sc; + BKE_scene_collections_iterator_next(&data->scene_collection_iter); + do { + sc = data->scene_collection_iter.current; + /* get the first unique object of this collection */ + LinkData *new_link = object_base_unique(data->visited, sc->objects.first); + if (new_link) { + data->link_next = new_link->next; + iter->current = new_link->data; + return; + } + BKE_scene_collections_iterator_next(&data->scene_collection_iter); + } while (data->scene_collection_iter.valid); + + if (!data->scene_collection_iter.valid) { + iter->valid = false; + } + } +} + +void BKE_scene_objects_iterator_end(BLI_Iterator *iter) +{ + SceneObjectsIteratorData *data = iter->data; + if (data) { + BKE_scene_collections_iterator_end(&data->scene_collection_iter); + BLI_gset_free(data->visited, NULL); + MEM_freeN(data); + } +} diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c index bd336016838..21945f07a10 100644 --- a/source/blender/blenkernel/intern/collision.c +++ b/source/blender/blenkernel/intern/collision.c @@ -47,6 +47,8 @@ #include "BKE_cloth.h" #include "BKE_effect.h" +#include "BKE_group.h" +#include "BKE_layer.h" #include "BKE_modifier.h" #include "BKE_scene.h" @@ -501,22 +503,22 @@ static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned /* objects in dupli groups, one level only for now */ if (ob->dup_group && level == 0) { - GroupObject *go; Group *group= ob->dup_group; /* add objects */ - for (go= group->gobject.first; go; go= go->next) - add_collision_object(objs, numobj, maxobj, go->ob, self, level+1, modifier_type); + FOREACH_GROUP_OBJECT(group, object) + { + add_collision_object(objs, numobj, maxobj, object, self, level+1, modifier_type); + } + FOREACH_GROUP_OBJECT_END } } // return all collision objects in scene // collision object will exclude self -Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, int layer, unsigned int *numcollobj, unsigned int modifier_type, bool dupli) +Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, unsigned int *numcollobj, unsigned int modifier_type, bool dupli) { - Base *base; Object **objs; - GroupObject *go; unsigned int numobj= 0, maxobj= 100; int level = dupli ? 0 : 1; @@ -525,16 +527,20 @@ Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, int /* gather all collision objects */ if (group) { /* use specified group */ - for (go= group->gobject.first; go; go= go->next) - add_collision_object(&objs, &numobj, &maxobj, go->ob, self, level, modifier_type); + FOREACH_GROUP_OBJECT(group, object) + { + add_collision_object(&objs, &numobj, &maxobj, object, self, level, modifier_type); + } + FOREACH_GROUP_OBJECT_END } else { Scene *sce_iter; + Base *base; /* add objects in same layer in scene */ for (SETLOOPER(scene, sce_iter, base)) { - if ( base->lay & layer ) + if ((base->flag & BASE_VISIBLED) != 0) { add_collision_object(&objs, &numobj, &maxobj, base->object, self, level, modifier_type); - + } } } @@ -547,7 +553,7 @@ Object **get_collisionobjects(Scene *scene, Object *self, Group *group, unsigned { /* Need to check for active layers, too. Otherwise this check fails if the objects are not on the same layer - DG */ - return get_collisionobjects_ext(scene, self, group, self->lay | scene->lay, numcollobj, modifier_type, true); + return get_collisionobjects_ext(scene, self, group, numcollobj, modifier_type, true); } static void add_collider_cache_object(ListBase **objs, Object *ob, Object *self, int level) @@ -575,24 +581,28 @@ static void add_collider_cache_object(ListBase **objs, Object *ob, Object *self, /* objects in dupli groups, one level only for now */ if (ob->dup_group && level == 0) { - GroupObject *go; Group *group= ob->dup_group; /* add objects */ - for (go= group->gobject.first; go; go= go->next) - add_collider_cache_object(objs, go->ob, self, level+1); + FOREACH_GROUP_OBJECT(group, object) + { + add_collider_cache_object(objs, object, self, level+1); + } + FOREACH_GROUP_OBJECT_END } } ListBase *get_collider_cache(Scene *scene, Object *self, Group *group) { - GroupObject *go; ListBase *objs= NULL; /* add object in same layer in scene */ if (group) { - for (go= group->gobject.first; go; go= go->next) - add_collider_cache_object(&objs, go->ob, self, 0); + FOREACH_GROUP_OBJECT(group, object) + { + add_collider_cache_object(&objs, object, self, 0); + } + FOREACH_GROUP_OBJECT_END } else { Scene *sce_iter; @@ -600,7 +610,7 @@ ListBase *get_collider_cache(Scene *scene, Object *self, Group *group) /* add objects in same layer in scene */ for (SETLOOPER(scene, sce_iter, base)) { - if (!self || (base->lay & self->lay)) + if (!self || ((base->flag & BASE_VISIBLED) != 0)) add_collider_cache_object(&objs, base->object, self, 0); } diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index c77cac7bcbd..b8dc7944a75 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -98,11 +98,6 @@ /* Constraint Target Macros */ #define VALID_CONS_TARGET(ct) ((ct) && (ct->tar)) -/* Workaround for cyclic depenndnecy with curves. - * In such case curve_cache might not be ready yet, - */ -#define CYCLIC_DEPENDENCY_WORKAROUND - /* ************************ Constraints - General Utilities *************************** */ /* These functions here don't act on any specific constraints, and are therefore should/will * not require any of the special function-pointers afforded by the relevant constraint @@ -689,7 +684,7 @@ static bConstraintTypeInfo CTI_CONSTRNAME = { /* This function should be used for the get_target_matrix member of all * constraints that are not picky about what happens to their target matrix. */ -static void default_get_tarmat(bConstraint *con, bConstraintOb *UNUSED(cob), bConstraintTarget *ct, float UNUSED(ctime)) +static void default_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx), bConstraint *con, bConstraintOb *UNUSED(cob), bConstraintTarget *ct, float UNUSED(ctime)) { if (VALID_CONS_TARGET(ct)) constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->flag, con->headtail); @@ -1158,7 +1153,7 @@ static void kinematic_flush_tars(bConstraint *con, ListBase *list, bool no_copy) } } -static void kinematic_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) +static void kinematic_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx), bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) { bKinematicConstraint *data = con->data; @@ -1245,7 +1240,9 @@ static void followpath_flush_tars(bConstraint *con, ListBase *list, bool no_copy } } -static void followpath_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) +static void followpath_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx), + bConstraint *con, bConstraintOb *UNUSED(cob), + bConstraintTarget *ct, float UNUSED(ctime)) { bFollowPathConstraint *data = con->data; @@ -1260,13 +1257,7 @@ static void followpath_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra * currently for paths to work it needs to go through the bevlist/displist system (ton) */ -#ifdef CYCLIC_DEPENDENCY_WORKAROUND - if (ct->tar->curve_cache == NULL) { - BKE_displist_make_curveTypes(cob->scene, ct->tar, false); - } -#endif - - if (ct->tar->curve_cache->path && ct->tar->curve_cache->path->data) { + if (ct->tar->curve_cache && ct->tar->curve_cache->path && ct->tar->curve_cache->path->data) { float quat[4]; if ((data->followflag & FOLLOWPATH_STATIC) == 0) { /* animated position along curve depending on time */ @@ -2027,21 +2018,19 @@ static void pycon_id_looper(bConstraint *con, ConstraintIDFunc func, void *userd } /* Whether this approach is maintained remains to be seen (aligorith) */ -static void pycon_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) +static void pycon_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx), + bConstraint *con, bConstraintOb *UNUSED(cob), + bConstraintTarget *ct, float UNUSED(ctime)) { #ifdef WITH_PYTHON bPythonConstraint *data = con->data; #endif if (VALID_CONS_TARGET(ct)) { -#ifdef CYCLIC_DEPENDENCY_WORKAROUND - /* special exception for curves - depsgraph issues */ - if (ct->tar->type == OB_CURVE) { - if (ct->tar->curve_cache == NULL) { - BKE_displist_make_curveTypes(cob->scene, ct->tar, false); - } + if (ct->tar->type == OB_CURVE && ct->tar->curve_cache == NULL) { + unit_m4(ct->matrix); + return; } -#endif /* firstly calculate the matrix the normal way, then let the py-function override * this matrix if it needs to do so @@ -2145,7 +2134,7 @@ static void actcon_flush_tars(bConstraint *con, ListBase *list, bool no_copy) } } -static void actcon_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) +static void actcon_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx), bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) { bActionConstraint *data = con->data; @@ -3134,16 +3123,10 @@ static void clampto_flush_tars(bConstraint *con, ListBase *list, bool no_copy) } } -static void clampto_get_tarmat(bConstraint *UNUSED(con), bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) +static void clampto_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx), + bConstraint *UNUSED(con), bConstraintOb *UNUSED(cob), + bConstraintTarget *ct, float UNUSED(ctime)) { -#ifdef CYCLIC_DEPENDENCY_WORKAROUND - if (VALID_CONS_TARGET(ct)) { - if (ct->tar->curve_cache == NULL) { - BKE_displist_make_curveTypes(cob->scene, ct->tar, false); - } - } -#endif - /* technically, this isn't really needed for evaluation, but we don't know what else * might end up calling this... */ @@ -3477,7 +3460,7 @@ static void shrinkwrap_flush_tars(bConstraint *con, ListBase *list, bool no_copy } -static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) +static void shrinkwrap_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx), bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) { bShrinkwrapConstraint *scon = (bShrinkwrapConstraint *) con->data; @@ -3809,16 +3792,10 @@ static void splineik_flush_tars(bConstraint *con, ListBase *list, bool no_copy) } } -static void splineik_get_tarmat(bConstraint *UNUSED(con), bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) +static void splineik_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx), + bConstraint *UNUSED(con), bConstraintOb *UNUSED(cob), + bConstraintTarget *ct, float UNUSED(ctime)) { -#ifdef CYCLIC_DEPENDENCY_WORKAROUND - if (VALID_CONS_TARGET(ct)) { - if (ct->tar->curve_cache == NULL) { - BKE_displist_make_curveTypes(cob->scene, ct->tar, false); - } - } -#endif - /* technically, this isn't really needed for evaluation, but we don't know what else * might end up calling this... */ @@ -4867,7 +4844,7 @@ bool BKE_constraints_proxylocked_owner(Object *ob, bPoseChannel *pchan) * None of the actual calculations of the matrices should be done here! Also, this function is * not to be used by any new constraints, particularly any that have multiple targets. */ -void BKE_constraint_target_matrix_get(Scene *scene, bConstraint *con, int index, short ownertype, void *ownerdata, float mat[4][4], float ctime) +void BKE_constraint_target_matrix_get(const struct EvaluationContext *eval_ctx, Scene *scene, bConstraint *con, int index, short ownertype, void *ownerdata, float mat[4][4], float ctime) { const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); ListBase targets = {NULL, NULL}; @@ -4918,7 +4895,7 @@ void BKE_constraint_target_matrix_get(Scene *scene, bConstraint *con, int index, if (ct) { if (cti->get_target_matrix) - cti->get_target_matrix(con, cob, ct, ctime); + cti->get_target_matrix(eval_ctx, con, cob, ct, ctime); copy_m4_m4(mat, ct->matrix); } @@ -4934,7 +4911,7 @@ void BKE_constraint_target_matrix_get(Scene *scene, bConstraint *con, int index, } /* Get the list of targets required for solving a constraint */ -void BKE_constraint_targets_for_solving_get(bConstraint *con, bConstraintOb *cob, ListBase *targets, float ctime) +void BKE_constraint_targets_for_solving_get(const struct EvaluationContext *eval_ctx, bConstraint *con, bConstraintOb *cob, ListBase *targets, float ctime) { const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); @@ -4952,7 +4929,7 @@ void BKE_constraint_targets_for_solving_get(bConstraint *con, bConstraintOb *cob */ if (cti->get_target_matrix) { for (ct = targets->first; ct; ct = ct->next) - cti->get_target_matrix(con, cob, ct, ctime); + cti->get_target_matrix(eval_ctx, con, cob, ct, ctime); } else { for (ct = targets->first; ct; ct = ct->next) @@ -4969,7 +4946,7 @@ void BKE_constraint_targets_for_solving_get(bConstraint *con, bConstraintOb *cob * BKE_constraints_make_evalob and BKE_constraints_clear_evalob should be called before and * after running this function, to sort out cob */ -void BKE_constraints_solve(ListBase *conlist, bConstraintOb *cob, float ctime) +void BKE_constraints_solve(const struct EvaluationContext *eval_ctx, ListBase *conlist, bConstraintOb *cob, float ctime) { bConstraint *con; float oldmat[4][4]; @@ -5004,7 +4981,7 @@ void BKE_constraints_solve(ListBase *conlist, bConstraintOb *cob, float ctime) BKE_constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace, false); /* prepare targets for constraint solving */ - BKE_constraint_targets_for_solving_get(con, cob, &targets, ctime); + BKE_constraint_targets_for_solving_get(eval_ctx, con, cob, &targets, ctime); /* Solve the constraint and put result in cob->matrix */ cti->evaluate_constraint(con, cob, &targets); diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c index 4c01bfd35f2..2af3b6ce593 100644 --- a/source/blender/blenkernel/intern/context.c +++ b/source/blender/blenkernel/intern/context.c @@ -38,6 +38,9 @@ #include "DNA_object_types.h" #include "DNA_linestyle_types.h" #include "DNA_gpencil_types.h" +#include "DNA_workspace_types.h" + +#include "DEG_depsgraph.h" #include "BLI_listbase.h" #include "BLI_string.h" @@ -47,9 +50,14 @@ #include "BLT_translation.h" #include "BKE_context.h" +#include "BKE_layer.h" #include "BKE_main.h" +#include "BKE_scene.h" #include "BKE_screen.h" #include "BKE_sound.h" +#include "BKE_workspace.h" + +#include "RE_engine.h" #include "RNA_access.h" @@ -66,10 +74,12 @@ struct bContext { struct { struct wmWindowManager *manager; struct wmWindow *window; + struct WorkSpace *workspace; struct bScreen *screen; struct ScrArea *area; struct ARegion *region; struct ARegion *menu; + struct wmManipulatorGroup *manipulator_group; struct bContextStore *store; const char *operator_poll_msg; /* reason for poll failing */ } wm; @@ -627,6 +637,11 @@ wmWindow *CTX_wm_window(const bContext *C) return ctx_wm_python_context_get(C, "window", &RNA_Window, C->wm.window); } +WorkSpace *CTX_wm_workspace(const bContext *C) +{ + return ctx_wm_python_context_get(C, "workspace", &RNA_WorkSpace, C->wm.workspace); +} + bScreen *CTX_wm_screen(const bContext *C) { return ctx_wm_python_context_get(C, "screen", &RNA_Screen, C->wm.screen); @@ -659,6 +674,16 @@ struct ARegion *CTX_wm_menu(const bContext *C) return C->wm.menu; } +struct wmManipulatorGroup *CTX_wm_manipulator_group(const bContext *C) +{ + return C->wm.manipulator_group; +} + +struct wmMsgBus *CTX_wm_message_bus(const bContext *C) +{ + return C->wm.manager ? C->wm.manager->message_bus : NULL; +} + struct ReportList *CTX_wm_reports(const bContext *C) { if (C->wm.manager) @@ -826,9 +851,11 @@ void CTX_wm_manager_set(bContext *C, wmWindowManager *wm) void CTX_wm_window_set(bContext *C, wmWindow *win) { C->wm.window = win; - C->wm.screen = (win) ? win->screen : NULL; - if (C->wm.screen) - C->data.scene = C->wm.screen->scene; + if (win) { + C->data.scene = win->scene; + } + C->wm.workspace = (win) ? BKE_workspace_active_get(win->workspace_hook) : NULL; + C->wm.screen = (win) ? BKE_workspace_active_screen_get(win->workspace_hook) : NULL; C->wm.area = NULL; C->wm.region = NULL; } @@ -836,8 +863,6 @@ void CTX_wm_window_set(bContext *C, wmWindow *win) void CTX_wm_screen_set(bContext *C, bScreen *screen) { C->wm.screen = screen; - if (C->wm.screen) - C->data.scene = C->wm.screen->scene; C->wm.area = NULL; C->wm.region = NULL; } @@ -858,6 +883,11 @@ void CTX_wm_menu_set(bContext *C, ARegion *menu) C->wm.menu = menu; } +void CTX_wm_manipulator_group_set(bContext *C, struct wmManipulatorGroup *mgroup) +{ + C->wm.manipulator_group = mgroup; +} + void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg) { C->wm.operator_poll_msg = msg; @@ -896,10 +926,80 @@ Scene *CTX_data_scene(const bContext *C) return C->data.scene; } -int CTX_data_mode_enum(const bContext *C) +ViewLayer *CTX_data_view_layer(const bContext *C) { - Object *obedit = CTX_data_edit_object(C); + ViewLayer *view_layer; + + if (ctx_data_pointer_verify(C, "view_layer", (void *)&view_layer)) { + return view_layer; + } + else { + return BKE_view_layer_from_workspace_get(CTX_data_scene(C), CTX_wm_workspace(C)); + } +} + +ViewRender *CTX_data_view_render(const bContext *C) +{ + ViewRender *view_render; + + if (ctx_data_pointer_verify(C, "view_render", (void *)&view_render)) { + return view_render; + } + else { + Scene *scene = CTX_data_scene(C); + WorkSpace *workspace = CTX_wm_workspace(C); + return BKE_viewrender_get(scene, workspace); + } +} + +RenderEngineType *CTX_data_engine_type(const bContext *C) +{ + ViewRender *view_render = CTX_data_view_render(C); + return RE_engines_find(view_render->engine_id); +} +/** + * This is tricky. Sometimes the user overrides the render_layer + * but not the scene_collection. In this case what to do? + * + * If the scene_collection is linked to the ViewLayer we use it. + * Otherwise we fallback to the active one of the ViewLayer. + */ +LayerCollection *CTX_data_layer_collection(const bContext *C) +{ + ViewLayer *view_layer = CTX_data_view_layer(C); + LayerCollection *layer_collection; + + if (ctx_data_pointer_verify(C, "layer_collection", (void *)&layer_collection)) { + if (BKE_view_layer_has_collection(view_layer, layer_collection->scene_collection)) { + return layer_collection; + } + } + + /* fallback */ + return BKE_layer_collection_get_active(view_layer); +} + +SceneCollection *CTX_data_scene_collection(const bContext *C) +{ + SceneCollection *scene_collection; + if (ctx_data_pointer_verify(C, "scene_collection", (void *)&scene_collection)) { + return scene_collection; + } + + LayerCollection *layer_collection = CTX_data_layer_collection(C); + if (layer_collection) { + return layer_collection->scene_collection; + } + + /* fallback */ + Scene *scene = CTX_data_scene(C); + return BKE_collection_master(&scene->id); +} + +int CTX_data_mode_enum_ex(const Object *obedit, const Object *ob, const eObjectMode object_mode) +{ + // Object *obedit = CTX_data_edit_object(C); if (obedit) { switch (obedit->type) { case OB_MESH: @@ -919,21 +1019,27 @@ int CTX_data_mode_enum(const bContext *C) } } else { - Object *ob = CTX_data_active_object(C); - + // Object *ob = CTX_data_active_object(C); if (ob) { - if (ob->mode & OB_MODE_POSE) return CTX_MODE_POSE; - else if (ob->mode & OB_MODE_SCULPT) return CTX_MODE_SCULPT; - else if (ob->mode & OB_MODE_WEIGHT_PAINT) return CTX_MODE_PAINT_WEIGHT; - else if (ob->mode & OB_MODE_VERTEX_PAINT) return CTX_MODE_PAINT_VERTEX; - else if (ob->mode & OB_MODE_TEXTURE_PAINT) return CTX_MODE_PAINT_TEXTURE; - else if (ob->mode & OB_MODE_PARTICLE_EDIT) return CTX_MODE_PARTICLE; + if (object_mode & OB_MODE_POSE) return CTX_MODE_POSE; + else if (object_mode & OB_MODE_SCULPT) return CTX_MODE_SCULPT; + else if (object_mode & OB_MODE_WEIGHT_PAINT) return CTX_MODE_PAINT_WEIGHT; + else if (object_mode & OB_MODE_VERTEX_PAINT) return CTX_MODE_PAINT_VERTEX; + else if (object_mode & OB_MODE_TEXTURE_PAINT) return CTX_MODE_PAINT_TEXTURE; + else if (object_mode & OB_MODE_PARTICLE_EDIT) return CTX_MODE_PARTICLE; } } return CTX_MODE_OBJECT; } +int CTX_data_mode_enum(const bContext *C) +{ + const WorkSpace *workspace = CTX_wm_workspace(C); + Object *obedit = CTX_data_edit_object(C); + Object *obact = obedit ? NULL : CTX_data_active_object(C); + return CTX_data_mode_enum_ex(obedit, obact, workspace->object_mode); +} /* would prefer if we can use the enum version below over this one - Campbell */ /* must be aligned with above enum */ @@ -954,6 +1060,7 @@ static const char *data_mode_strings[] = { "objectmode", NULL }; +BLI_STATIC_ASSERT(ARRAY_SIZE(data_mode_strings) == CTX_MODE_NUM + 1, "Must have a string for each context mode") const char *CTX_data_mode_string(const bContext *C) { return data_mode_strings[CTX_data_mode_enum(C)]; @@ -1154,3 +1261,23 @@ int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list) return ctx_data_collection_get(C, "editable_gpencil_strokes", list); } +Depsgraph *CTX_data_depsgraph(const bContext *C) +{ + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + return BKE_scene_get_depsgraph(scene, view_layer, true); +} + +void CTX_data_eval_ctx(const bContext *C, EvaluationContext *eval_ctx) +{ + BLI_assert(C != NULL); + + Scene *scene = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); + RenderEngineType *engine_type = CTX_data_engine_type(C); + WorkSpace *workspace = CTX_wm_workspace(C); + DEG_evaluation_context_init_from_scene( + eval_ctx, + scene, view_layer, engine_type, + workspace->object_mode, DAG_EVAL_VIEWPORT); +} diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c index 56df8e51eba..d2ffbbcf27b 100644 --- a/source/blender/blenkernel/intern/crazyspace.c +++ b/source/blender/blenkernel/intern/crazyspace.c @@ -99,7 +99,8 @@ static int modifiers_disable_subsurf_temporary(Object *ob) } /* disable subsurf temporal, get mapped cos, and enable it */ -float (*BKE_crazyspace_get_mapped_editverts(Scene *scene, Object *obedit))[3] +float (*BKE_crazyspace_get_mapped_editverts( + const struct EvaluationContext *eval_ctx, Scene *scene, Object *obedit))[3] { Mesh *me = obedit->data; DerivedMesh *dm; @@ -109,13 +110,13 @@ float (*BKE_crazyspace_get_mapped_editverts(Scene *scene, Object *obedit))[3] /* disable subsurf temporal, get mapped cos, and enable it */ if (modifiers_disable_subsurf_temporary(obedit)) { /* need to make new derivemesh */ - makeDerivedMesh(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH, false); + makeDerivedMesh(eval_ctx, scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH, false); } /* now get the cage */ vertexcos = MEM_mallocN(sizeof(*vertexcos) * nverts, "vertexcos map"); - dm = editbmesh_get_derived_cage(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH); + dm = editbmesh_get_derived_cage(eval_ctx, scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH); mesh_get_mapped_verts_coords(dm, vertexcos, nverts); @@ -250,8 +251,9 @@ void BKE_crazyspace_set_quats_mesh(Mesh *me, float (*origcos)[3], float (*mapped /** returns an array of deform matrices for crazyspace correction, and the * number of modifiers left */ -int BKE_crazyspace_get_first_deform_matrices_editbmesh(Scene *scene, Object *ob, BMEditMesh *em, - float (**deformmats)[3][3], float (**deformcos)[3]) +int BKE_crazyspace_get_first_deform_matrices_editbmesh( + const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, BMEditMesh *em, + float (**deformmats)[3][3], float (**deformcos)[3]) { ModifierData *md; DerivedMesh *dm; @@ -290,7 +292,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(Scene *scene, Object *ob, unit_m3(defmats[a]); } - mti->deformMatricesEM(md, ob, em, dm, deformedVerts, defmats, + mti->deformMatricesEM(md, eval_ctx, ob, em, dm, deformedVerts, defmats, numVerts); } else @@ -310,7 +312,9 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(Scene *scene, Object *ob, return numleft; } -int BKE_sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]) +int BKE_sculpt_get_first_deform_matrices( + const struct EvaluationContext *eval_ctx, Scene *scene, + Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]) { ModifierData *md; DerivedMesh *dm; @@ -346,7 +350,7 @@ int BKE_sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**defo unit_m3(defmats[a]); } - if (mti->deformMatrices) mti->deformMatrices(md, ob, dm, deformedVerts, defmats, numVerts); + if (mti->deformMatrices) mti->deformMatrices(md, eval_ctx, ob, dm, deformedVerts, defmats, numVerts); else break; } } @@ -369,9 +373,9 @@ int BKE_sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**defo return numleft; } -void BKE_crazyspace_build_sculpt(Scene *scene, Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]) +void BKE_crazyspace_build_sculpt(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]) { - int totleft = BKE_sculpt_get_first_deform_matrices(scene, ob, deformmats, deformcos); + int totleft = BKE_sculpt_get_first_deform_matrices(eval_ctx, scene, ob, deformmats, deformcos); if (totleft) { /* there are deformation modifier which doesn't support deformation matrices @@ -396,7 +400,7 @@ void BKE_crazyspace_build_sculpt(Scene *scene, Object *ob, float (**deformmats)[ if (mti->deformMatrices && !deformed) continue; - mti->deformVerts(md, ob, NULL, deformedVerts, me->totvert, 0); + mti->deformVerts(md, eval_ctx, ob, NULL, deformedVerts, me->totvert, 0); deformed = 1; } } diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index d18fda632aa..2a27bad0fb5 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -53,7 +53,6 @@ #include "BKE_animsys.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_displist.h" #include "BKE_font.h" #include "BKE_global.h" @@ -65,6 +64,8 @@ #include "BKE_object.h" #include "BKE_material.h" +#include "DEG_depsgraph.h" + /* globals */ /* local */ @@ -127,6 +128,8 @@ void BKE_curve_free(Curve *cu) { BKE_animdata_free((ID *)cu, false); + BKE_curve_batch_cache_free(cu); + BKE_nurbList_free(&cu->nurb); BKE_curve_editfont_free(cu); @@ -207,6 +210,7 @@ void BKE_curve_copy_data(Main *bmain, Curve *cu_dst, const Curve *cu_src, const cu_dst->strinfo = MEM_dupallocN(cu_src->strinfo); cu_dst->tb = MEM_dupallocN(cu_src->tb); cu_dst->bb = MEM_dupallocN(cu_src->bb); + cu_dst->batch_cache = NULL; if (cu_src->key) { BKE_id_copy_ex(bmain, &cu_src->key->id, (ID **)&cu_dst->key, flag, false); @@ -1620,7 +1624,7 @@ float *BKE_curve_surf_make_orco(Object *ob) /* NOTE: This routine is tied to the order of vertex * built by displist and as passed to the renderer. */ -float *BKE_curve_make_orco(Scene *scene, Object *ob, int *r_numVerts) +float *BKE_curve_make_orco(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, int *r_numVerts) { Curve *cu = ob->data; DispList *dl; @@ -1628,7 +1632,7 @@ float *BKE_curve_make_orco(Scene *scene, Object *ob, int *r_numVerts) float *fp, *coord_array; ListBase disp = {NULL, NULL}; - BKE_displist_make_curveTypes_forOrco(scene, ob, &disp); + BKE_displist_make_curveTypes_forOrco(eval_ctx, scene, ob, &disp); numVerts = 0; for (dl = disp.first; dl; dl = dl->next) { @@ -1719,8 +1723,9 @@ float *BKE_curve_make_orco(Scene *scene, Object *ob, int *r_numVerts) /* ***************** BEVEL ****************** */ -void BKE_curve_bevel_make(Scene *scene, Object *ob, ListBase *disp, - const bool for_render, const bool use_render_resolution) +void BKE_curve_bevel_make( + const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *disp, + const bool for_render, const bool use_render_resolution) { DispList *dl, *dlnew; Curve *bevcu, *cu; @@ -1744,7 +1749,7 @@ void BKE_curve_bevel_make(Scene *scene, Object *ob, ListBase *disp, facy = cu->bevobj->size[1]; if (for_render) { - BKE_displist_make_curveTypes_forRender(scene, cu->bevobj, &bevdisp, NULL, false, use_render_resolution); + BKE_displist_make_curveTypes_forRender(eval_ctx, scene, cu->bevobj, &bevdisp, NULL, false, use_render_resolution); dl = bevdisp.first; } else if (cu->bevobj->curve_cache) { @@ -5183,7 +5188,7 @@ int BKE_curve_material_index_validate(Curve *cu) } if (!is_valid) { - DAG_id_tag_update(&cu->id, OB_RECALC_DATA); + DEG_id_tag_update(&cu->id, OB_RECALC_DATA); return true; } else { @@ -5250,7 +5255,7 @@ void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *t /* **** Depsgraph evaluation **** */ -void BKE_curve_eval_geometry(EvaluationContext *UNUSED(eval_ctx), +void BKE_curve_eval_geometry(const EvaluationContext *UNUSED(eval_ctx), Curve *curve) { if (G.debug & G_DEBUG_DEPSGRAPH) { @@ -5260,3 +5265,20 @@ void BKE_curve_eval_geometry(EvaluationContext *UNUSED(eval_ctx), BKE_curve_texspace_calc(curve); } } + +/* Draw Engine */ +void (*BKE_curve_batch_cache_dirty_cb)(Curve *cu, int mode) = NULL; +void (*BKE_curve_batch_cache_free_cb)(Curve *cu) = NULL; + +void BKE_curve_batch_cache_dirty(Curve *cu, int mode) +{ + if (cu->batch_cache) { + BKE_curve_batch_cache_dirty_cb(cu, mode); + } +} +void BKE_curve_batch_cache_free(Curve *cu) +{ + if (cu->batch_cache) { + BKE_curve_batch_cache_free_cb(cu); + } +} diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c index cf86963cf60..9c0ace2f654 100644 --- a/source/blender/blenkernel/intern/customdata.c +++ b/source/blender/blenkernel/intern/customdata.c @@ -390,37 +390,19 @@ static void layerSwap_tface(void *data, const int *corner_indices) { MTFace *tf = data; float uv[4][2]; - static const short pin_flags[4] = { TF_PIN1, TF_PIN2, TF_PIN3, TF_PIN4 }; - static const char sel_flags[4] = { TF_SEL1, TF_SEL2, TF_SEL3, TF_SEL4 }; - short unwrap = tf->unwrap & ~(TF_PIN1 | TF_PIN2 | TF_PIN3 | TF_PIN4); - char flag = tf->flag & ~(TF_SEL1 | TF_SEL2 | TF_SEL3 | TF_SEL4); int j; for (j = 0; j < 4; ++j) { const int source_index = corner_indices[j]; - copy_v2_v2(uv[j], tf->uv[source_index]); - - /* swap pinning flags around */ - if (tf->unwrap & pin_flags[source_index]) { - unwrap |= pin_flags[j]; - } - - /* swap selection flags around */ - if (tf->flag & sel_flags[source_index]) { - flag |= sel_flags[j]; - } } memcpy(tf->uv, uv, sizeof(tf->uv)); - tf->unwrap = unwrap; - tf->flag = flag; } static void layerDefault_tface(void *data, int count) { - static MTFace default_tf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}, NULL, - 0, 0, TF_DYNAMIC | TF_CONVERTED, 0, 0}; + static MTFace default_tf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}}; MTFace *tf = (MTFace *)data; int i; @@ -1190,6 +1172,15 @@ static void layerSwap_flnor(void *data, const int *corner_indices) memcpy(flnors, nors, sizeof(nors)); } +static void layerDefault_fmap(void *data, int count) +{ + int *fmap_num = (int *)data; + int i; + for (i = 0; i < count; i++) { + *fmap_num = -1; + } +} + static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { /* 0: CD_MVERT */ {sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL}, @@ -1215,8 +1206,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { /* 3 floats per normal vector */ {sizeof(float) * 3, "vec3f", 1, NULL, NULL, NULL, layerInterp_normal, NULL, NULL, NULL, NULL, NULL, NULL, NULL, layerCopyValue_normal}, - /* 9: CD_POLYINDEX */ /* DEPRECATED */ - {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, + /* 9: CD_FACEMAP */ + {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, layerDefault_fmap, NULL}, /* 10: CD_PROP_FLT */ {sizeof(MFloatProperty), "MFloatProperty", 1, N_("Float"), layerCopy_propFloat, NULL, NULL, NULL}, /* 11: CD_PROP_INT */ @@ -1228,10 +1219,9 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { layerInterp_origspace_face, layerSwap_origspace_face, layerDefault_origspace_face}, /* 14: CD_ORCO */ {sizeof(float) * 3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, - /* 15: CD_MTEXPOLY */ + /* 15: CD_MTEXPOLY */ /* DEPRECATED */ /* 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, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, layerMaxNum_tface}, + {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL}, /* 16: CD_MLOOPUV */ {sizeof(MLoopUV), "MLoopUV", 1, N_("UVMap"), NULL, NULL, layerInterp_mloopuv, NULL, NULL, layerEqual_mloopuv, layerMultiply_mloopuv, layerInitMinMax_mloopuv, @@ -1310,7 +1300,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { static const char *LAYERTYPENAMES[CD_NUMTYPES] = { /* 0-4 */ "CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace", - /* 5-9 */ "CDMTFace", "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags", + /* 5-9 */ "CDMTFace", "CDMCol", "CDOrigIndex", "CDNormal", "CDFaceMap", /* 10-14 */ "CDMFloatProperty", "CDMIntProperty", "CDMStringProperty", "CDOrigSpace", "CDOrco", /* 15-19 */ "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent", "CDMDisps", /* 20-24 */ "CDPreviewMCol", "CDIDMCol", "CDTextureMCol", "CDClothOrco", "CDMRecast", @@ -1325,41 +1315,41 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = { const CustomDataMask CD_MASK_BAREMESH = - CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MLOOP | CD_MASK_MPOLY | CD_MASK_BWEIGHT; + CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MLOOP | CD_MASK_MPOLY | CD_MASK_BWEIGHT | CD_MASK_FACEMAP; const CustomDataMask CD_MASK_MESH = CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MPOLY | CD_MASK_MLOOP | - CD_MASK_MTEXPOLY | CD_MASK_RECAST | CD_MASK_PAINT_MASK | + CD_MASK_RECAST | CD_MASK_PAINT_MASK | CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE | - CD_MASK_CUSTOMLOOPNORMAL; + CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_FACEMAP; const CustomDataMask CD_MASK_EDITMESH = CD_MASK_MDEFORMVERT | CD_MASK_MLOOPUV | - CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_SHAPE_KEYINDEX | + CD_MASK_MLOOPCOL | CD_MASK_SHAPE_KEYINDEX | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS | CD_MASK_SHAPEKEY | CD_MASK_RECAST | CD_MASK_PAINT_MASK | - CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_CUSTOMLOOPNORMAL; + CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_FACEMAP; const CustomDataMask CD_MASK_DERIVEDMESH = CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_CLOTH_ORCO | - CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_PREVIEW_MLOOPCOL | + CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORIGSPACE_MLOOP | CD_MASK_ORCO | CD_MASK_TANGENT | CD_MASK_PREVIEW_MCOL | CD_MASK_SHAPEKEY | CD_MASK_RECAST | CD_MASK_ORIGINDEX | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE | - CD_MASK_CUSTOMLOOPNORMAL; + CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_FACEMAP; const CustomDataMask CD_MASK_BMESH = - CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | + CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX | CD_MASK_MDISPS | CD_MASK_CREASE | CD_MASK_BWEIGHT | CD_MASK_RECAST | CD_MASK_PAINT_MASK | CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE | - CD_MASK_CUSTOMLOOPNORMAL; + CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_FACEMAP; /** * cover values copied by #BKE_mesh_loops_to_tessdata */ const CustomDataMask CD_MASK_FACECORNERS = - CD_MASK_MTFACE | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV | + CD_MASK_MTFACE | CD_MASK_MLOOPUV | CD_MASK_MCOL | CD_MASK_MLOOPCOL | CD_MASK_PREVIEW_MCOL | CD_MASK_PREVIEW_MLOOPCOL | CD_MASK_ORIGSPACE | CD_MASK_ORIGSPACE_MLOOP | @@ -1368,7 +1358,7 @@ const CustomDataMask CD_MASK_FACECORNERS = const CustomDataMask CD_MASK_EVERYTHING = CD_MASK_MVERT | CD_MASK_MDEFORMVERT | CD_MASK_MEDGE | CD_MASK_MFACE | CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_NORMAL /* | CD_MASK_POLYINDEX */ | CD_MASK_PROP_FLT | - CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV | + CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_TANGENT | CD_MASK_MDISPS | CD_MASK_PREVIEW_MCOL | CD_MASK_CLOTH_ORCO | CD_MASK_RECAST | /* BMESH ONLY START */ CD_MASK_MPOLY | CD_MASK_MLOOP | CD_MASK_SHAPE_KEYINDEX | CD_MASK_SHAPEKEY | CD_MASK_BWEIGHT | CD_MASK_CREASE | @@ -1376,7 +1366,7 @@ const CustomDataMask CD_MASK_EVERYTHING = /* BMESH ONLY END */ CD_MASK_PAINT_MASK | CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE | - CD_MASK_MLOOPTANGENT | CD_MASK_TESSLOOPNORMAL | CD_MASK_CUSTOMLOOPNORMAL; + CD_MASK_MLOOPTANGENT | CD_MASK_TESSLOOPNORMAL | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_FACEMAP; static const LayerTypeInfo *layerType_getInfo(int type) { @@ -2501,13 +2491,10 @@ void CustomData_set(const CustomData *data, int index, int type, const void *sou /* BMesh functions */ /* needed to convert to/from different face reps */ -void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata, - int totloop, int totpoly) +void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *ldata, int totloop) { - int i; - for (i = 0; i < fdata->totlayer; i++) { + for (int i = 0; i < fdata->totlayer; i++) { if (fdata->layers[i].type == CD_MTFACE) { - CustomData_add_layer_named(pdata, CD_MTEXPOLY, CD_CALLOC, NULL, totpoly, fdata->layers[i].name); CustomData_add_layer_named(ldata, CD_MLOOPUV, CD_CALLOC, NULL, totloop, fdata->layers[i].name); } else if (fdata->layers[i].type == CD_MCOL) { @@ -2522,19 +2509,18 @@ void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *l } } -void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata, int total) +void CustomData_from_bmeshpoly( + CustomData *fdata, CustomData *ldata, int total) { int i; /* avoid accumulating extra layers */ - BLI_assert(!CustomData_from_bmeshpoly_test(fdata, pdata, ldata, false)); + BLI_assert(!CustomData_from_bmeshpoly_test(fdata, ldata, false)); - for (i = 0; i < pdata->totlayer; i++) { - if (pdata->layers[i].type == CD_MTEXPOLY) { - CustomData_add_layer_named(fdata, CD_MTFACE, CD_CALLOC, NULL, total, pdata->layers[i].name); - } - } for (i = 0; i < ldata->totlayer; i++) { + if (ldata->layers[i].type == CD_MLOOPUV) { + CustomData_add_layer_named(fdata, CD_MTFACE, CD_CALLOC, NULL, total, ldata->layers[i].name); + } if (ldata->layers[i].type == CD_MLOOPCOL) { CustomData_add_layer_named(fdata, CD_MCOL, CD_CALLOC, NULL, total, ldata->layers[i].name); } @@ -2552,7 +2538,7 @@ void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData } } - CustomData_bmesh_update_active_layers(fdata, pdata, ldata); + CustomData_bmesh_update_active_layers(fdata, ldata); } #ifndef NDEBUG @@ -2562,13 +2548,13 @@ void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData * \param fallback: Use when there are no layers to handle, * since callers may expect success or failure. */ -bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *pdata, CustomData *ldata, bool fallback) +bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *ldata, bool fallback) { int a_num = 0, b_num = 0; #define LAYER_CMP(l_a, t_a, l_b, t_b) \ ((a_num += CustomData_number_of_layers(l_a, t_a)) == (b_num += CustomData_number_of_layers(l_b, t_b))) - if (!LAYER_CMP(pdata, CD_MTEXPOLY, fdata, CD_MTFACE)) + if (!LAYER_CMP(ldata, CD_MLOOPUV, fdata, CD_MTFACE)) return false; if (!LAYER_CMP(ldata, CD_MLOOPCOL, fdata, CD_MCOL)) return false; @@ -2590,25 +2576,21 @@ bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *pdata, Custom #endif -void CustomData_bmesh_update_active_layers(CustomData *fdata, CustomData *pdata, CustomData *ldata) +void CustomData_bmesh_update_active_layers(CustomData *fdata, CustomData *ldata) { int act; - if (CustomData_has_layer(pdata, CD_MTEXPOLY)) { - act = CustomData_get_active_layer(pdata, CD_MTEXPOLY); - CustomData_set_layer_active(ldata, CD_MLOOPUV, act); + if (CustomData_has_layer(ldata, CD_MLOOPUV)) { + act = CustomData_get_active_layer(ldata, CD_MLOOPUV); CustomData_set_layer_active(fdata, CD_MTFACE, act); - act = CustomData_get_render_layer(pdata, CD_MTEXPOLY); - CustomData_set_layer_render(ldata, CD_MLOOPUV, act); + act = CustomData_get_render_layer(ldata, CD_MLOOPUV); CustomData_set_layer_render(fdata, CD_MTFACE, act); - act = CustomData_get_clone_layer(pdata, CD_MTEXPOLY); - CustomData_set_layer_clone(ldata, CD_MLOOPUV, act); + act = CustomData_get_clone_layer(ldata, CD_MLOOPUV); CustomData_set_layer_clone(fdata, CD_MTFACE, act); - act = CustomData_get_stencil_layer(pdata, CD_MTEXPOLY); - CustomData_set_layer_stencil(ldata, CD_MLOOPUV, act); + act = CustomData_get_stencil_layer(ldata, CD_MLOOPUV); CustomData_set_layer_stencil(fdata, CD_MTFACE, act); } @@ -2632,25 +2614,21 @@ void CustomData_bmesh_update_active_layers(CustomData *fdata, CustomData *pdata, * used by do_versions in readfile.c when creating pdata and ldata for pre-bmesh * meshes and needed to preserve active/render/clone/stencil flags set in pre-bmesh files */ -void CustomData_bmesh_do_versions_update_active_layers(CustomData *fdata, CustomData *pdata, CustomData *ldata) +void CustomData_bmesh_do_versions_update_active_layers(CustomData *fdata, CustomData *ldata) { int act; if (CustomData_has_layer(fdata, CD_MTFACE)) { act = CustomData_get_active_layer(fdata, CD_MTFACE); - CustomData_set_layer_active(pdata, CD_MTEXPOLY, act); CustomData_set_layer_active(ldata, CD_MLOOPUV, act); act = CustomData_get_render_layer(fdata, CD_MTFACE); - CustomData_set_layer_render(pdata, CD_MTEXPOLY, act); CustomData_set_layer_render(ldata, CD_MLOOPUV, act); act = CustomData_get_clone_layer(fdata, CD_MTFACE); - CustomData_set_layer_clone(pdata, CD_MTEXPOLY, act); CustomData_set_layer_clone(ldata, CD_MLOOPUV, act); act = CustomData_get_stencil_layer(fdata, CD_MTFACE); - CustomData_set_layer_stencil(pdata, CD_MTEXPOLY, act); CustomData_set_layer_stencil(ldata, CD_MLOOPUV, act); } diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c index 3bc09c0173b..00b8063110d 100644 --- a/source/blender/blenkernel/intern/data_transfer.c +++ b/source/blender/blenkernel/intern/data_transfer.c @@ -79,7 +79,7 @@ CustomDataMask BKE_object_data_transfer_dttypes_to_cdmask(const int dtdata_types cddata_mask |= CD_MASK_MDEFORMVERT; /* Exception for vgroups :/ */ } else if (cddata_type == CD_FAKE_UV) { - cddata_mask |= CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV; + cddata_mask |= CD_MASK_MLOOPUV; } else if (cddata_type == CD_FAKE_LNOR) { cddata_mask |= CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL; @@ -962,7 +962,7 @@ static bool data_transfer_layersmapping_generate( } else if (elem_type == ME_POLY) { if (cddata_type == CD_FAKE_UV) { - cddata_type = CD_MTEXPOLY; + cddata_type = CD_MLOOPUV; } if (!(cddata_type & CD_FAKE)) { @@ -1010,7 +1010,8 @@ static bool data_transfer_layersmapping_generate( * to get (as much as possible) exact copy of source data layout. */ void BKE_object_data_transfer_layout( - Scene *scene, Object *ob_src, Object *ob_dst, const int data_types, const bool use_delete, + const struct EvaluationContext *eval_ctx, Scene *scene, + Object *ob_src, Object *ob_dst, const int data_types, const bool use_delete, const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX]) { DerivedMesh *dm_src; @@ -1027,7 +1028,7 @@ void BKE_object_data_transfer_layout( /* Get source DM.*/ dm_src_mask |= BKE_object_data_transfer_dttypes_to_cdmask(data_types); - dm_src = mesh_get_derived_final(scene, ob_src, dm_src_mask); + dm_src = mesh_get_derived_final(eval_ctx, scene, ob_src, dm_src_mask); if (!dm_src) { return; } @@ -1085,9 +1086,9 @@ void BKE_object_data_transfer_layout( } bool BKE_object_data_transfer_dm( - Scene *scene, Object *ob_src, Object *ob_dst, DerivedMesh *dm_dst, const int data_types, bool use_create, - const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode, - SpaceTransform *space_transform, const bool auto_transform, + const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob_src, Object *ob_dst, DerivedMesh *dm_dst, + const int data_types, bool use_create, const int map_vert_mode, const int map_edge_mode, + const int map_loop_mode, const int map_poly_mode, SpaceTransform *space_transform, const bool auto_transform, const float max_distance, const float ray_radius, const float islands_handling_precision, const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX], const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup, @@ -1149,7 +1150,7 @@ bool BKE_object_data_transfer_dm( * Also, we need to make a local copy of dm_src, otherwise we may end with concurrent creation * of data in it (multi-threaded evaluation of the modifier stack, see T46672). */ - dm_src = dm_dst ? ob_src->derivedFinal : mesh_get_derived_final(scene, ob_src, dm_src_mask); + dm_src = dm_dst ? ob_src->derivedFinal : mesh_get_derived_final(eval_ctx, scene, ob_src, dm_src_mask); if (!dm_src) { return changed; } @@ -1457,16 +1458,16 @@ bool BKE_object_data_transfer_dm( } bool BKE_object_data_transfer_mesh( - Scene *scene, Object *ob_src, Object *ob_dst, const int data_types, const bool use_create, - const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode, - SpaceTransform *space_transform, const bool auto_transform, + const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob_src, Object *ob_dst, const int data_types, + const bool use_create, const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, + const int map_poly_mode, SpaceTransform *space_transform, const bool auto_transform, const float max_distance, const float ray_radius, const float islands_handling_precision, const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX], const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup, ReportList *reports) { return BKE_object_data_transfer_dm( - scene, ob_src, ob_dst, NULL, data_types, use_create, + eval_ctx, scene, ob_src, ob_dst, NULL, data_types, use_create, map_vert_mode, map_edge_mode, map_loop_mode, map_poly_mode, space_transform, auto_transform, max_distance, ray_radius, islands_handling_precision, diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 22ff8bf4bb7..d4ff9bd5c0c 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -54,6 +54,7 @@ #include "BKE_customdata.h" #include "BKE_data_transfer.h" #include "BKE_deform.h" /* own include */ +#include "BKE_mesh.h" #include "BKE_mesh_mapping.h" #include "BKE_object_deform.h" @@ -73,6 +74,8 @@ bDeformGroup *BKE_defgroup_new(Object *ob, const char *name) BLI_addtail(&ob->defbase, defgroup); defgroup_unique_name(defgroup, ob); + BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL); + return defgroup; } diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c deleted file mode 100644 index 149158b9f5d..00000000000 --- a/source/blender/blenkernel/intern/depsgraph.c +++ /dev/null @@ -1,3739 +0,0 @@ -/* - * ***** 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) 2004 Blender Foundation. - * All rights reserved. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/blenkernel/intern/depsgraph.c - * \ingroup bke - */ - - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <math.h> - -#include "MEM_guardedalloc.h" - -#ifdef WIN32 -# include "BLI_winstuff.h" -#endif - -#include "BLI_utildefines.h" -#include "BLI_listbase.h" -#include "BLI_ghash.h" -#include "BLI_threads.h" - -#include "DNA_anim_types.h" -#include "DNA_camera_types.h" -#include "DNA_cachefile_types.h" -#include "DNA_group_types.h" -#include "DNA_lamp_types.h" -#include "DNA_lattice_types.h" -#include "DNA_key_types.h" -#include "DNA_material_types.h" -#include "DNA_mesh_types.h" -#include "DNA_node_types.h" -#include "DNA_scene_types.h" -#include "DNA_screen_types.h" -#include "DNA_windowmanager_types.h" -#include "DNA_movieclip_types.h" -#include "DNA_mask_types.h" -#include "DNA_modifier_types.h" -#include "DNA_rigidbody_types.h" - -#include "BKE_anim.h" -#include "BKE_animsys.h" -#include "BKE_action.h" -#include "BKE_DerivedMesh.h" -#include "BKE_collision.h" -#include "BKE_curve.h" -#include "BKE_effect.h" -#include "BKE_fcurve.h" -#include "BKE_global.h" -#include "BKE_idcode.h" -#include "BKE_image.h" -#include "BKE_key.h" -#include "BKE_library.h" -#include "BKE_main.h" -#include "BKE_node.h" -#include "BKE_material.h" -#include "BKE_mball.h" -#include "BKE_modifier.h" -#include "BKE_object.h" -#include "BKE_paint.h" -#include "BKE_particle.h" -#include "BKE_pointcache.h" -#include "BKE_scene.h" -#include "BKE_screen.h" -#include "BKE_tracking.h" - -#include "GPU_buffers.h" - -#include "atomic_ops.h" - -#include "depsgraph_private.h" - -#include "DEG_depsgraph.h" -#include "DEG_depsgraph_build.h" -#include "DEG_depsgraph_debug.h" -#include "DEG_depsgraph_query.h" - -#ifdef WITH_LEGACY_DEPSGRAPH - -static SpinLock threaded_update_lock; - -void DAG_init(void) -{ - BLI_spin_init(&threaded_update_lock); - DEG_register_node_types(); -} - -void DAG_exit(void) -{ - BLI_spin_end(&threaded_update_lock); - DEG_free_node_types(); -} - -/* Queue and stack operations for dag traversal - * - * the queue store a list of freenodes to avoid successive alloc/dealloc - */ - -DagNodeQueue *queue_create(int slots) -{ - DagNodeQueue *queue; - DagNodeQueueElem *elem; - int i; - - queue = MEM_mallocN(sizeof(DagNodeQueue), "DAG queue"); - queue->freenodes = MEM_mallocN(sizeof(DagNodeQueue), "DAG queue"); - queue->count = 0; - queue->maxlevel = 0; - queue->first = queue->last = NULL; - elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem3"); - elem->node = NULL; - elem->next = NULL; - queue->freenodes->first = queue->freenodes->last = elem; - - for (i = 1; i < slots; i++) { - elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem4"); - elem->node = NULL; - elem->next = NULL; - queue->freenodes->last->next = elem; - queue->freenodes->last = elem; - } - queue->freenodes->count = slots; - return queue; -} - -void queue_raz(DagNodeQueue *queue) -{ - DagNodeQueueElem *elem; - - elem = queue->first; - if (queue->freenodes->last) - queue->freenodes->last->next = elem; - else - queue->freenodes->first = queue->freenodes->last = elem; - - elem->node = NULL; - queue->freenodes->count++; - while (elem->next) { - elem = elem->next; - elem->node = NULL; - queue->freenodes->count++; - } - queue->freenodes->last = elem; - queue->count = 0; -} - -void queue_delete(DagNodeQueue *queue) -{ - DagNodeQueueElem *elem; - DagNodeQueueElem *temp; - - elem = queue->first; - while (elem) { - temp = elem; - elem = elem->next; - MEM_freeN(temp); - } - - elem = queue->freenodes->first; - while (elem) { - temp = elem; - elem = elem->next; - MEM_freeN(temp); - } - - MEM_freeN(queue->freenodes); - MEM_freeN(queue); -} - -/* insert in queue, remove in front */ -void push_queue(DagNodeQueue *queue, DagNode *node) -{ - DagNodeQueueElem *elem; - int i; - - if (node == NULL) { - fprintf(stderr, "pushing null node\n"); - return; - } - /*fprintf(stderr, "BFS push : %s %d\n", ((ID *) node->ob)->name, queue->count);*/ - - elem = queue->freenodes->first; - if (elem != NULL) { - queue->freenodes->first = elem->next; - if (queue->freenodes->last == elem) { - queue->freenodes->last = NULL; - queue->freenodes->first = NULL; - } - queue->freenodes->count--; - } - else { /* alllocating more */ - elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem1"); - elem->node = NULL; - elem->next = NULL; - queue->freenodes->first = queue->freenodes->last = elem; - - for (i = 1; i < DAGQUEUEALLOC; i++) { - elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem2"); - elem->node = NULL; - elem->next = NULL; - queue->freenodes->last->next = elem; - queue->freenodes->last = elem; - } - queue->freenodes->count = DAGQUEUEALLOC; - - elem = queue->freenodes->first; - queue->freenodes->first = elem->next; - } - elem->next = NULL; - elem->node = node; - if (queue->last != NULL) - queue->last->next = elem; - queue->last = elem; - if (queue->first == NULL) { - queue->first = elem; - } - queue->count++; -} - - -/* insert in front, remove in front */ -void push_stack(DagNodeQueue *queue, DagNode *node) -{ - DagNodeQueueElem *elem; - int i; - - elem = queue->freenodes->first; - if (elem != NULL) { - queue->freenodes->first = elem->next; - if (queue->freenodes->last == elem) { - queue->freenodes->last = NULL; - queue->freenodes->first = NULL; - } - queue->freenodes->count--; - } - else { /* alllocating more */ - elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem1"); - elem->node = NULL; - elem->next = NULL; - queue->freenodes->first = queue->freenodes->last = elem; - - for (i = 1; i < DAGQUEUEALLOC; i++) { - elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem2"); - elem->node = NULL; - elem->next = NULL; - queue->freenodes->last->next = elem; - queue->freenodes->last = elem; - } - queue->freenodes->count = DAGQUEUEALLOC; - - elem = queue->freenodes->first; - queue->freenodes->first = elem->next; - } - elem->next = queue->first; - elem->node = node; - queue->first = elem; - if (queue->last == NULL) - queue->last = elem; - queue->count++; -} - - -DagNode *pop_queue(DagNodeQueue *queue) -{ - DagNodeQueueElem *elem; - DagNode *node; - - elem = queue->first; - if (elem) { - queue->first = elem->next; - if (queue->last == elem) { - queue->last = NULL; - queue->first = NULL; - } - queue->count--; - if (queue->freenodes->last) - queue->freenodes->last->next = elem; - queue->freenodes->last = elem; - if (queue->freenodes->first == NULL) - queue->freenodes->first = elem; - node = elem->node; - elem->node = NULL; - elem->next = NULL; - queue->freenodes->count++; - return node; - } - else { - fprintf(stderr, "return null\n"); - return NULL; - } -} - -DagNode *get_top_node_queue(DagNodeQueue *queue) -{ - return queue->first->node; -} - -DagForest *dag_init(void) -{ - DagForest *forest; - /* use callocN to init all zero */ - forest = MEM_callocN(sizeof(DagForest), "DAG root"); - forest->ugly_hack_sorry = true; - return forest; -} - -/* isdata = object data... */ -/* XXX this needs to be extended to be more flexible (so that not only objects are evaluated via depsgraph)... */ -static void dag_add_driver_relation(AnimData *adt, DagForest *dag, DagNode *node, int isdata) -{ - FCurve *fcu; - DagNode *node1; - - for (fcu = adt->drivers.first; fcu; fcu = fcu->next) { - ChannelDriver *driver = fcu->driver; - DriverVar *dvar; - int isdata_fcu = (isdata) || (fcu->rna_path && strstr(fcu->rna_path, "modifiers[")); - - /* loop over variables to get the target relationships */ - for (dvar = driver->variables.first; dvar; dvar = dvar->next) { - /* only used targets */ - DRIVER_TARGETS_USED_LOOPER(dvar) - { - if (dtar->id) { - /* FIXME: other data types need to be added here so that they can work! */ - if (GS(dtar->id->name) == ID_OB) { - Object *ob = (Object *)dtar->id; - - /* normal channel-drives-channel */ - node1 = dag_get_node(dag, dtar->id); - - /* check if bone... */ - if ((ob->type == OB_ARMATURE) && - ( ((dtar->rna_path) && strstr(dtar->rna_path, "pose.bones[")) || - ((dtar->flag & DTAR_FLAG_STRUCT_REF) && (dtar->pchan_name[0])) )) - { - dag_add_relation(dag, node1, node, isdata_fcu ? DAG_RL_DATA_DATA : DAG_RL_DATA_OB, "Driver"); - } - /* check if ob data */ - else if (dtar->rna_path && strstr(dtar->rna_path, "data.")) - dag_add_relation(dag, node1, node, isdata_fcu ? DAG_RL_DATA_DATA : DAG_RL_DATA_OB, "Driver"); - /* normal */ - else - dag_add_relation(dag, node1, node, isdata_fcu ? DAG_RL_OB_DATA : DAG_RL_OB_OB, "Driver"); - } - } - } - DRIVER_TARGETS_LOOPER_END - } - } -} - -/* XXX: forward def for material driver handling... */ -static void dag_add_material_driver_relations(DagForest *dag, DagNode *node, Material *ma); - -/* recursive handling for shader nodetree drivers */ -static void dag_add_shader_nodetree_driver_relations(DagForest *dag, DagNode *node, bNodeTree *ntree) -{ - bNode *n; - - /* nodetree itself */ - if (ntree->adt) { - dag_add_driver_relation(ntree->adt, dag, node, 1); - } - - /* nodetree's nodes... */ - for (n = ntree->nodes.first; n; n = n->next) { - if (n->id) { - if (GS(n->id->name) == ID_MA) { - dag_add_material_driver_relations(dag, node, (Material *)n->id); - } - else if (n->type == NODE_GROUP) { - dag_add_shader_nodetree_driver_relations(dag, node, (bNodeTree *)n->id); - } - } - } -} - -/* recursive handling for material drivers */ -static void dag_add_material_driver_relations(DagForest *dag, DagNode *node, Material *ma) -{ - /* Prevent infinite recursion by checking (and tagging the material) as having been visited - * already (see build_dag()). This assumes ma->id.tag & LIB_TAG_DOIT isn't set by anything else - * in the meantime... [#32017] - */ - if (ma->id.tag & LIB_TAG_DOIT) - return; - - ma->id.tag |= LIB_TAG_DOIT; - - /* material itself */ - if (ma->adt) - dag_add_driver_relation(ma->adt, dag, node, 1); - - /* textures */ - // TODO... - //dag_add_texture_driver_relations(DagForest *dag, DagNode *node, ID *id); - - /* material's nodetree */ - if (ma->nodetree) - dag_add_shader_nodetree_driver_relations(dag, node, ma->nodetree); - - ma->id.tag &= ~LIB_TAG_DOIT; -} - -/* recursive handling for lamp drivers */ -static void dag_add_lamp_driver_relations(DagForest *dag, DagNode *node, Lamp *la) -{ - /* Prevent infinite recursion by checking (and tagging the lamp) as having been visited - * already (see build_dag()). This assumes la->id.tag & LIB_TAG_DOIT isn't set by anything else - * in the meantime... [#32017] - */ - if (la->id.tag & LIB_TAG_DOIT) - return; - - la->id.tag |= LIB_TAG_DOIT; - - /* lamp itself */ - if (la->adt) - dag_add_driver_relation(la->adt, dag, node, 1); - - /* textures */ - // TODO... - //dag_add_texture_driver_relations(DagForest *dag, DagNode *node, ID *id); - - /* lamp's nodetree */ - if (la->nodetree) - dag_add_shader_nodetree_driver_relations(dag, node, la->nodetree); - - la->id.tag &= ~LIB_TAG_DOIT; -} - -static void create_collision_relation(DagForest *dag, DagNode *node, Object *ob1, const char *name) -{ - DagNode *node2 = dag_get_node(dag, ob1); - dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, name); -} - -void dag_add_collision_relations(DagForest *dag, Scene *scene, Object *ob, DagNode *node, Group *group, int layer, unsigned int modifier_type, DagCollobjFilterFunction fn, bool dupli, const char *name) -{ - unsigned int numcollobj; - Object **collobjs = get_collisionobjects_ext(scene, ob, group, layer, &numcollobj, modifier_type, dupli); - - for (unsigned int i = 0; i < numcollobj; i++) { - Object *ob1 = collobjs[i]; - - if (!fn || fn(ob1, modifiers_findByType(ob1, modifier_type))) { - create_collision_relation(dag, node, ob1, name); - } - } - - if (collobjs) - MEM_freeN(collobjs); -} - -void dag_add_forcefield_relations(DagForest *dag, Scene *scene, Object *ob, DagNode *node, EffectorWeights *effector_weights, bool add_absorption, int skip_forcefield, const char *name) -{ - ListBase *effectors = pdInitEffectors(scene, ob, NULL, effector_weights, false); - - if (effectors) { - for (EffectorCache *eff = effectors->first; eff; eff = eff->next) { - if (eff->ob != ob && eff->pd->forcefield != skip_forcefield) { - create_collision_relation(dag, node, eff->ob, name); - - if (eff->pd->forcefield == PFIELD_SMOKEFLOW && eff->pd->f_source) { - create_collision_relation(dag, node, eff->pd->f_source, "Smoke Force Domain"); - } - - if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) { - /* Actual code uses get_collider_cache */ - dag_add_collision_relations(dag, scene, ob, node, NULL, eff->ob->lay, eModifierType_Collision, NULL, true, "Force Absorption"); - } - } - } - } - - pdEndEffectors(&effectors); -} - -static bool build_deg_tracking_constraints(DagForest *dag, - Scene *scene, - DagNode *scenenode, - bConstraint *con, - const bConstraintTypeInfo *cti, - DagNode *node, - bool is_data) -{ - if (!ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, - CONSTRAINT_TYPE_CAMERASOLVER, - CONSTRAINT_TYPE_OBJECTSOLVER)) - { - return false; - } - bool depends_on_camera = false; - if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) { - bFollowTrackConstraint *data = (bFollowTrackConstraint *)con->data; - if ((data->clip || data->flag & FOLLOWTRACK_ACTIVECLIP) && data->track[0]) { - depends_on_camera = true; - } - if (data->depth_ob != NULL) { - DagNode *node2 = dag_get_node(dag, data->depth_ob); - dag_add_relation(dag, - node2, node, - (is_data) ? (DAG_RL_DATA_DATA | DAG_RL_OB_DATA) - : (DAG_RL_DATA_OB | DAG_RL_OB_OB), - cti->name); - } - } - else if (cti->type == CONSTRAINT_TYPE_OBJECTSOLVER) { - depends_on_camera = true; - } - if (depends_on_camera && scene->camera != NULL) { - DagNode *node2 = dag_get_node(dag, scene->camera); - dag_add_relation(dag, - node2, node, - (is_data) ? (DAG_RL_DATA_DATA | DAG_RL_OB_DATA) - : (DAG_RL_DATA_OB | DAG_RL_OB_OB), - cti->name); - } - dag_add_relation(dag, scenenode, node, DAG_RL_SCENE, "Scene Relation"); - return true; -} - -static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Scene *scene, Object *ob, int mask) -{ - bConstraint *con; - DagNode *node; - DagNode *node2; - DagNode *node3; - Key *key; - ParticleSystem *psys; - int addtoroot = 1; - - node = dag_get_node(dag, ob); - - if ((ob->data) && (mask & DAG_RL_DATA)) { - node2 = dag_get_node(dag, ob->data); - dag_add_relation(dag, node, node2, DAG_RL_DATA, "Object-Data Relation"); - node2->first_ancestor = ob; - node2->ancestor_count += 1; - } - - /* also build a custom data mask for dependencies that need certain layers */ - - if (ob->type == OB_ARMATURE) { - if (ob->pose) { - bPoseChannel *pchan; - - for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) { - for (con = pchan->constraints.first; con; con = con->next) { - const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); - ListBase targets = {NULL, NULL}; - bConstraintTarget *ct; - - if (!cti) { - continue; - } - - if (build_deg_tracking_constraints(dag, scene, scenenode, con, cti, node, true)) { - /* pass */ - } - else if (cti->get_constraint_targets) { - cti->get_constraint_targets(con, &targets); - - for (ct = targets.first; ct; ct = ct->next) { - if (ct->tar && ct->tar != ob) { - // fprintf(stderr, "armature %s target :%s\n", ob->id.name, target->id.name); - node3 = dag_get_node(dag, ct->tar); - - if (ct->subtarget[0]) { - dag_add_relation(dag, node3, node, DAG_RL_OB_DATA | DAG_RL_DATA_DATA, cti->name); - if (ct->tar->type == OB_MESH) - node3->customdata_mask |= CD_MASK_MDEFORMVERT; - } - else if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, - CONSTRAINT_TYPE_CLAMPTO, - CONSTRAINT_TYPE_SPLINEIK, - CONSTRAINT_TYPE_SHRINKWRAP)) - { - dag_add_relation(dag, node3, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, cti->name); - } - else { - dag_add_relation(dag, node3, node, DAG_RL_OB_DATA, cti->name); - } - } - } - - if (cti->flush_constraint_targets) - cti->flush_constraint_targets(con, &targets, 1); - } - - } - } - } - } - - /* driver dependencies, nla modifiers */ -#if 0 // XXX old animation system - if (ob->nlastrips.first) { - bActionStrip *strip; - bActionChannel *chan; - for (strip = ob->nlastrips.first; strip; strip = strip->next) { - if (strip->modifiers.first) { - bActionModifier *amod; - for (amod = strip->modifiers.first; amod; amod = amod->next) { - if (amod->ob) { - node2 = dag_get_node(dag, amod->ob); - dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "NLA Strip Modifier"); - } - } - } - } - } -#endif // XXX old animation system - if (ob->adt) - dag_add_driver_relation(ob->adt, dag, node, (ob->type == OB_ARMATURE)); // XXX isdata arg here doesn't give an accurate picture of situation - - key = BKE_key_from_object(ob); - if (key && key->adt) - dag_add_driver_relation(key->adt, dag, node, 1); - - if (ob->modifiers.first) { - ModifierData *md; - - for (md = ob->modifiers.first; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); - - if (mti->updateDepgraph) mti->updateDepgraph(md, dag, bmain, scene, ob, node); - } - } - if (ob->parent) { - node2 = dag_get_node(dag, ob->parent); - - switch (ob->partype) { - case PARSKEL: - dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_OB, "Parent"); - break; - case PARVERT1: case PARVERT3: - dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, "Vertex Parent"); - node2->customdata_mask |= CD_MASK_ORIGINDEX; - break; - case PARBONE: - dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, "Bone Parent"); - break; - default: - if (ob->parent->type == OB_LATTICE) - dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_OB, "Lattice Parent"); - else if (ob->parent->type == OB_CURVE) { - Curve *cu = ob->parent->data; - if (cu->flag & CU_PATH) - dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, "Curve Parent"); - else - dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Curve Parent"); - } - else - dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Parent"); - break; - } - /* exception case: parent is duplivert */ - if (ob->type == OB_MBALL && (ob->parent->transflag & OB_DUPLIVERTS)) { - dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_OB, "Duplivert"); - } - - addtoroot = 0; - } - if (ob->proxy) { - node2 = dag_get_node(dag, ob->proxy); - dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA | DAG_RL_OB_OB, "Proxy"); - /* inverted relation, so addtoroot shouldn't be set to zero */ - } - - if (ob->transflag & OB_DUPLI) { - if ((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) { - GroupObject *go; - for (go = ob->dup_group->gobject.first; go; go = go->next) { - if (go->ob) { - node2 = dag_get_node(dag, go->ob); - /* node2 changes node1, this keeps animations updated in groups?? not logical? */ - dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Dupligroup"); - } - } - } - } - - /* rigidbody force fields */ - if ((ob->type == OB_MESH) || (ob->type == OB_CURVE) || (ob->type == OB_LATTICE)) { - if (ob->rigidbody_object && scene->rigidbody_world) { - dag_add_forcefield_relations(dag, scene, ob, node, scene->rigidbody_world->effector_weights, true, 0, "Force Field"); - } - } - - /* object data drivers */ - if (ob->data) { - AnimData *adt = BKE_animdata_from_id((ID *)ob->data); - if (adt) - dag_add_driver_relation(adt, dag, node, 1); - } - - /* object type/data relationships */ - switch (ob->type) { - case OB_CAMERA: - { - Camera *cam = (Camera *)ob->data; - - if (cam->dof_ob) { - node2 = dag_get_node(dag, cam->dof_ob); - dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Camera DoF"); - } - break; - } - case OB_MBALL: - { - Object *mom = BKE_mball_basis_find(scene, ob); - - if (mom != ob) { - node2 = dag_get_node(dag, mom); - dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Metaball"); /* mom depends on children! */ - } - break; - } - case OB_CURVE: - case OB_FONT: - { - Curve *cu = ob->data; - - if (cu->bevobj) { - node2 = dag_get_node(dag, cu->bevobj); - dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Curve Bevel"); - } - if (cu->taperobj) { - node2 = dag_get_node(dag, cu->taperobj); - dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Curve Taper"); - } - if (ob->type == OB_FONT) { - /* Really rather dirty hack. needs to support font family to work - * reliably on render export. - * - * This totally mimics behavior of regular verts duplication with - * parenting. The only tricky thing here is to get list of objects - * used for the custom "font". - * - * This shouldn't harm so much because this code only runs on DAG - * rebuild and this feature is not that commonly used. - * - * - sergey - - */ - if (cu->family[0] != '\n') { - ListBase *duplilist; - DupliObject *dob; - duplilist = object_duplilist(G.main->eval_ctx, scene, ob); - for (dob = duplilist->first; dob; dob = dob->next) { - node2 = dag_get_node(dag, dob->ob); - dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Object Font"); - } - free_object_duplilist(duplilist); - } - - if (cu->textoncurve) { - node2 = dag_get_node(dag, cu->textoncurve); - /* Text on curve requires path to be evaluated for the target curve. */ - node2->eval_flags |= DAG_EVAL_NEED_CURVE_PATH; - dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Texture On Curve"); - } - } - break; - } - } - - /* material drivers */ - if (ob->totcol) { - int a; - - for (a = 1; a <= ob->totcol; a++) { - Material *ma = give_current_material(ob, a); - - if (ma) { - /* recursively figure out if there are drivers, and hook these up to this object */ - dag_add_material_driver_relations(dag, node, ma); - } - } - } - else if (ob->type == OB_LAMP) { - dag_add_lamp_driver_relations(dag, node, ob->data); - } - - /* particles */ - psys = ob->particlesystem.first; - if (psys) { - GroupObject *go; - - for (; psys; psys = psys->next) { - BoidRule *rule = NULL; - BoidState *state = NULL; - ParticleSettings *part = psys->part; - - if (part->adt) { - dag_add_driver_relation(part->adt, dag, node, 1); - } - - dag_add_relation(dag, node, node, DAG_RL_OB_DATA, "Particle-Object Relation"); - - if (!psys_check_enabled(ob, psys, G.is_rendering)) - continue; - - if (ELEM(part->phystype, PART_PHYS_KEYED, PART_PHYS_BOIDS)) { - ParticleTarget *pt = psys->targets.first; - - for (; pt; pt = pt->next) { - if (pt->ob && BLI_findlink(&pt->ob->particlesystem, pt->psys - 1)) { - node2 = dag_get_node(dag, pt->ob); - dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Particle Targets"); - } - } - } - - if (part->ren_as == PART_DRAW_OB && part->dup_ob) { - node2 = dag_get_node(dag, part->dup_ob); - /* note that this relation actually runs in the wrong direction, the problem - * is that dupli system all have this (due to parenting), and the render - * engine instancing assumes particular ordering of objects in list */ - dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Object Visualization"); - if (part->dup_ob->type == OB_MBALL) - dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Object Visualization"); - } - - if (part->ren_as == PART_DRAW_GR && part->dup_group) { - for (go = part->dup_group->gobject.first; go; go = go->next) { - node2 = dag_get_node(dag, go->ob); - dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Particle Group Visualization"); - } - } - - if (part->type != PART_HAIR) { - /* Actual code uses get_collider_cache */ - dag_add_collision_relations(dag, scene, ob, node, part->collision_group, ob->lay, eModifierType_Collision, NULL, true, "Particle Collision"); - } - else if ((psys->flag & PSYS_HAIR_DYNAMICS) && psys->clmd && psys->clmd->coll_parms) { - /* Hair uses cloth simulation, i.e. get_collision_objects */ - dag_add_collision_relations(dag, scene, ob, node, psys->clmd->coll_parms->group, ob->lay | scene->lay, eModifierType_Collision, NULL, true, "Hair Collision"); - } - - dag_add_forcefield_relations(dag, scene, ob, node, part->effector_weights, part->type == PART_HAIR, 0, "Particle Force Field"); - - if (part->boids) { - for (state = part->boids->states.first; state; state = state->next) { - for (rule = state->rules.first; rule; rule = rule->next) { - Object *ruleob = NULL; - if (rule->type == eBoidRuleType_Avoid) - ruleob = ((BoidRuleGoalAvoid *)rule)->ob; - else if (rule->type == eBoidRuleType_FollowLeader) - ruleob = ((BoidRuleFollowLeader *)rule)->ob; - - if (ruleob) { - node2 = dag_get_node(dag, ruleob); - dag_add_relation(dag, node2, node, DAG_RL_OB_DATA, "Boid Rule"); - } - } - } - } - } - } - - /* object constraints */ - for (con = ob->constraints.first; con; con = con->next) { - const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); - ListBase targets = {NULL, NULL}; - bConstraintTarget *ct; - - if (!cti) - continue; - - /* special case for camera tracking -- it doesn't use targets to define relations */ - if (build_deg_tracking_constraints(dag, scene, scenenode, con, cti, node, false)) { - addtoroot = 0; - } - else if (cti->get_constraint_targets) { - cti->get_constraint_targets(con, &targets); - - for (ct = targets.first; ct; ct = ct->next) { - Object *obt; - - if (ct->tar) - obt = ct->tar; - else - continue; - - node2 = dag_get_node(dag, obt); - if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO)) - dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, cti->name); - else { - if (ELEM(obt->type, OB_ARMATURE, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) { - dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, cti->name); - if (obt->type == OB_MESH) - node2->customdata_mask |= CD_MASK_MDEFORMVERT; - } - else if (cti->type == CONSTRAINT_TYPE_SHRINKWRAP) { - dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, cti->name); - } - else { - dag_add_relation(dag, node2, node, DAG_RL_OB_OB, cti->name); - } - } - addtoroot = 0; - } - - if (cti->flush_constraint_targets) - cti->flush_constraint_targets(con, &targets, 1); - } - } - - if (addtoroot == 1) - dag_add_relation(dag, scenenode, node, DAG_RL_SCENE, "Scene Relation"); -} - -static void build_dag_group(DagForest *dag, DagNode *scenenode, Main *bmain, Scene *scene, Group *group, short mask) -{ - GroupObject *go; - - if (group->id.tag & LIB_TAG_DOIT) - return; - - group->id.tag |= LIB_TAG_DOIT; - - for (go = group->gobject.first; go; go = go->next) { - build_dag_object(dag, scenenode, bmain, scene, go->ob, mask); - if (go->ob->dup_group) - build_dag_group(dag, scenenode, bmain, scene, go->ob->dup_group, mask); - } -} - -DagForest *build_dag(Main *bmain, Scene *sce, short mask) -{ - Base *base; - Object *ob; - DagNode *node; - DagNode *scenenode; - DagForest *dag; - DagAdjList *itA; - - dag = sce->theDag; - if (dag) - free_forest(dag); - else { - dag = dag_init(); - sce->theDag = dag; - } - dag->need_update = false; - - BKE_main_id_tag_idcode(bmain, ID_OB, LIB_TAG_DOIT, false); - - /* clear "LIB_TAG_DOIT" flag from all materials, to prevent infinite recursion problems later [#32017] */ - BKE_main_id_tag_idcode(bmain, ID_MA, LIB_TAG_DOIT, false); - BKE_main_id_tag_idcode(bmain, ID_LA, LIB_TAG_DOIT, false); - BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false); - - /* add base node for scene. scene is always the first node in DAG */ - scenenode = dag_add_node(dag, sce); - - /* add current scene objects */ - for (base = sce->base.first; base; base = base->next) { - ob = base->object; - ob->id.tag |= LIB_TAG_DOIT; - build_dag_object(dag, scenenode, bmain, sce, ob, mask); - if (ob->proxy) - build_dag_object(dag, scenenode, bmain, sce, ob->proxy, mask); - if (ob->dup_group) - build_dag_group(dag, scenenode, bmain, sce, ob->dup_group, mask); - } - - /* There might be situations when object from current scene depends on - * objects form other scene AND objects from other scene has own - * dependencies on objects from other scene. - * - * This is really important to include such indirect dependencies in order - * to keep threaded update safe but since we don't really know if object is - * coming from current scene or another scene we do rather stupid tag-based - * check here: all the objects for which build_dag_object() was called are - * getting tagged with LIB_TAG_DOIT. This way if some node has untagged - * object we know it's an object from other scene. - * - * It should be enough to to it once, because if there's longer chain of - * indirect dependencies, all the new nodes will be added to the end of the - * list, meaning we'll keep covering them in this for loop. - */ - for (node = sce->theDag->DagNode.first; node != NULL; node = node->next) { - if (node->type == ID_OB) { - ob = node->ob; - if ((ob->id.tag & LIB_TAG_DOIT) == 0) { - ob->id.tag |= LIB_TAG_DOIT; - build_dag_object(dag, scenenode, bmain, sce, ob, mask); - if (ob->proxy) - build_dag_object(dag, scenenode, bmain, sce, ob->proxy, mask); - if (ob->dup_group) - build_dag_group(dag, scenenode, bmain, sce, ob->dup_group, mask); - } - } - } - - BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false); - - /* Now all relations were built, but we need to solve 1 exceptional case; - * When objects have multiple "parents" (for example parent + constraint working on same object) - * the relation type has to be synced. One of the parents can change, and should give same event to child */ - - /* nodes were callocced, so we can use node->color for temporal storage */ - for (node = sce->theDag->DagNode.first; node; node = node->next) { - if (node->type == ID_OB) { - for (itA = node->child; itA; itA = itA->next) { - if (itA->node->type == ID_OB) { - itA->node->color |= itA->type; - } - } - - /* also flush custom data mask */ - ((Object *)node->ob)->customdata_mask = node->customdata_mask; - - if (node->parent == NULL) { - dag_add_relation(dag, scenenode, node, DAG_RL_SCENE, "Scene Relation"); - } - } - } - /* now set relations equal, so that when only one parent changes, the correct recalcs are found */ - for (node = sce->theDag->DagNode.first; node; node = node->next) { - if (node->type == ID_OB) { - for (itA = node->child; itA; itA = itA->next) { - if (itA->node->type == ID_OB) { - itA->type |= itA->node->color; - } - } - } - } - - /* cycle detection and solving */ - // solve_cycles(dag); - - return dag; -} - - -void free_forest(DagForest *Dag) -{ /* remove all nodes and deps */ - DagNode *tempN; - DagAdjList *tempA; - DagAdjList *itA; - DagNode *itN = Dag->DagNode.first; - - while (itN) { - itA = itN->child; - while (itA) { - tempA = itA; - itA = itA->next; - MEM_freeN(tempA); - } - - itA = itN->parent; - while (itA) { - tempA = itA; - itA = itA->next; - MEM_freeN(tempA); - } - - tempN = itN; - itN = itN->next; - MEM_freeN(tempN); - } - - BLI_ghash_free(Dag->nodeHash, NULL, NULL); - Dag->nodeHash = NULL; - Dag->DagNode.first = NULL; - Dag->DagNode.last = NULL; - Dag->numNodes = 0; - -} - -DagNode *dag_find_node(DagForest *forest, void *fob) -{ - if (forest->nodeHash) - return BLI_ghash_lookup(forest->nodeHash, fob); - - return NULL; -} - -static int dag_print_dependencies = 0; /* debugging */ - -/* no checking of existence, use dag_find_node first or dag_get_node */ -DagNode *dag_add_node(DagForest *forest, void *fob) -{ - DagNode *node; - - node = MEM_callocN(sizeof(DagNode), "DAG node"); - if (node) { - node->ob = fob; - node->color = DAG_WHITE; - - if (forest->ugly_hack_sorry) node->type = GS(((ID *) fob)->name); /* sorry, done for pose sorting */ - if (forest->numNodes) { - ((DagNode *) forest->DagNode.last)->next = node; - forest->DagNode.last = node; - forest->numNodes++; - } - else { - forest->DagNode.last = node; - forest->DagNode.first = node; - forest->numNodes = 1; - } - - if (!forest->nodeHash) - forest->nodeHash = BLI_ghash_ptr_new("dag_add_node gh"); - BLI_ghash_insert(forest->nodeHash, fob, node); - } - - return node; -} - -DagNode *dag_get_node(DagForest *forest, void *fob) -{ - DagNode *node; - - node = dag_find_node(forest, fob); - if (!node) - node = dag_add_node(forest, fob); - return node; -} - - - -DagNode *dag_get_sub_node(DagForest *forest, void *fob) -{ - DagNode *node; - DagAdjList *mainchild, *prev = NULL; - - mainchild = ((DagNode *) forest->DagNode.first)->child; - /* remove from first node (scene) adj list if present */ - while (mainchild) { - if (mainchild->node == fob) { - if (prev) { - prev->next = mainchild->next; - MEM_freeN(mainchild); - break; - } - else { - ((DagNode *) forest->DagNode.first)->child = mainchild->next; - MEM_freeN(mainchild); - break; - } - } - prev = mainchild; - mainchild = mainchild->next; - } - node = dag_find_node(forest, fob); - if (!node) - node = dag_add_node(forest, fob); - return node; -} - -static void dag_add_parent_relation(DagForest *UNUSED(forest), DagNode *fob1, DagNode *fob2, short rel, const char *name) -{ - DagAdjList *itA = fob2->parent; - - while (itA) { /* search if relation exist already */ - if (itA->node == fob1) { - itA->type |= rel; - itA->count += 1; - return; - } - itA = itA->next; - } - /* create new relation and insert at head. MALLOC alert! */ - itA = MEM_mallocN(sizeof(DagAdjList), "DAG adj list"); - itA->node = fob1; - itA->type = rel; - itA->count = 1; - itA->next = fob2->parent; - itA->name = name; - fob2->parent = itA; -} - -void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, const char *name) -{ - DagAdjList *itA = fob1->child; - - /* parent relation is for cycle checking */ - dag_add_parent_relation(forest, fob1, fob2, rel, name); - - /* TODO(sergey): Find a better place for this. */ -#ifdef WITH_OPENSUBDIV - if ((rel & (DAG_RL_DATA_DATA | DAG_RL_DATA_OB)) != 0) { - if (fob1->type == ID_OB) { - if ((fob1->eval_flags & DAG_EVAL_NEED_CPU) == 0) { - Object *ob2 = fob2->ob; - if (ob2->recalc & OB_RECALC_ALL) { - /* Make sure object has all the data on CPU. */ - Object *ob1 = fob1->ob; - ob1->recalc |= OB_RECALC_DATA; - } - fob1->eval_flags |= DAG_EVAL_NEED_CPU; - } - } - } -#endif - - while (itA) { /* search if relation exist already */ - if (itA->node == fob2) { - itA->type |= rel; - itA->count += 1; - return; - } - itA = itA->next; - } - /* create new relation and insert at head. MALLOC alert! */ - itA = MEM_mallocN(sizeof(DagAdjList), "DAG adj list"); - itA->node = fob2; - itA->type = rel; - itA->count = 1; - itA->next = fob1->child; - itA->name = name; - fob1->child = itA; -} - -static const char *dag_node_name(DagForest *dag, DagNode *node) -{ - if (node->ob == NULL) - return "null"; - else if (dag->ugly_hack_sorry) - return ((ID *)(node->ob))->name + 2; - else - return ((bPoseChannel *)(node->ob))->name; -} - -static void dag_node_print_dependencies(DagForest *dag, DagNode *node) -{ - DagAdjList *itA; - - printf("%s depends on:\n", dag_node_name(dag, node)); - - for (itA = node->parent; itA; itA = itA->next) - printf(" %s through %s\n", dag_node_name(dag, itA->node), itA->name); - printf("\n"); -} - -static int dag_node_print_dependency_recurs(DagForest *dag, DagNode *node, DagNode *endnode) -{ - DagAdjList *itA; - - if (node->color == DAG_BLACK) - return 0; - - node->color = DAG_BLACK; - - if (node == endnode) - return 1; - - for (itA = node->parent; itA; itA = itA->next) { - if (dag_node_print_dependency_recurs(dag, itA->node, endnode)) { - printf(" %s depends on %s through %s.\n", dag_node_name(dag, node), dag_node_name(dag, itA->node), itA->name); - return 1; - } - } - - return 0; -} - -static void dag_node_print_dependency_cycle(DagForest *dag, DagNode *startnode, DagNode *endnode, const char *name) -{ - DagNode *node; - - for (node = dag->DagNode.first; node; node = node->next) - node->color = DAG_WHITE; - - printf(" %s depends on %s through %s.\n", dag_node_name(dag, endnode), dag_node_name(dag, startnode), name); - dag_node_print_dependency_recurs(dag, startnode, endnode); - printf("\n"); -} - -static int dag_node_recurs_level(DagNode *node, int level) -{ - DagAdjList *itA; - int newlevel; - - node->color = DAG_BLACK; /* done */ - newlevel = ++level; - - for (itA = node->parent; itA; itA = itA->next) { - if (itA->node->color == DAG_WHITE) { - itA->node->ancestor_count = dag_node_recurs_level(itA->node, level); - newlevel = MAX2(newlevel, level + itA->node->ancestor_count); - } - else - newlevel = MAX2(newlevel, level + itA->node->ancestor_count); - } - - return newlevel; -} - -static void dag_check_cycle(DagForest *dag) -{ - DagNode *node; - DagAdjList *itA; - - dag->is_acyclic = true; - - /* debugging print */ - if (dag_print_dependencies) - for (node = dag->DagNode.first; node; node = node->next) - dag_node_print_dependencies(dag, node); - - /* tag nodes unchecked */ - for (node = dag->DagNode.first; node; node = node->next) - node->color = DAG_WHITE; - - for (node = dag->DagNode.first; node; node = node->next) { - if (node->color == DAG_WHITE) { - node->ancestor_count = dag_node_recurs_level(node, 0); - } - } - - /* check relations, and print errors */ - for (node = dag->DagNode.first; node; node = node->next) { - for (itA = node->parent; itA; itA = itA->next) { - if (itA->node->ancestor_count > node->ancestor_count) { - if (node->ob && itA->node->ob) { - dag->is_acyclic = false; - printf("Dependency cycle detected:\n"); - dag_node_print_dependency_cycle(dag, itA->node, node, itA->name); - } - } - } - } - - /* parent relations are only needed for cycle checking, so free now */ - for (node = dag->DagNode.first; node; node = node->next) { - while (node->parent) { - itA = node->parent->next; - MEM_freeN(node->parent); - node->parent = itA; - } - } -} - -/* debug test functions */ - -void graph_print_queue(DagNodeQueue *nqueue) -{ - DagNodeQueueElem *queueElem; - - queueElem = nqueue->first; - while (queueElem) { - fprintf(stderr, "** %s %i %i-%i ", ((ID *) queueElem->node->ob)->name, queueElem->node->color, queueElem->node->DFS_dvtm, queueElem->node->DFS_fntm); - queueElem = queueElem->next; - } - fprintf(stderr, "\n"); -} - -void graph_print_queue_dist(DagNodeQueue *nqueue) -{ - DagNodeQueueElem *queueElem; - int count; - - queueElem = nqueue->first; - count = 0; - while (queueElem) { - fprintf(stderr, "** %25s %2.2i-%2.2i ", ((ID *) queueElem->node->ob)->name, queueElem->node->DFS_dvtm, queueElem->node->DFS_fntm); - while (count < queueElem->node->DFS_dvtm - 1) { fputc(' ', stderr); count++; } - fputc('|', stderr); - while (count < queueElem->node->DFS_fntm - 2) { fputc('-', stderr); count++; } - fputc('|', stderr); - fputc('\n', stderr); - count = 0; - queueElem = queueElem->next; - } - fprintf(stderr, "\n"); -} - -void graph_print_adj_list(DagForest *dag) -{ - DagNode *node; - DagAdjList *itA; - - node = dag->DagNode.first; - while (node) { - fprintf(stderr, "node : %s col: %i", ((ID *) node->ob)->name, node->color); - itA = node->child; - while (itA) { - fprintf(stderr, "-- %s ", ((ID *) itA->node->ob)->name); - - itA = itA->next; - } - fprintf(stderr, "\n"); - node = node->next; - } -} - -/* ************************ API *********************** */ - -/* mechanism to allow editors to be informed of depsgraph updates, - * to do their own updates based on changes... */ -static void (*EditorsUpdateIDCb)(Main *bmain, ID *id) = NULL; -static void (*EditorsUpdateSceneCb)(Main *bmain, Scene *scene, int updated) = NULL; -static void (*EditorsUpdateScenePreCb)(Main *bmain, Scene *scene, bool time) = NULL; - -void DAG_editors_update_cb(void (*id_func)(Main *bmain, ID *id), - void (*scene_func)(Main *bmain, Scene *scene, int updated), - void (*scene_pre_func)(Main *bmain, Scene *scene, bool time)) -{ - if (DEG_depsgraph_use_legacy()) { - EditorsUpdateIDCb = id_func; - EditorsUpdateSceneCb = scene_func; - EditorsUpdateScenePreCb = scene_pre_func; - } - else { - /* New dependency graph. */ - DEG_editors_set_update_cb(id_func, scene_func, scene_pre_func); - } -} - -void DAG_editors_update_pre(Main *bmain, Scene *scene, bool time) -{ - if (DEG_depsgraph_use_legacy()) { - if (EditorsUpdateScenePreCb != NULL) { - EditorsUpdateScenePreCb(bmain, scene, time); - } - } - else { - DEG_editors_update_pre(bmain, scene, time); - } -} - -static void dag_editors_id_update(Main *bmain, ID *id) -{ - if (EditorsUpdateIDCb) - EditorsUpdateIDCb(bmain, id); -} - -static void dag_editors_scene_update(Main *bmain, Scene *scene, int updated) -{ - if (EditorsUpdateSceneCb) - EditorsUpdateSceneCb(bmain, scene, updated); -} - -/* groups with objects in this scene need to be put in the right order as well */ -static void scene_sort_groups(Main *bmain, Scene *sce) -{ - Base *base; - Group *group; - GroupObject *go; - Object *ob; - - /* test; are group objects all in this scene? */ - for (ob = bmain->object.first; ob; ob = ob->id.next) { - ob->id.tag &= ~LIB_TAG_DOIT; - } - for (base = sce->base.first; base; base = base->next) - base->object->id.tag |= LIB_TAG_DOIT; - - for (group = bmain->group.first; group; group = group->id.next) { - for (go = group->gobject.first; go; go = go->next) { - if ((go->ob->id.tag & LIB_TAG_DOIT) == 0) - break; - } - /* this group is entirely in this scene */ - if (go == NULL) { - ListBase listb = {NULL, NULL}; - - for (go = group->gobject.first; go; go = go->next) - go->ob->id.newid = (ID *)go; - - /* in order of sorted bases we reinsert group objects */ - for (base = sce->base.first; base; base = base->next) { - - if (base->object->id.newid) { - go = (GroupObject *)base->object->id.newid; - base->object->id.newid = NULL; - BLI_remlink(&group->gobject, go); - BLI_addtail(&listb, go); - } - } - /* copy the newly sorted listbase */ - group->gobject = listb; - } - } - - /* newid abused for GroupObject, cleanup. */ - for (ob = bmain->object.first; ob; ob = ob->id.next) { - ob->id.newid = NULL; - } -} - -static void dag_scene_tag_rebuild(Scene *sce) -{ - if (sce->theDag) { - sce->theDag->need_update = true; - } -} - -/* free the depency graph */ -static void dag_scene_free(Scene *sce) -{ - if (sce->theDag) { - free_forest(sce->theDag); - MEM_freeN(sce->theDag); - sce->theDag = NULL; - } -} - -/* Check whether object data needs to be evaluated before it - * might be used by others. - * - * Means that mesh object needs to have proper derivedFinal, - * curves-typed objects are to have proper curve cache. - * - * Other objects or objects which are tagged for data update are - * not considered to be in need of evaluation. - */ -static bool check_object_needs_evaluation(Object *object) -{ - if (object->recalc & OB_RECALC_ALL) { - /* Object is tagged for update anyway, no need to re-tag it. */ - return false; - } - - if (object->type == OB_MESH) { - return object->derivedFinal == NULL; - } - else if (ELEM(object->type, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { - return object->curve_cache == NULL; - } - - return false; -} - -/* Check whether object data is tagged for update. */ -static bool check_object_tagged_for_update(Object *object) -{ - if (object->recalc & OB_RECALC_ALL) { - return true; - } - - if (ELEM(object->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { - ID *data_id = object->data; - return (data_id->recalc & ID_RECALC_ALL) != 0; - } - - return false; -} - -/* Flush changes from tagged objects in the scene to their - * dependencies which are not evaluated yet. - * - * This is needed to ensure all the dependencies are met - * before objects gets handled by object_handle_update(), - * - * This is needed when visible layers are changed or changing - * scene graph layout which involved usage of objects which - * aren't in the scene or weren't visible yet. - */ -static void dag_invisible_dependencies_flush(Scene *scene) -{ - DagNode *root_node = scene->theDag->DagNode.first, *node; - DagNodeQueue *queue; - - for (node = root_node; node != NULL; node = node->next) { - node->color = DAG_WHITE; - } - - queue = queue_create(DAGQUEUEALLOC); - - for (node = root_node; node != NULL; node = node->next) { - if (node->color == DAG_WHITE) { - push_stack(queue, node); - node->color = DAG_GRAY; - - while (queue->count) { - DagNode *current_node = get_top_node_queue(queue); - DagAdjList *itA; - bool skip = false; - - for (itA = current_node->child; itA; itA = itA->next) { - if (itA->node->color == DAG_WHITE) { - itA->node->color = DAG_GRAY; - push_stack(queue, itA->node); - skip = true; - break; - } - } - - if (!skip) { - current_node = pop_queue(queue); - - if (current_node->type == ID_OB) { - Object *current_object = current_node->ob; - if (check_object_needs_evaluation(current_object)) { - for (itA = current_node->child; itA; itA = itA->next) { - if (itA->node->type == ID_OB) { - Object *object = itA->node->ob; - if (check_object_tagged_for_update(object)) { - current_object->recalc |= OB_RECALC_OB | OB_RECALC_DATA; - } - } - } - } - } - node->color = DAG_BLACK; - } - } - } - } - - queue_delete(queue); -} - -static void dag_invisible_dependencies_check_flush(Main *bmain, Scene *scene) -{ - if (DAG_id_type_tagged(bmain, ID_OB) || - DAG_id_type_tagged(bmain, ID_ME) || /* Mesh */ - DAG_id_type_tagged(bmain, ID_CU) || /* Curve */ - DAG_id_type_tagged(bmain, ID_MB) || /* MetaBall */ - DAG_id_type_tagged(bmain, ID_LT)) /* Lattice */ - { - dag_invisible_dependencies_flush(scene); - } -} - -/* sort the base list on dependency order */ -static void dag_scene_build(Main *bmain, Scene *sce) -{ - DagNode *node, *rootnode; - DagNodeQueue *nqueue; - DagAdjList *itA; - int time; - int skip = 0; - ListBase tempbase; - Base *base; - - BLI_listbase_clear(&tempbase); - - build_dag(bmain, sce, DAG_RL_ALL_BUT_DATA); - - dag_check_cycle(sce->theDag); - - nqueue = queue_create(DAGQUEUEALLOC); - - for (node = sce->theDag->DagNode.first; node; node = node->next) { - node->color = DAG_WHITE; - } - - time = 1; - - rootnode = sce->theDag->DagNode.first; - rootnode->color = DAG_GRAY; - time++; - push_stack(nqueue, rootnode); - - while (nqueue->count) { - - skip = 0; - node = get_top_node_queue(nqueue); - - itA = node->child; - while (itA != NULL) { - if (itA->node->color == DAG_WHITE) { - itA->node->DFS_dvtm = time; - itA->node->color = DAG_GRAY; - - time++; - push_stack(nqueue, itA->node); - skip = 1; - break; - } - itA = itA->next; - } - - if (!skip) { - if (node) { - node = pop_queue(nqueue); - if (node->ob == sce) /* we are done */ - break; - node->color = DAG_BLACK; - - time++; - base = sce->base.first; - while (base && base->object != node->ob) - base = base->next; - if (base) { - BLI_remlink(&sce->base, base); - BLI_addhead(&tempbase, base); - } - } - } - } - - /* temporal correction for circular dependencies */ - base = sce->base.first; - while (base) { - BLI_remlink(&sce->base, base); - BLI_addhead(&tempbase, base); - //if (G.debug & G_DEBUG) - printf("cyclic %s\n", base->object->id.name); - base = sce->base.first; - } - - sce->base = tempbase; - queue_delete(nqueue); - - /* all groups with objects in this scene gets resorted too */ - scene_sort_groups(bmain, sce); - - if (G.debug & G_DEBUG) { - printf("\nordered\n"); - for (base = sce->base.first; base; base = base->next) { - printf(" %s\n", base->object->id.name); - } - } - - /* Make sure that new dependencies which came from invisible layers - * are tagged for update (if they're needed for objects which were - * tagged for update). - */ - dag_invisible_dependencies_check_flush(bmain, sce); -} - -/* clear all dependency graphs */ -void DAG_relations_tag_update(Main *bmain) -{ - if (DEG_depsgraph_use_legacy()) { - Scene *sce; - for (sce = bmain->scene.first; sce; sce = sce->id.next) { - dag_scene_tag_rebuild(sce); - } - } - else { - /* New dependency graph. */ - DEG_relations_tag_update(bmain); - } -} - -/* rebuild dependency graph only for a given scene */ -void DAG_scene_relations_rebuild(Main *bmain, Scene *sce) -{ - if (DEG_depsgraph_use_legacy()) { - dag_scene_free(sce); - DAG_scene_relations_update(bmain, sce); - } - else { - /* New dependency graph. */ - DEG_scene_relations_rebuild(bmain, sce); - } -} - -/* create dependency graph if it was cleared or didn't exist yet */ -void DAG_scene_relations_update(Main *bmain, Scene *sce) -{ - if (DEG_depsgraph_use_legacy()) { - if (!sce->theDag || sce->theDag->need_update) - dag_scene_build(bmain, sce); - } - else { - /* New dependency graph. */ - DEG_scene_relations_update(bmain, sce); - } -} - -void DAG_scene_relations_validate(Main *bmain, Scene *sce) -{ - if (!DEG_depsgraph_use_legacy()) { - DEG_debug_scene_relations_validate(bmain, sce); - } -} - -void DAG_scene_free(Scene *sce) -{ - if (DEG_depsgraph_use_legacy()) { - if (sce->theDag) { - free_forest(sce->theDag); - MEM_freeN(sce->theDag); - sce->theDag = NULL; - } - } - else { - if (sce->depsgraph) { - DEG_graph_free(sce->depsgraph); - sce->depsgraph = NULL; - } - } -} - -static void lib_id_recalc_tag(Main *bmain, ID *id) -{ - id->recalc |= ID_RECALC; - DAG_id_type_tag(bmain, GS(id->name)); -} - -static void lib_id_recalc_data_tag(Main *bmain, ID *id) -{ - id->recalc |= ID_RECALC_DATA; - DAG_id_type_tag(bmain, GS(id->name)); -} - -/* node was checked to have lasttime != curtime and is if type ID_OB */ -static void flush_update_node(Main *bmain, DagNode *node, unsigned int layer, int curtime) -{ - DagAdjList *itA; - Object *ob, *obc; - int oldflag; - bool changed = false; - unsigned int all_layer; - - node->lasttime = curtime; - - ob = node->ob; - if (ob && (ob->recalc & OB_RECALC_ALL)) { - all_layer = node->scelay; - - /* got an object node that changes, now check relations */ - for (itA = node->child; itA; itA = itA->next) { - all_layer |= itA->lay; - /* the relationship is visible */ - if ((itA->lay & layer)) { // XXX || (itA->node->ob == obedit) - if (itA->node->type == ID_OB) { - obc = itA->node->ob; - oldflag = obc->recalc; - - /* got a ob->obc relation, now check if flag needs flush */ - if (ob->recalc & OB_RECALC_OB) { - if (itA->type & DAG_RL_OB_OB) { - //printf("ob %s changes ob %s\n", ob->id.name, obc->id.name); - obc->recalc |= OB_RECALC_OB; - lib_id_recalc_tag(bmain, &obc->id); - } - if (itA->type & DAG_RL_OB_DATA) { - //printf("ob %s changes obdata %s\n", ob->id.name, obc->id.name); - obc->recalc |= OB_RECALC_DATA; - lib_id_recalc_data_tag(bmain, &obc->id); - } - } - if (ob->recalc & OB_RECALC_DATA) { - if (itA->type & DAG_RL_DATA_OB) { - //printf("obdata %s changes ob %s\n", ob->id.name, obc->id.name); - obc->recalc |= OB_RECALC_OB; - lib_id_recalc_tag(bmain, &obc->id); - } - if (itA->type & DAG_RL_DATA_DATA) { - //printf("obdata %s changes obdata %s\n", ob->id.name, obc->id.name); - obc->recalc |= OB_RECALC_DATA; - lib_id_recalc_data_tag(bmain, &obc->id); - } - } - if (oldflag != obc->recalc) changed = 1; - } - } - } - /* even nicer, we can clear recalc flags... */ - if ((all_layer & layer) == 0) { // XXX && (ob != obedit)) { - /* but existing displaylists or derivedmesh should be freed */ - if (ob->recalc & OB_RECALC_DATA) - BKE_object_free_derived_caches(ob); - - ob->recalc &= ~OB_RECALC_ALL; - } - } - - /* check case where child changes and parent forcing obdata to change */ - /* should be done regardless if this ob has recalc set */ - /* could merge this in with loop above...? (ton) */ - for (itA = node->child; itA; itA = itA->next) { - /* the relationship is visible */ - if ((itA->lay & layer)) { // XXX || (itA->node->ob == obedit) - if (itA->node->type == ID_OB) { - obc = itA->node->ob; - /* child moves */ - if ((obc->recalc & OB_RECALC_ALL) == OB_RECALC_OB) { - /* parent has deforming info */ - if (itA->type & (DAG_RL_OB_DATA | DAG_RL_DATA_DATA)) { - // printf("parent %s changes ob %s\n", ob->id.name, obc->id.name); - obc->recalc |= OB_RECALC_DATA; - lib_id_recalc_data_tag(bmain, &obc->id); - } - } - } - } - } - - /* we only go deeper if node not checked or something changed */ - for (itA = node->child; itA; itA = itA->next) { - if (changed || itA->node->lasttime != curtime) - flush_update_node(bmain, itA->node, layer, curtime); - } - -} - -/* node was checked to have lasttime != curtime, and is of type ID_OB */ -static unsigned int flush_layer_node(Scene *sce, DagNode *node, int curtime) -{ - DagAdjList *itA; - - node->lasttime = curtime; - node->lay = node->scelay; - - for (itA = node->child; itA; itA = itA->next) { - if (itA->node->type == ID_OB) { - if (itA->node->lasttime != curtime) { - itA->lay = flush_layer_node(sce, itA->node, curtime); /* lay is only set once for each relation */ - } - else { - itA->lay = itA->node->lay; - } - - node->lay |= itA->lay; - } - } - - return node->lay; -} - -/* node was checked to have lasttime != curtime, and is of type ID_OB */ -static void flush_pointcache_reset(Main *bmain, Scene *scene, DagNode *node, - int curtime, unsigned int lay, bool reset) -{ - DagAdjList *itA; - Object *ob; - - node->lasttime = curtime; - - for (itA = node->child; itA; itA = itA->next) { - if (itA->node->type == ID_OB) { - if (itA->node->lasttime != curtime) { - ob = (Object *)(itA->node->ob); - - if (reset || (ob->recalc & OB_RECALC_ALL)) { - if (BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH)) { - /* Don't tag nodes which are on invisible layer. */ - if (itA->node->lay & lay) { - ob->recalc |= OB_RECALC_DATA; - lib_id_recalc_data_tag(bmain, &ob->id); - } - } - - flush_pointcache_reset(bmain, scene, itA->node, curtime, lay, true); - } - else - flush_pointcache_reset(bmain, scene, itA->node, curtime, lay, false); - } - } - } -} - -/* flush layer flags to dependencies */ -static void dag_scene_flush_layers(Scene *sce, int lay) -{ - DagNode *node, *firstnode; - DagAdjList *itA; - Base *base; - int lasttime; - - firstnode = sce->theDag->DagNode.first; /* always scene node */ - - for (itA = firstnode->child; itA; itA = itA->next) - itA->lay = 0; - - sce->theDag->time++; /* so we know which nodes were accessed */ - lasttime = sce->theDag->time; - - /* update layer flags in nodes */ - for (base = sce->base.first; base; base = base->next) { - node = dag_get_node(sce->theDag, base->object); - node->scelay = base->object->lay; - } - - /* ensure cameras are set as if they are on a visible layer, because - * they ared still used for rendering or setting the camera view - * - * XXX, this wont work for local view / unlocked camera's */ - if (sce->camera) { - node = dag_get_node(sce->theDag, sce->camera); - node->scelay |= lay; - } - -#ifdef DURIAN_CAMERA_SWITCH - { - TimeMarker *m; - - for (m = sce->markers.first; m; m = m->next) { - if (m->camera) { - node = dag_get_node(sce->theDag, m->camera); - node->scelay |= lay; - } - } - } -#endif - - /* flush layer nodes to dependencies */ - for (itA = firstnode->child; itA; itA = itA->next) - if (itA->node->lasttime != lasttime && itA->node->type == ID_OB) - flush_layer_node(sce, itA->node, lasttime); -} - -static void dag_tag_renderlayers(Scene *sce, unsigned int lay) -{ - if (sce->nodetree) { - bNode *node; - Base *base; - unsigned int lay_changed = 0; - - for (base = sce->base.first; base; base = base->next) - if (base->lay & lay) - if (base->object->recalc) - lay_changed |= base->lay; - - for (node = sce->nodetree->nodes.first; node; node = node->next) { - if (node->id == (ID *)sce) { - SceneRenderLayer *srl = BLI_findlink(&sce->r.layers, node->custom1); - if (srl && (srl->lay & lay_changed)) - nodeUpdate(sce->nodetree, node); - } - } - } -} - -/* flushes all recalc flags in objects down the dependency tree */ -void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const short time) -{ - DagNode *firstnode; - DagAdjList *itA; - Object *ob; - int lasttime; - - if (!DEG_depsgraph_use_legacy()) { - DEG_scene_flush_update(bmain, sce); - return; - } - - if (sce->theDag == NULL || sce->theDag->need_update) { - printf("DAG zero... not allowed to happen!\n"); - DAG_scene_relations_update(bmain, sce); - } - - firstnode = sce->theDag->DagNode.first; /* always scene node */ - - /* first we flush the layer flags */ - dag_scene_flush_layers(sce, lay); - - /* then we use the relationships + layer info to flush update events */ - sce->theDag->time++; /* so we know which nodes were accessed */ - lasttime = sce->theDag->time; - for (itA = firstnode->child; itA; itA = itA->next) - if (itA->node->lasttime != lasttime && itA->node->type == ID_OB) - flush_update_node(bmain, itA->node, lay, lasttime); - - /* if update is not due to time change, do pointcache clears */ - if (!time) { - sce->theDag->time++; /* so we know which nodes were accessed */ - lasttime = sce->theDag->time; - for (itA = firstnode->child; itA; itA = itA->next) { - if (itA->node->lasttime != lasttime && itA->node->type == ID_OB) { - ob = (Object *)(itA->node->ob); - - if (ob->recalc & OB_RECALC_ALL) { - if (BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH)) { - ob->recalc |= OB_RECALC_DATA; - lib_id_recalc_data_tag(bmain, &ob->id); - } - - flush_pointcache_reset(bmain, sce, itA->node, lasttime, - lay, true); - } - else - flush_pointcache_reset(bmain, sce, itA->node, lasttime, - lay, false); - } - } - } - - dag_tag_renderlayers(sce, lay); -} - -static bool modifier_nlastrips_use_time(ListBase *strips) -{ - NlaStrip *strip; - - if (strips) { - for (strip = strips->first; strip; strip = strip->next) { - if (modifier_nlastrips_use_time(&strip->strips)) { - return true; - } - else if (strip->act) { - FCurve *fcu; - - for (fcu = strip->act->curves.first; fcu; fcu = fcu->next) { - if (fcu->rna_path && strstr(fcu->rna_path, "modifiers[")) - return true; - } - } - } - } - - return false; -} - -static bool object_modifiers_use_time(Object *ob) -{ - ModifierData *md; - - /* check if a modifier in modifier stack needs time input */ - for (md = ob->modifiers.first; md; md = md->next) { - if (modifier_dependsOnTime(md)) - return true; - } - - /* check whether any modifiers are animated */ - if (ob->adt) { - AnimData *adt = ob->adt; - NlaTrack *nlt; - FCurve *fcu; - - /* action - check for F-Curves with paths containing 'modifiers[' */ - if (adt->action) { - for (fcu = adt->action->curves.first; fcu; fcu = fcu->next) { - if (fcu->rna_path && strstr(fcu->rna_path, "modifiers[")) - return true; - } - } - - /* This here allows modifier properties to get driven and still update properly - * - * Workaround to get [#26764] (e.g. subsurf levels not updating when animated/driven) - * working, without the updating problems ([#28525] [#28690] [#28774] [#28777]) caused - * by the RNA updates cache introduced in r.38649 - */ - for (fcu = adt->drivers.first; fcu; fcu = fcu->next) { - if (fcu->rna_path && strstr(fcu->rna_path, "modifiers[")) - return true; - } - - /* Also check NLA Strips... [#T45938] */ - for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { - if (modifier_nlastrips_use_time(&nlt->strips)) - return true; - } - } - - return false; -} - -static short animdata_use_time(AnimData *adt) -{ - NlaTrack *nlt; - - if (adt == NULL) return 0; - - /* check action - only if assigned, and it has anim curves */ - if (adt->action && adt->action->curves.first) - return 1; - - /* check NLA tracks + strips */ - for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) { - if (nlt->strips.first) - return 1; - } - - /* If we have drivers, more likely than not, on a frame change - * they'll need updating because their owner changed - * - * This is kindof a hack to get around a whole host of problems - * involving drivers using non-object datablock data (which the - * depsgraph currently has no way of representing let alone correctly - * dependency sort+tagging). By doing this, at least we ensure that - * some commonly attempted drivers (such as scene -> current frame; - * see "Driver updates fail" thread on Bf-committers dated July 2) - * will work correctly, and that other non-object datablocks will have - * their drivers update at least on frame change. - * - * -- Aligorith, July 4 2011 - */ - if (adt->drivers.first) - return 1; - - return 0; -} - -static void dag_object_time_update_flags(Main *bmain, Scene *scene, Object *ob) -{ - if (ob->constraints.first) { - bConstraint *con; - for (con = ob->constraints.first; con; con = con->next) { - const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); - ListBase targets = {NULL, NULL}; - bConstraintTarget *ct; - - if (cti) { - /* special case for camera tracking -- it doesn't use targets to define relations */ - if (ELEM(cti->type, - CONSTRAINT_TYPE_FOLLOWTRACK, - CONSTRAINT_TYPE_CAMERASOLVER, - CONSTRAINT_TYPE_OBJECTSOLVER, - CONSTRAINT_TYPE_TRANSFORM_CACHE)) - { - ob->recalc |= OB_RECALC_OB; - } - else if (cti->get_constraint_targets) { - cti->get_constraint_targets(con, &targets); - - for (ct = targets.first; ct; ct = ct->next) { - if (ct->tar) { - ob->recalc |= OB_RECALC_OB; - break; - } - } - - if (cti->flush_constraint_targets) - cti->flush_constraint_targets(con, &targets, 1); - } - - } - } - } - - if (ob->parent) { - /* motion path or bone child */ - if (ob->parent->type == OB_CURVE || ob->parent->type == OB_ARMATURE) ob->recalc |= OB_RECALC_OB; - } - -#if 0 // XXX old animation system - if (ob->nlastrips.first) { - if (ob->dup_group) { - bActionStrip *strip; - /* this case is for groups with nla, whilst nla target has no action or nla */ - for (strip = ob->nlastrips.first; strip; strip = strip->next) { - if (strip->object) - strip->object->recalc |= OB_RECALC_ALL; - } - } - } -#endif // XXX old animation system - - if (animdata_use_time(ob->adt)) { - ob->recalc |= OB_RECALC_OB; - ob->adt->recalc |= ADT_RECALC_ANIM; - } - - if ((ob->adt) && (ob->type == OB_ARMATURE)) ob->recalc |= OB_RECALC_DATA; - - if (object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA; - if ((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA; - - // XXX: scene here may not be the scene that contains the rigidbody world affecting this! - if (ob->rigidbody_object && BKE_scene_check_rigidbody_active(scene)) - ob->recalc |= OB_RECALC_OB; - - { - AnimData *adt = BKE_animdata_from_id((ID *)ob->data); - Mesh *me; - Curve *cu; - Lattice *lt; - - switch (ob->type) { - case OB_MESH: - me = ob->data; - if (me->key) { - if (!(ob->shapeflag & OB_SHAPE_LOCK)) { - ob->recalc |= OB_RECALC_DATA; - } - } - if (ob->particlesystem.first) - ob->recalc |= OB_RECALC_DATA; - break; - case OB_CURVE: - case OB_SURF: - cu = ob->data; - if (cu->key) { - if (!(ob->shapeflag & OB_SHAPE_LOCK)) { - ob->recalc |= OB_RECALC_DATA; - } - } - break; - case OB_FONT: - cu = ob->data; - if (cu->str && cu->vfont) { - /* Can be in the curve-cache or the curve. */ - if (ob->curve_cache && !BLI_listbase_is_empty(&ob->curve_cache->disp)) { - /* pass */ - } - else if (!BLI_listbase_is_empty(&cu->nurb)) { - /* pass */ - } - else { - ob->recalc |= OB_RECALC_DATA; - } - } - break; - case OB_LATTICE: - lt = ob->data; - if (lt->key) { - if (!(ob->shapeflag & OB_SHAPE_LOCK)) { - ob->recalc |= OB_RECALC_DATA; - } - } - break; - case OB_MBALL: - if (ob->transflag & OB_DUPLI) ob->recalc |= OB_RECALC_DATA; - break; - case OB_EMPTY: - /* update animated images */ - if (ob->empty_drawtype == OB_EMPTY_IMAGE && ob->data) - if (BKE_image_is_animated(ob->data)) - ob->recalc |= OB_RECALC_DATA; - break; - } - - if (animdata_use_time(adt)) { - ob->recalc |= OB_RECALC_DATA; - adt->recalc |= ADT_RECALC_ANIM; - } - - if (ob->particlesystem.first) { - ParticleSystem *psys = ob->particlesystem.first; - - for (; psys; psys = psys->next) { - if (psys_check_enabled(ob, psys, G.is_rendering)) { - ob->recalc |= OB_RECALC_DATA; - break; - } - } - } - } - - if (ob->recalc & OB_RECALC_OB) - lib_id_recalc_tag(bmain, &ob->id); - if (ob->recalc & OB_RECALC_DATA) - lib_id_recalc_data_tag(bmain, &ob->id); - -} - -/* recursively update objects in groups, each group is done at most once */ -static void dag_group_update_flags(Main *bmain, Scene *scene, Group *group, const bool do_time) -{ - GroupObject *go; - - if (group->id.tag & LIB_TAG_DOIT) - return; - - group->id.tag |= LIB_TAG_DOIT; - - for (go = group->gobject.first; go; go = go->next) { - if (do_time) - dag_object_time_update_flags(bmain, scene, go->ob); - if (go->ob->dup_group) - dag_group_update_flags(bmain, scene, go->ob->dup_group, do_time); - } -} - -/* flag all objects that need recalc, for changes in time for example */ -/* do_time: make this optional because undo resets objects to their animated locations without this */ -void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const bool do_time, const bool do_invisible_flush) -{ - Base *base; - Object *ob; - Group *group; - GroupObject *go; - Scene *sce_iter; - - BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false); - - /* set ob flags where animated systems are */ - for (SETLOOPER(scene, sce_iter, base)) { - ob = base->object; - - if (do_time) { - /* now if DagNode were part of base, the node->lay could be checked... */ - /* we do all now, since the scene_flush checks layers and clears recalc flags even */ - - /* NOTE: "sce_iter" not "scene" so that rigidbodies in background scenes work - * (i.e. muting + rbw availability can be checked and tagged properly) [#33970] - */ - dag_object_time_update_flags(bmain, sce_iter, ob); - } - - /* recursively tag groups with LIB_TAG_DOIT, and update flags for objects */ - if (ob->dup_group) - dag_group_update_flags(bmain, scene, ob->dup_group, do_time); - } - - for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set) - DAG_scene_flush_update(bmain, sce_iter, lay, 1); - - if (do_time) { - /* test: set time flag, to disable baked systems to update */ - for (SETLOOPER(scene, sce_iter, base)) { - ob = base->object; - if (ob->recalc & OB_RECALC_ALL) - ob->recalc |= OB_RECALC_TIME; - } - - /* hrmf... an exception to look at once, for invisible camera object we do it over */ - if (scene->camera) - dag_object_time_update_flags(bmain, scene, scene->camera); - } - - /* and store the info in groupobject */ - for (group = bmain->group.first; group; group = group->id.next) { - if (group->id.tag & LIB_TAG_DOIT) { - for (go = group->gobject.first; go; go = go->next) { - go->recalc = go->ob->recalc; - // printf("ob %s recalc %d\n", go->ob->id.name, go->recalc); - } - group->id.tag &= ~LIB_TAG_DOIT; - } - } - - if (do_invisible_flush) { - dag_invisible_dependencies_check_flush(bmain, scene); - } -} - -/* struct returned by DagSceneLayer */ -typedef struct DagSceneLayer { - struct DagSceneLayer *next, *prev; - Scene *scene; - unsigned int layer; -} DagSceneLayer; - -/* returns visible scenes with valid DAG */ -static void dag_current_scene_layers(Main *bmain, ListBase *lb) -{ - wmWindowManager *wm; - wmWindow *win; - - BLI_listbase_clear(lb); - - /* if we have a windowmanager, look into windows */ - if ((wm = bmain->wm.first)) { - - BKE_main_id_flag_listbase(&bmain->scene, LIB_TAG_DOIT, 1); - - for (win = wm->windows.first; win; win = win->next) { - if (win->screen && win->screen->scene->theDag) { - Scene *scene = win->screen->scene; - DagSceneLayer *dsl; - - if (scene->id.tag & LIB_TAG_DOIT) { - dsl = MEM_mallocN(sizeof(DagSceneLayer), "dag scene layer"); - - BLI_addtail(lb, dsl); - - dsl->scene = scene; - dsl->layer = BKE_screen_visible_layers(win->screen, scene); - - scene->id.tag &= ~LIB_TAG_DOIT; - } - else { - /* It is possible that multiple windows shares the same scene - * and have different layers visible. - * - * Here we deal with such cases by squashing layers bits from - * multiple windoew to the DagSceneLayer. - * - * TODO(sergey): Such a lookup could be optimized perhaps, - * however should be fine for now since we usually have only - * few open windows. - */ - for (dsl = lb->first; dsl; dsl = dsl->next) { - if (dsl->scene == scene) { - dsl->layer |= BKE_screen_visible_layers(win->screen, scene); - break; - } - } - } - } - } - } - else { - /* if not, use the first sce */ - DagSceneLayer *dsl = MEM_mallocN(sizeof(DagSceneLayer), "dag scene layer"); - - BLI_addtail(lb, dsl); - - dsl->scene = bmain->scene.first; - dsl->layer = dsl->scene->lay; - - /* XXX for background mode, we should get the scene - * from somewhere, for the -S option, but it's in - * the context, how to get it here? */ - } -} - -static void dag_group_on_visible_update(Scene *scene, Group *group) -{ - GroupObject *go; - - if (group->id.tag & LIB_TAG_DOIT) - return; - - group->id.tag |= LIB_TAG_DOIT; - - for (go = group->gobject.first; go; go = go->next) { - if (ELEM(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) { - go->ob->recalc |= OB_RECALC_DATA; - go->ob->id.tag |= LIB_TAG_DOIT; - lib_id_recalc_tag(G.main, &go->ob->id); - } - if (go->ob->proxy_from) { - go->ob->recalc |= OB_RECALC_OB; - go->ob->id.tag |= LIB_TAG_DOIT; - lib_id_recalc_tag(G.main, &go->ob->id); - } - - if (go->ob->dup_group) - dag_group_on_visible_update(scene, go->ob->dup_group); - } -} - -void DAG_on_visible_update(Main *bmain, const bool do_time) -{ - ListBase listbase; - DagSceneLayer *dsl; - - if (!DEG_depsgraph_use_legacy()) { - /* Inform new dependnecy graphs about visibility changes. */ - DEG_on_visible_update(bmain, do_time); - return; - } - - /* get list of visible scenes and layers */ - dag_current_scene_layers(bmain, &listbase); - - for (dsl = listbase.first; dsl; dsl = dsl->next) { - Scene *scene = dsl->scene; - Scene *sce_iter; - Base *base; - Object *ob; - DagNode *node; - unsigned int lay = dsl->layer, oblay; - - /* derivedmeshes and displists are not saved to file so need to be - * remade, tag them so they get remade in the scene update loop, - * note armature poses or object matrices are preserved and do not - * require updates, so we skip those */ - for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set) - dag_scene_flush_layers(sce_iter, lay); - - BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false); - - for (SETLOOPER(scene, sce_iter, base)) { - ob = base->object; - node = (sce_iter->theDag) ? dag_get_node(sce_iter->theDag, ob) : NULL; - oblay = (node) ? node->lay : ob->lay; - - if ((oblay & lay) & ~scene->lay_updated) { - /* TODO(sergey): Why do we need armature here now but didn't need before? */ - if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE, OB_ARMATURE)) { - 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); - } - if (ob->dup_group) - dag_group_on_visible_update(scene, ob->dup_group); - } - } - - BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false); - - /* now tag update flags, to ensure deformers get calculated on redraw */ - DAG_scene_update_flags(bmain, scene, lay, do_time, true); - scene->lay_updated |= lay; - } - - BLI_freelistN(&listbase); - - /* hack to get objects updating on layer changes */ - DAG_id_type_tag(bmain, ID_OB); - - /* so masks update on load */ - if (bmain->mask.first) { - Mask *mask; - - for (mask = bmain->mask.first; mask; mask = mask->id.next) { - DAG_id_tag_update(&mask->id, 0); - } - } -} - -static void dag_id_flush_update__isDependentTexture( - void *userData, Object *UNUSED(ob), ID **idpoin, int UNUSED(cb_flag)) -{ - struct { ID *id; bool is_dependent; } *data = userData; - - if (*idpoin && GS((*idpoin)->name) == ID_TE) { - if (data->id == (*idpoin)) - data->is_dependent = 1; - } -} - -static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id) -{ - Object *obt, *ob = NULL; - short idtype; - - /* here we flush a few things before actual scene wide flush, mostly - * due to only objects and not other datablocks being in the depsgraph */ - - /* set flags & pointcache for object */ - if (GS(id->name) == ID_OB) { - ob = (Object *)id; - BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH); - - /* So if someone tagged object recalc directly, - * id_tag_update bit-field stays relevant - */ - if (ob->recalc & OB_RECALC_ALL) { - DAG_id_type_tag(bmain, GS(id->name)); - } - - if (ob->recalc & OB_RECALC_DATA) { - /* all users of this ob->data should be checked */ - id = ob->data; - - /* no point in trying in this cases */ - if (id && id->us <= 1) { - dag_editors_id_update(bmain, id); - id = NULL; - } - } - } - - /* set flags & pointcache for object data */ - if (id) { - idtype = GS(id->name); - - - if (OB_DATA_SUPPORT_ID(idtype)) { - for (obt = bmain->object.first; obt; obt = obt->id.next) { - if (!(ob && obt == ob) && obt->data == id) { - obt->recalc |= OB_RECALC_DATA; - lib_id_recalc_data_tag(bmain, &obt->id); - BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH); - } - } - } - else if (idtype == ID_VF) { - for (obt = bmain->object.first; obt; obt = obt->id.next) { - if (obt->type == OB_FONT) { - Curve *cu = obt->data; - if (ELEM((struct VFont *)id, CURVE_VFONT_ANY(cu))) { - obt->recalc |= OB_RECALC_DATA; - lib_id_recalc_data_tag(bmain, &obt->id); - } - } - } - } - - /* set flags based on textures - can influence depgraph via modifiers */ - if (idtype == ID_TE) { - for (obt = bmain->object.first; obt; obt = obt->id.next) { - struct { ID *id; bool is_dependent; } data; - data.id = id; - data.is_dependent = 0; - - modifiers_foreachIDLink(obt, dag_id_flush_update__isDependentTexture, &data); - if (data.is_dependent) { - obt->recalc |= OB_RECALC_DATA; - lib_id_recalc_data_tag(bmain, &obt->id); - } - - /* particle settings can use the texture as well */ - if (obt->particlesystem.first) { - ParticleSystem *psys = obt->particlesystem.first; - MTex **mtexp, *mtex; - int a; - for (; psys; psys = psys->next) { - mtexp = psys->part->mtex; - for (a = 0; a < MAX_MTEX; a++, mtexp++) { - mtex = *mtexp; - if (mtex && mtex->tex == (Tex *)id) { - obt->recalc |= OB_RECALC_DATA; - lib_id_recalc_data_tag(bmain, &obt->id); - - if (mtex->mapto & PAMAP_INIT) - psys->recalc |= PSYS_RECALC_RESET; - if (mtex->mapto & PAMAP_CHILD) - psys->recalc |= PSYS_RECALC_CHILD; - - BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH); - } - } - } - } - } - } - - /* set flags based on ShapeKey */ - if (idtype == ID_KE) { - for (obt = bmain->object.first; obt; obt = obt->id.next) { - Key *key = BKE_key_from_object(obt); - if (!(ob && obt == ob) && ((ID *)key == id)) { - obt->flag |= (OB_RECALC_OB | OB_RECALC_DATA); - lib_id_recalc_tag(bmain, &obt->id); - lib_id_recalc_data_tag(bmain, &obt->id); - BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH); - } - } - } - - /* set flags based on particle settings */ - if (idtype == ID_PA) { - ParticleSystem *psys; - for (obt = bmain->object.first; obt; obt = obt->id.next) - for (psys = obt->particlesystem.first; psys; psys = psys->next) - if (&psys->part->id == id) - BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH); - } - - if (ELEM(idtype, ID_MA, ID_TE)) { - obt = sce->basact ? sce->basact->object : NULL; - if (obt && obt->mode & OB_MODE_TEXTURE_PAINT) { - BKE_texpaint_slots_refresh_object(sce, obt); - BKE_paint_proj_mesh_data_check(sce, obt, NULL, NULL, NULL, NULL); - GPU_drawobject_free(obt->derivedFinal); - } - } - - if (idtype == ID_MC) { - MovieClip *clip = (MovieClip *) id; - - BKE_tracking_dopesheet_tag_update(&clip->tracking); - - for (obt = bmain->object.first; obt; obt = obt->id.next) { - bConstraint *con; - for (con = obt->constraints.first; con; con = con->next) { - const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); - if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER, - CONSTRAINT_TYPE_OBJECTSOLVER)) - { - obt->recalc |= OB_RECALC_OB; - lib_id_recalc_tag(bmain, &obt->id); - break; - } - } - } - - if (sce->nodetree) { - bNode *node; - - for (node = sce->nodetree->nodes.first; node; node = node->next) { - if (node->id == id) { - nodeUpdate(sce->nodetree, node); - } - } - } - } - - /* Not pretty to iterate all the nodes here, but it's as good as it - * could be with the current depsgraph design/ - */ - if (idtype == ID_IM) { - FOREACH_NODETREE(bmain, ntree, parent_id) { - if (ntree->type == NTREE_SHADER) { - bNode *node; - for (node = ntree->nodes.first; node; node = node->next) { - if (node->id == id) { - lib_id_recalc_tag(bmain, &ntree->id); - break; - } - } - } - } FOREACH_NODETREE_END - } - - if (idtype == ID_MSK) { - if (sce->nodetree) { - bNode *node; - - for (node = sce->nodetree->nodes.first; node; node = node->next) { - if (node->id == id) { - nodeUpdate(sce->nodetree, node); - } - } - } - } - - /* camera's matrix is used to orient reconstructed stuff, - * so it should happen tracking-related constraints recalculation - * when camera is changing (sergey) */ - if (sce->camera && &sce->camera->id == id) { - MovieClip *clip = BKE_object_movieclip_get(sce, sce->camera, true); - - if (clip) - dag_id_flush_update(bmain, sce, &clip->id); - } - - /* update editors */ - dag_editors_id_update(bmain, id); - } -} - -void DAG_ids_flush_tagged(Main *bmain) -{ - ListBase listbase; - DagSceneLayer *dsl; - ListBase *lbarray[MAX_LIBARRAY]; - int a; - bool do_flush = false; - - if (!DEG_depsgraph_use_legacy()) { - DEG_ids_flush_tagged(bmain); - return; - } - - /* get list of visible scenes and layers */ - dag_current_scene_layers(bmain, &listbase); - - if (BLI_listbase_is_empty(&listbase)) - return; - - /* loop over all ID types */ - a = set_listbasepointers(bmain, lbarray); - - while (a--) { - ListBase *lb = lbarray[a]; - ID *id = lb->first; - - if (id && bmain->id_tag_update[BKE_idcode_to_index(GS(id->name))]) { - for (; id; id = id->next) { - if (id->recalc & ID_RECALC_ALL) { - for (dsl = listbase.first; dsl; dsl = dsl->next) - dag_id_flush_update(bmain, dsl->scene, id); - - do_flush = true; - } - } - } - } - - /* flush changes to other objects */ - if (do_flush) { - for (dsl = listbase.first; dsl; dsl = dsl->next) - DAG_scene_flush_update(bmain, dsl->scene, dsl->layer, 0); - } - - BLI_freelistN(&listbase); -} - -void DAG_ids_check_recalc(Main *bmain, Scene *scene, bool time) -{ - ListBase *lbarray[MAX_LIBARRAY]; - int a; - bool updated = false; - - if (!DEG_depsgraph_use_legacy()) { - DEG_ids_check_recalc(bmain, scene, time); - return; - } - - /* loop over all ID types */ - a = set_listbasepointers(bmain, lbarray); - - while (a--) { - ListBase *lb = lbarray[a]; - ID *id = lb->first; - - if (id && bmain->id_tag_update[BKE_idcode_to_index(GS(id->name))]) { - updated = true; - break; - } - } - - dag_editors_scene_update(bmain, scene, (updated || time)); -} - -/* It is possible that scene_update_post and frame_update_post handlers - * will modify objects. The issue is that DAG_ids_clear_recalc is called - * just after callbacks, which leaves objects with recalc flags but no - * corresponding bit in ID recalc bitfield. This leads to some kind of - * regression when using ID type tag fields to check whether there objects - * to be updated internally comparing threaded DAG with legacy one. - * - * For now let's have a workaround which will preserve tag for ID_OB - * if there're objects with OB_RECALC_ALL bits. This keeps behavior - * unchanged comparing with 2.69 release. - * - * TODO(sergey): Need to get rid of such a workaround. - * - * - sergey - - */ - -#define POST_UPDATE_HANDLER_WORKAROUND - -void DAG_ids_clear_recalc(Main *bmain) -{ - ListBase *lbarray[MAX_LIBARRAY]; - bNodeTree *ntree; - int a; - -#ifdef POST_UPDATE_HANDLER_WORKAROUND - bool have_updated_objects = false; - - if (DAG_id_type_tagged(bmain, ID_OB)) { - ListBase listbase; - DagSceneLayer *dsl; - - /* We need to check all visible scenes, otherwise resetting - * OB_ID changed flag will only work fine for first scene of - * multiple visible and all the rest will skip update. - * - * This could also lead to wrong behavior scene update handlers - * because of missing ID datablock changed flags. - * - * This is a bit of a bummer to allocate list here, but likely - * it wouldn't become too much bad because it only happens when - * objects were actually changed. - */ - dag_current_scene_layers(bmain, &listbase); - - for (dsl = listbase.first; dsl; dsl = dsl->next) { - Scene *scene = dsl->scene; - DagNode *node; - for (node = scene->theDag->DagNode.first; - node != NULL && have_updated_objects == false; - node = node->next) - { - if (node->type == ID_OB) { - Object *object = (Object *) node->ob; - if (object->recalc & OB_RECALC_ALL) { - have_updated_objects = true; - break; - } - } - } - } - - BLI_freelistN(&listbase); - } -#endif - - /* loop over all ID types */ - a = set_listbasepointers(bmain, lbarray); - - while (a--) { - ListBase *lb = lbarray[a]; - ID *id = lb->first; - - if (id && bmain->id_tag_update[BKE_idcode_to_index(GS(id->name))]) { - for (; id; id = id->next) { - id->recalc &= ~ID_RECALC_ALL; - - /* some ID's contain semi-datablock nodetree */ - ntree = ntreeFromID(id); - if (ntree) - ntree->id.recalc &= ~ID_RECALC_ALL; - } - } - } - - memset(bmain->id_tag_update, 0, sizeof(bmain->id_tag_update)); - -#ifdef POST_UPDATE_HANDLER_WORKAROUND - if (have_updated_objects) { - DAG_id_type_tag(bmain, ID_OB); - } -#endif -} - -void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag) -{ - if (!DEG_depsgraph_use_legacy()) { - DEG_id_tag_update_ex(bmain, id, flag); - return; - } - - if (id == NULL) return; - - if (G.debug & G_DEBUG_DEPSGRAPH) { - printf("%s: id=%s flag=%d\n", __func__, id->name, flag); - } - - /* tag ID for update */ - if (flag) { - if (flag & OB_RECALC_OB) - lib_id_recalc_tag(bmain, id); - if (flag & (OB_RECALC_DATA | PSYS_RECALC)) - lib_id_recalc_data_tag(bmain, id); - } - else - lib_id_recalc_tag(bmain, id); - - /* flag is for objects and particle systems */ - if (flag) { - Object *ob; - short idtype = GS(id->name); - - if (idtype == ID_OB) { - /* only quick tag */ - ob = (Object *)id; - ob->recalc |= (flag & OB_RECALC_ALL); - } - else if (idtype == ID_PA) { - ParticleSystem *psys; - /* this is weak still, should be done delayed as well */ - for (ob = bmain->object.first; ob; ob = ob->id.next) { - for (psys = ob->particlesystem.first; psys; psys = psys->next) { - if (&psys->part->id == id) { - ob->recalc |= (flag & OB_RECALC_ALL); - psys->recalc |= (flag & PSYS_RECALC); - lib_id_recalc_tag(bmain, &ob->id); - lib_id_recalc_data_tag(bmain, &ob->id); - } - } - } - } - else { - /* disable because this is called on various ID types automatically. - * where printing warning is not useful. for now just ignore */ - /* BLI_assert(!"invalid flag for this 'idtype'"); */ - } - } - else if (GS(id->name) == ID_CF) { - for (Object *ob = bmain->object.first; ob; ob = ob->id.next) { - ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache); - - if (md) { - MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md; - - if (mcmd->cache_file && (&mcmd->cache_file->id == id)) { - ob->recalc |= OB_RECALC_ALL; - continue; - } - } - - for (bConstraint *con = ob->constraints.first; con; con = con->next) { - if (con->type != CONSTRAINT_TYPE_TRANSFORM_CACHE) { - continue; - } - - bTransformCacheConstraint *data = con->data; - - if (data->cache_file && (&data->cache_file->id == id)) { - ob->recalc |= OB_RECALC_ALL; - break; - } - } - } - } -} - -void DAG_id_tag_update(ID *id, short flag) -{ - DAG_id_tag_update_ex(G.main, id, flag); -} - -void DAG_id_type_tag(Main *bmain, short idtype) -{ - if (idtype == ID_NT) { - /* stupid workaround so parent datablocks of nested nodetree get looped - * over when we loop over tagged datablock types */ - DAG_id_type_tag(bmain, ID_MA); - DAG_id_type_tag(bmain, ID_TE); - DAG_id_type_tag(bmain, ID_LA); - DAG_id_type_tag(bmain, ID_WO); - DAG_id_type_tag(bmain, ID_SCE); - } - - atomic_fetch_and_or_uint8((uint8_t *)&bmain->id_tag_update[BKE_idcode_to_index(idtype)], 1); -} - -int DAG_id_type_tagged(Main *bmain, short idtype) -{ - return bmain->id_tag_update[BKE_idcode_to_index(idtype)]; -} - -#if 0 // UNUSED -/* recursively descends tree, each node only checked once */ -/* node is checked to be of type object */ -static int parent_check_node(DagNode *node, int curtime) -{ - DagAdjList *itA; - - node->lasttime = curtime; - - if (node->color == DAG_GRAY) - return DAG_GRAY; - - for (itA = node->child; itA; itA = itA->next) { - if (itA->node->type == ID_OB) { - - if (itA->node->color == DAG_GRAY) - return DAG_GRAY; - - /* descend if not done */ - if (itA->node->lasttime != curtime) { - itA->node->color = parent_check_node(itA->node, curtime); - - if (itA->node->color == DAG_GRAY) - return DAG_GRAY; - } - } - } - - return DAG_WHITE; -} -#endif - -/* ******************* DAG FOR ARMATURE POSE ***************** */ - -/* we assume its an armature with pose */ -void DAG_pose_sort(Object *ob) -{ - bPose *pose = ob->pose; - bPoseChannel *pchan; - bConstraint *con; - DagNode *node; - DagNode *node2, *node3; - DagNode *rootnode; - DagForest *dag; - DagNodeQueue *nqueue; - DagAdjList *itA; - ListBase tempbase; - int skip = 0; - - dag = dag_init(); - dag->ugly_hack_sorry = false; /* no ID structs */ - - rootnode = dag_add_node(dag, NULL); /* node->ob becomes NULL */ - - /* we add the hierarchy and the constraints */ - for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { - int addtoroot = 1; - - node = dag_get_node(dag, pchan); - - if (pchan->parent) { - node2 = dag_get_node(dag, pchan->parent); - dag_add_relation(dag, node2, node, 0, "Parent Relation"); - addtoroot = 0; - } - for (con = pchan->constraints.first; con; con = con->next) { - const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); - ListBase targets = {NULL, NULL}; - bConstraintTarget *ct; - - if (cti && cti->get_constraint_targets) { - cti->get_constraint_targets(con, &targets); - - for (ct = targets.first; ct; ct = ct->next) { - if (ct->tar == ob && ct->subtarget[0]) { - bPoseChannel *target = BKE_pose_channel_find_name(ob->pose, ct->subtarget); - if (target) { - node2 = dag_get_node(dag, target); - dag_add_relation(dag, node2, node, 0, "Pose Constraint"); - - if (con->type == CONSTRAINT_TYPE_KINEMATIC) { - bKinematicConstraint *data = (bKinematicConstraint *)con->data; - bPoseChannel *parchan; - int segcount = 0; - - /* exclude tip from chain? */ - if (!(data->flag & CONSTRAINT_IK_TIP)) - parchan = pchan->parent; - else - parchan = pchan; - - /* Walk to the chain's root */ - while (parchan) { - node3 = dag_get_node(dag, parchan); - dag_add_relation(dag, node2, node3, 0, "IK Constraint"); - - segcount++; - if (segcount == data->rootbone || segcount > 255) break; /* 255 is weak */ - parchan = parchan->parent; - } - } - } - } - } - - if (cti->flush_constraint_targets) - cti->flush_constraint_targets(con, &targets, 1); - } - } - if (addtoroot == 1) { - dag_add_relation(dag, rootnode, node, 0, "Root Bone Relation"); - } - } - - dag_check_cycle(dag); - - /* now we try to sort... */ - BLI_listbase_clear(&tempbase); - - nqueue = queue_create(DAGQUEUEALLOC); - - /* tag nodes unchecked */ - for (node = dag->DagNode.first; node; node = node->next) - node->color = DAG_WHITE; - - rootnode->color = DAG_GRAY; - push_stack(nqueue, rootnode); - - while (nqueue->count) { - - skip = 0; - node = get_top_node_queue(nqueue); - - itA = node->child; - while (itA != NULL) { - if (itA->node->color == DAG_WHITE) { - itA->node->color = DAG_GRAY; - push_stack(nqueue, itA->node); - skip = 1; - break; - } - itA = itA->next; - } - - if (!skip) { - if (node) { - node = pop_queue(nqueue); - if (node->ob == NULL) /* we are done */ - break; - node->color = DAG_BLACK; - - /* put node in new list */ - BLI_remlink(&pose->chanbase, node->ob); - BLI_addhead(&tempbase, node->ob); - } - } - } - - /* temporal correction for circular dependencies */ - while (pose->chanbase.first) { - pchan = pose->chanbase.first; - BLI_remlink(&pose->chanbase, pchan); - BLI_addhead(&tempbase, pchan); - - printf("cyclic %s\n", pchan->name); - } - - pose->chanbase = tempbase; - queue_delete(nqueue); - -// printf("\nordered\n"); -// for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) { -// printf(" %s\n", pchan->name); -// } - - free_forest(dag); - MEM_freeN(dag); -} - -/* ************************ DAG FOR THREADED UPDATE ********************* */ - -/* Initialize run-time data in the graph needed for traversing it - * from multiple threads and start threaded tree traversal by adding - * the root node to the queue. - * - * This will mark DAG nodes as object/non-object and will calculate - * num_pending_parents of nodes (which is how many non-updated parents node - * have, which helps a lot checking whether node could be scheduled - * already or not). - */ -void DAG_threaded_update_begin(Scene *scene, - void (*func)(void *node, void *user_data), - void *user_data) -{ - DagNode *node; - - /* We reset num_pending_parents to zero first and tag node as not scheduled yet... */ - for (node = scene->theDag->DagNode.first; node; node = node->next) { - node->num_pending_parents = 0; - node->scheduled = false; - } - - /* ... and then iterate over all the nodes and - * increase num_pending_parents for node childs. - */ - for (node = scene->theDag->DagNode.first; node; node = node->next) { - DagAdjList *itA; - - for (itA = node->child; itA; itA = itA->next) { - if (itA->node != node) { - itA->node->num_pending_parents++; - } - } - } - - /* Add root nodes to the queue. */ - BLI_spin_lock(&threaded_update_lock); - for (node = scene->theDag->DagNode.first; node; node = node->next) { - if (node->num_pending_parents == 0) { - node->scheduled = true; - func(node, user_data); - } - } - BLI_spin_unlock(&threaded_update_lock); -} - -/* This function is called when handling node is done. - * - * This function updates num_pending_parents for all childs and - * schedules them if they're ready. - */ -void DAG_threaded_update_handle_node_updated(void *node_v, - void (*func)(void *node, void *user_data), - void *user_data) -{ - DagNode *node = node_v; - DagAdjList *itA; - - for (itA = node->child; itA; itA = itA->next) { - DagNode *child_node = itA->node; - if (child_node != node) { - atomic_sub_and_fetch_uint32(&child_node->num_pending_parents, 1); - - if (child_node->num_pending_parents == 0) { - bool need_schedule; - - BLI_spin_lock(&threaded_update_lock); - need_schedule = child_node->scheduled == false; - child_node->scheduled = true; - BLI_spin_unlock(&threaded_update_lock); - - if (need_schedule) { - func(child_node, user_data); - } - } - } - } -} - -/* ************************ DAG DEBUGGING ********************* */ - -void DAG_print_dependencies(Main *bmain, Scene *scene, Object *ob) -{ - /* utility for debugging dependencies */ - dag_print_dependencies = 1; - - if (ob && (ob->mode & OB_MODE_POSE)) { - printf("\nDEPENDENCY RELATIONS for %s\n\n", ob->id.name + 2); - DAG_pose_sort(ob); - } - else { - printf("\nDEPENDENCY RELATIONS for %s\n\n", scene->id.name + 2); - DAG_scene_relations_rebuild(bmain, scene); - } - - dag_print_dependencies = 0; -} - -/* ************************ DAG querying ********************* */ - -/* Will return Object ID if node represents Object, - * and will return NULL otherwise. - */ -Object *DAG_get_node_object(void *node_v) -{ - DagNode *node = node_v; - - if (node->type == ID_OB) { - return node->ob; - } - - return NULL; -} - -/* Returns node name, used for debug output only, atm. */ -const char *DAG_get_node_name(Scene *scene, void *node_v) -{ - DagNode *node = node_v; - - return dag_node_name(scene->theDag, node); -} - -short DAG_get_eval_flags_for_object(Scene *scene, void *object) -{ - DagNode *node; - - if (!DEG_depsgraph_use_legacy()) { - return DEG_get_eval_flags_for_id(scene->depsgraph, (ID *)object); - } - - if (scene->theDag == NULL) { - /* Happens when converting objects to mesh from a python script - * after modifying scene graph. - * - * Currently harmless because it's only called for temporary - * objects which are out of the DAG anyway. - */ - return 0; - } - - node = dag_find_node(scene->theDag, object); - - if (node) { - return node->eval_flags; - } - else { - /* Happens when external render engine exports temporary objects - * which are not in the DAG. - */ - - /* TODO(sergey): Doublecheck objects with Curve Deform exports all fine. */ - - /* TODO(sergey): Weak but currently we can't really access proper DAG from - * the modifiers stack. This is because in most cases modifier is to use - * the foreground scene, but to access evaluation flags we need to know - * active background scene, which we don't know. - */ - if (scene->set) { - return DAG_get_eval_flags_for_object(scene->set, object); - } - return 0; - } -} - -bool DAG_is_acyclic(Scene *scene) -{ - return scene->theDag->is_acyclic; -} - -#else - -/* ********************************************************************* - * Stubs to avoid linking issues and make sure legacy crap is not used * - * ********************************************************************* - */ - -DagNodeQueue *queue_create(int UNUSED(slots)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); - return NULL; -} - -void queue_raz(DagNodeQueue *UNUSED(queue)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); -} - -void queue_delete(DagNodeQueue *UNUSED(queue)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); -} - -void push_queue(DagNodeQueue *UNUSED(queue), DagNode *UNUSED(node)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); -} - -void push_stack(DagNodeQueue *UNUSED(queue), DagNode *UNUSED(node)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); -} - -DagNode *pop_queue(DagNodeQueue *UNUSED(queue)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); - return NULL; -} - -DagNode *get_top_node_queue(DagNodeQueue *UNUSED(queue)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); - return NULL; -} - -DagForest *dag_init(void) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); - return NULL; -} - -DagForest *build_dag(Main *UNUSED(bmain), - Scene *UNUSED(sce), - short UNUSED(mask)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); - return NULL; -} - -void free_forest(DagForest *UNUSED(Dag)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); -} - -DagNode *dag_find_node(DagForest *UNUSED(forest), void *UNUSED(fob)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); - return NULL; -} - -DagNode *dag_add_node(DagForest *UNUSED(forest), void *UNUSED(fob)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); - return NULL; -} - -DagNode *dag_get_node(DagForest *UNUSED(forest), void *UNUSED(fob)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); - return NULL; -} - -DagNode *dag_get_sub_node(DagForest *UNUSED(forest), void *UNUSED(fob)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); - return NULL; -} - -void dag_add_relation(DagForest *UNUSED(forest), - DagNode *UNUSED(fob1), - DagNode *UNUSED(fob2), - short UNUSED(rel), - const char *UNUSED(name)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); -} - -/* debug test functions */ - -void graph_print_queue(DagNodeQueue *UNUSED(nqueue)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); -} - -void graph_print_queue_dist(DagNodeQueue *UNUSED(nqueue)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); -} - -void graph_print_adj_list(DagForest *UNUSED(dag)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); -} - -void DAG_scene_flush_update(Main *UNUSED(bmain), - Scene *UNUSED(sce), - unsigned int UNUSED(lay), - const short UNUSED(time)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); -} - -void DAG_scene_update_flags(Main *UNUSED(bmain), - Scene *UNUSED(scene), - unsigned int UNUSED(lay), - const bool UNUSED(do_time), - const bool UNUSED(do_invisible_flush)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); -} - -/* ******************* DAG FOR ARMATURE POSE ***************** */ - -void DAG_pose_sort(Object *UNUSED(ob)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); -} - -/* ************************ DAG FOR THREADED UPDATE ********************* */ - -void DAG_threaded_update_begin(Scene *UNUSED(scene), - void (*func)(void *node, void *user_data), - void *UNUSED(user_data)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); - (void)func; -} - -void DAG_threaded_update_handle_node_updated(void *UNUSED(node_v), - void (*func)(void *node, void *user_data), - void *UNUSED(user_data)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); - (void)func; -} - -/* ************************ DAG querying ********************* */ - -Object *DAG_get_node_object(void *UNUSED(node_v)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); - return NULL; -} - -const char *DAG_get_node_name(Scene *UNUSED(scene), void *UNUSED(node_v)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); - return "INVALID"; -} - -bool DAG_is_acyclic(Scene *UNUSED(scene)) -{ - BLI_assert(!"Should not be used with new dependnecy graph"); - return false; -} - -/* ************************************ - * This functions are to be supported * - * ************************************ - */ - -void DAG_init(void) -{ - DEG_register_node_types(); -} - -void DAG_exit(void) -{ - DEG_free_node_types(); -} - -/* ************************ API *********************** */ - -void DAG_editors_update_cb(DEG_EditorUpdateIDCb id_func, - DEG_EditorUpdateSceneCb scene_func, - DEG_EditorUpdateScenePreCb scene_func_pre) -{ - DEG_editors_set_update_cb(id_func, scene_func, scene_func_pre); -} - -void DAG_editors_update_pre(Main *bmain, Scene *scene, bool time) -{ - DEG_editors_update_pre(bmain, scene, time); -} - -/* Tag all relations for update. */ -void DAG_relations_tag_update(Main *bmain) -{ - DEG_relations_tag_update(bmain); -} - -/* Rebuild dependency graph only for a given scene. */ -void DAG_scene_relations_rebuild(Main *bmain, Scene *scene) -{ - DEG_scene_relations_rebuild(bmain, scene); -} - -/* Create dependency graph if it was cleared or didn't exist yet. */ -void DAG_scene_relations_update(Main *bmain, Scene *scene) -{ - DEG_scene_relations_update(bmain, scene); -} - -void DAG_scene_relations_validate(Main *bmain, Scene *scene) -{ - DEG_debug_scene_relations_validate(bmain, scene); -} - -void DAG_scene_free(Scene *scene) -{ - DEG_scene_graph_free(scene); -} - -void DAG_on_visible_update(Main *bmain, const bool do_time) -{ - DEG_on_visible_update(bmain, do_time); -} - -void DAG_ids_check_recalc(Main *bmain, Scene *scene, bool time) -{ - DEG_ids_check_recalc(bmain, scene, time); -} - -void DAG_id_tag_update(ID *id, short flag) -{ - DEG_id_tag_update_ex(G.main, id, flag); -} - -void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag) -{ - DEG_id_tag_update_ex(bmain, id, flag); -} - -void DAG_id_type_tag(Main *bmain, short idtype) -{ - DEG_id_type_tag(bmain, idtype); -} - -int DAG_id_type_tagged(Main *bmain, short idtype) -{ - return DEG_id_type_tagged(bmain, idtype); -} - -void DAG_ids_clear_recalc(Main *bmain) -{ - DEG_ids_clear_recalc(bmain); -} - -short DAG_get_eval_flags_for_object(Scene *scene, void *object) -{ - return DEG_get_eval_flags_for_id(scene->depsgraph, (ID *)object); -} - -void DAG_ids_flush_tagged(Main *bmain) -{ - DEG_ids_flush_tagged(bmain); -} - -/* ************************ DAG DEBUGGING ********************* */ - -void DAG_print_dependencies(Main *UNUSED(bmain), - Scene *scene, - Object *UNUSED(ob)) -{ - DEG_debug_relations_graphviz(scene->depsgraph, stdout, "Depsgraph"); -} - -#endif diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index 2a300cbe47b..15a520fe8ce 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -48,7 +48,6 @@ #include "BLI_utildefines.h" #include "BKE_global.h" -#include "BKE_depsgraph.h" #include "BKE_displist.h" #include "BKE_cdderivedmesh.h" #include "BKE_object.h" @@ -63,6 +62,9 @@ #include "BLI_sys_types.h" // for intptr_t support +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + static void boundbox_displist_object(Object *ob); void BKE_displist_elem_free(DispList *dl) @@ -676,7 +678,7 @@ static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dis * - first point left, last point right * - based on subdivided points in original curve, not on points in taper curve (still) */ -static float displist_calc_taper(Scene *scene, Object *taperobj, float fac) +static float displist_calc_taper(const EvaluationContext *eval_ctx, Scene *scene, Object *taperobj, float fac) { DispList *dl; @@ -685,7 +687,7 @@ static float displist_calc_taper(Scene *scene, Object *taperobj, float fac) dl = taperobj->curve_cache ? taperobj->curve_cache->disp.first : NULL; if (dl == NULL) { - BKE_displist_make_curveTypes(scene, taperobj, 0); + BKE_displist_make_curveTypes(eval_ctx, scene, taperobj, 0); dl = taperobj->curve_cache->disp.first; } if (dl) { @@ -716,14 +718,14 @@ static float displist_calc_taper(Scene *scene, Object *taperobj, float fac) return 1.0; } -float BKE_displist_calc_taper(Scene *scene, Object *taperobj, int cur, int tot) +float BKE_displist_calc_taper(const EvaluationContext *eval_ctx, Scene *scene, Object *taperobj, int cur, int tot) { float fac = ((float)cur) / (float)(tot - 1); - return displist_calc_taper(scene, taperobj, fac); + return displist_calc_taper(eval_ctx, scene, taperobj, fac); } -void BKE_displist_make_mball(EvaluationContext *eval_ctx, Scene *scene, Object *ob) +void BKE_displist_make_mball(const EvaluationContext *eval_ctx, Scene *scene, Object *ob) { if (!ob || ob->type != OB_MBALL) return; @@ -746,7 +748,7 @@ void BKE_displist_make_mball(EvaluationContext *eval_ctx, Scene *scene, Object * } } -void BKE_displist_make_mball_forRender(EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase) +void BKE_displist_make_mball_forRender(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase) { BKE_mball_polygonize(eval_ctx, scene, ob, dispbase); BKE_mball_texspace_calc(ob); @@ -796,8 +798,9 @@ static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob, return pretessellatePoint; } -static void curve_calc_modifiers_pre(Scene *scene, Object *ob, ListBase *nurb, - const bool for_render, const bool use_render_resolution) +static void curve_calc_modifiers_pre( + const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *nurb, + const bool for_render, const bool use_render_resolution) { VirtualModifierData virtualModifierData; ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); @@ -854,7 +857,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, ListBase *nurb, deformedVerts = BKE_curve_nurbs_vertexCos_get(nurb, &numVerts); } - mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, app_flag); + mti->deformVerts(md, eval_ctx, ob, NULL, deformedVerts, numVerts, app_flag); if (md == pretessellatePoint) break; @@ -906,9 +909,10 @@ static void displist_apply_allverts(ListBase *dispbase, float (*allverts)[3]) } } -static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *nurb, - ListBase *dispbase, DerivedMesh **r_dm_final, - const bool for_render, const bool use_render_resolution) +static void curve_calc_modifiers_post( + const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *nurb, + ListBase *dispbase, DerivedMesh **r_dm_final, + const bool for_render, const bool use_render_resolution) { VirtualModifierData virtualModifierData; ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); @@ -962,14 +966,14 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *nurb, dm->getVertCos(dm, vertCos); } - mti->deformVerts(md, ob, dm, vertCos, totvert, appf); + mti->deformVerts(md, eval_ctx, ob, dm, vertCos, totvert, appf); } else { if (!vertCos) { vertCos = displist_get_allverts(dispbase, &totvert); } - mti->deformVerts(md, ob, NULL, vertCos, totvert, appf); + mti->deformVerts(md, eval_ctx, ob, NULL, vertCos, totvert, appf); } } else { @@ -1011,7 +1015,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *nurb, if (useCache) appf |= MOD_APPLY_USECACHE; - ndm = modwrap_applyModifier(md, ob, dm, appf); + ndm = modwrap_applyModifier(md, eval_ctx, ob, dm, appf); if (ndm) { /* Modifier returned a new derived mesh */ @@ -1088,13 +1092,13 @@ static void displist_surf_indices(DispList *dl) } } -static DerivedMesh *create_orco_dm(Scene *scene, Object *ob) +static DerivedMesh *create_orco_dm(const EvaluationContext *eval_ctx, Scene *scene, Object *ob) { DerivedMesh *dm; ListBase disp = {NULL, NULL}; /* OrcoDM should be created from underformed disp lists */ - BKE_displist_make_curveTypes_forOrco(scene, ob, &disp); + BKE_displist_make_curveTypes_forOrco(eval_ctx, scene, ob, &disp); dm = CDDM_from_curve_displist(ob, &disp); BKE_displist_free(&disp); @@ -1132,8 +1136,9 @@ static void add_orco_dm(Object *ob, DerivedMesh *dm, DerivedMesh *orcodm) DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, orco); } -static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *dm_final, - const bool for_render, const bool use_render_resolution) +static void curve_calc_orcodm( + const EvaluationContext *eval_ctx, Scene *scene, Object *ob, DerivedMesh *dm_final, + const bool for_render, const bool use_render_resolution) { /* this function represents logic of mesh's orcodm calculation * for displist-based objects @@ -1170,7 +1175,7 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *dm_final, * This means we can create ORCO DM in advance and assume it's * never NULL. */ - orcodm = create_orco_dm(scene, ob); + orcodm = create_orco_dm(eval_ctx, scene, ob); for (; md; md = md->next) { const ModifierTypeInfo *mti = modifierType_getInfo(md->type); @@ -1182,7 +1187,7 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *dm_final, if (mti->type != eModifierTypeType_Constructive) continue; - ndm = modwrap_applyModifier(md, ob, orcodm, app_flag); + ndm = modwrap_applyModifier(md, eval_ctx, ob, orcodm, app_flag); if (ndm) { /* if the modifier returned a new dm, release the old one */ @@ -1199,9 +1204,10 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *dm_final, orcodm->release(orcodm); } -void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase, - DerivedMesh **r_dm_final, - const bool for_render, const bool for_orco, const bool use_render_resolution) +void BKE_displist_make_surf( + const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase, + DerivedMesh **r_dm_final, + const bool for_render, const bool for_orco, const bool use_render_resolution) { ListBase nubase = {NULL, NULL}; Nurb *nu; @@ -1218,7 +1224,7 @@ void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase, } if (!for_orco) - curve_calc_modifiers_pre(scene, ob, &nubase, for_render, use_render_resolution); + curve_calc_modifiers_pre(eval_ctx, scene, ob, &nubase, for_render, use_render_resolution); for (nu = nubase.first; nu; nu = nu->next) { if ((for_render || nu->hide == 0) && BKE_nurb_check_valid_uv(nu)) { @@ -1285,7 +1291,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, + curve_calc_modifiers_post(eval_ctx, scene, ob, &nubase, dispbase, r_dm_final, for_render, use_render_resolution); } @@ -1511,9 +1517,10 @@ static void calc_bevfac_mapping(Curve *cu, BevList *bl, Nurb *nu, } } -static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispbase, - DerivedMesh **r_dm_final, - const bool for_render, const bool for_orco, const bool use_render_resolution) +static void do_makeDispListCurveTypes( + const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase, + DerivedMesh **r_dm_final, + const bool for_render, const bool for_orco, const bool use_render_resolution) { Curve *cu = ob->data; @@ -1521,7 +1528,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba if (!ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return; if (ob->type == OB_SURF) { - BKE_displist_make_surf(scene, ob, dispbase, r_dm_final, for_render, for_orco, use_render_resolution); + BKE_displist_make_surf(eval_ctx, scene, ob, dispbase, r_dm_final, for_render, for_orco, use_render_resolution); } else if (ELEM(ob->type, OB_CURVE, OB_FONT)) { ListBase dlbev; @@ -1546,12 +1553,12 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba } if (!for_orco) - curve_calc_modifiers_pre(scene, ob, &nubase, for_render, use_render_resolution); + curve_calc_modifiers_pre(eval_ctx, scene, ob, &nubase, for_render, use_render_resolution); BKE_curve_bevelList_make(ob, &nubase, for_render != false); /* If curve has no bevel will return nothing */ - BKE_curve_bevel_make(scene, ob, &dlbev, for_render, use_render_resolution); + BKE_curve_bevel_make(eval_ctx, scene, ob, &dlbev, for_render, use_render_resolution); /* no bevel or extrude, and no width correction? */ if (!dlbev.first && cu->width == 1.0f) { @@ -1686,7 +1693,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba taper_fac -= (1.0f - lastblend) / len; } - fac = displist_calc_taper(scene, cu->taperobj, taper_fac); + fac = displist_calc_taper(eval_ctx, scene, cu->taperobj, taper_fac); } if (bevp->split_tag) { @@ -1739,7 +1746,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba if (!for_orco) { if ((cu->flag & CU_PATH) || - DAG_get_eval_flags_for_object(scene, ob) & DAG_EVAL_NEED_CURVE_PATH) + DEG_get_eval_flags_for_id(eval_ctx->depsgraph, &ob->id) & DAG_EVAL_NEED_CURVE_PATH) { calc_curvepath(ob, &nubase); } @@ -1747,7 +1754,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba 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); + curve_calc_modifiers_post(eval_ctx, scene, ob, &nubase, dispbase, r_dm_final, for_render, use_render_resolution); } if (cu->flag & CU_DEFORM_FILL && !ob->derivedFinal) { @@ -1758,7 +1765,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba } } -void BKE_displist_make_curveTypes(Scene *scene, Object *ob, const bool for_orco) +void BKE_displist_make_curveTypes(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, const bool for_orco) { ListBase *dispbase; @@ -1776,35 +1783,38 @@ void BKE_displist_make_curveTypes(Scene *scene, Object *ob, const bool for_orco) dispbase = &(ob->curve_cache->disp); - do_makeDispListCurveTypes(scene, ob, dispbase, &ob->derivedFinal, 0, for_orco, 0); + do_makeDispListCurveTypes(eval_ctx, scene, ob, dispbase, &ob->derivedFinal, 0, for_orco, 0); boundbox_displist_object(ob); } -void BKE_displist_make_curveTypes_forRender(Scene *scene, Object *ob, ListBase *dispbase, - DerivedMesh **r_dm_final, const bool for_orco, - const bool use_render_resolution) +void BKE_displist_make_curveTypes_forRender( + const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase, + DerivedMesh **r_dm_final, const bool for_orco, + const bool use_render_resolution) { if (ob->curve_cache == NULL) { ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve"); } - do_makeDispListCurveTypes(scene, ob, dispbase, r_dm_final, true, for_orco, use_render_resolution); + do_makeDispListCurveTypes(eval_ctx, scene, ob, dispbase, r_dm_final, true, for_orco, use_render_resolution); } -void BKE_displist_make_curveTypes_forOrco(struct Scene *scene, struct Object *ob, struct ListBase *dispbase) +void BKE_displist_make_curveTypes_forOrco( + const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase) { if (ob->curve_cache == NULL) { ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve"); } - do_makeDispListCurveTypes(scene, ob, dispbase, NULL, 1, 1, 1); + do_makeDispListCurveTypes(eval_ctx, scene, ob, dispbase, NULL, 1, 1, 1); } /* add Orco layer to the displist object which has got derived mesh and return orco */ -float *BKE_displist_make_orco(Scene *scene, Object *ob, DerivedMesh *dm_final, - const bool for_render, - const bool use_render_resolution) +float *BKE_displist_make_orco( + const EvaluationContext *eval_ctx, Scene *scene, Object *ob, DerivedMesh *dm_final, + const bool for_render, + const bool use_render_resolution) { float *orco; @@ -1812,7 +1822,7 @@ float *BKE_displist_make_orco(Scene *scene, Object *ob, DerivedMesh *dm_final, dm_final = ob->derivedFinal; if (!dm_final->getVertDataArray(dm_final, CD_ORCO)) { - curve_calc_orcodm(scene, ob, dm_final, for_render, use_render_resolution); + curve_calc_orcodm(eval_ctx, scene, ob, dm_final, for_render, use_render_resolution); } orco = dm_final->getVertDataArray(dm_final, CD_ORCO); diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c index 41a5d8574e6..2591c3c3c47 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -74,6 +74,8 @@ #include "BKE_pointcache.h" #include "BKE_scene.h" +#include "DEG_depsgraph.h" + /* for image output */ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -486,36 +488,27 @@ static void scene_setSubframe(Scene *scene, float subframe) scene->r.subframe = subframe; } -static int surface_getBrushFlags(DynamicPaintSurface *surface, const Scene *scene) +static int surface_getBrushFlags(DynamicPaintSurface *surface, const ViewLayer *view_layer) { Base *base = NULL; - GroupObject *go = NULL; Object *brushObj = NULL; ModifierData *md = NULL; int flags = 0; if (surface->brush_group) - go = surface->brush_group->gobject.first; + base = FIRSTBASE(surface->brush_group->view_layer); else - base = scene->base.first; + base = FIRSTBASE(view_layer); - while (base || go) { + while (base) { brushObj = NULL; /* select object */ - if (surface->brush_group) { - if (go->ob) - brushObj = go->ob; - } - else { - brushObj = base->object; - } + brushObj = base->object; - if (surface->brush_group) - go = go->next; - else - base = base->next; + /* next item */ + base = base->next; if (!brushObj) { continue; @@ -2071,7 +2064,9 @@ static void canvas_copyDerivedMesh(DynamicPaintCanvasSettings *canvas, DerivedMe /* * Updates derived mesh copy and processes dynamic paint step / caches. */ -static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd, Scene *scene, Object *ob, DerivedMesh *dm) +static void dynamicPaint_frameUpdate( + DynamicPaintModifierData *pmd, const struct EvaluationContext *eval_ctx, Scene *scene, + Object *ob, DerivedMesh *dm) { if (pmd->canvas) { DynamicPaintCanvasSettings *canvas = pmd->canvas; @@ -2134,7 +2129,7 @@ static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd, Scene *scene else if (can_simulate) { /* calculate surface frame */ canvas->flags |= MOD_DPAINT_BAKING; - dynamicPaint_calculateFrame(surface, scene, ob, current_frame); + dynamicPaint_calculateFrame(surface, eval_ctx, scene, ob, current_frame); canvas->flags &= ~MOD_DPAINT_BAKING; /* restore canvas derivedmesh if required */ @@ -2153,13 +2148,15 @@ static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd, Scene *scene } /* Modifier call. Processes dynamic paint modifier step. */ -DerivedMesh *dynamicPaint_Modifier_do(DynamicPaintModifierData *pmd, Scene *scene, Object *ob, DerivedMesh *dm) +DerivedMesh *dynamicPaint_Modifier_do( + DynamicPaintModifierData *pmd, const struct EvaluationContext *eval_ctx, Scene *scene, + Object *ob, DerivedMesh *dm) { if (pmd->canvas) { DerivedMesh *ret; /* Update canvas data for a new frame */ - dynamicPaint_frameUpdate(pmd, scene, ob, dm); + dynamicPaint_frameUpdate(pmd, eval_ctx, scene, ob, dm); /* Return output mesh */ ret = dynamicPaint_Modifier_apply(pmd, ob, dm); @@ -2168,7 +2165,7 @@ DerivedMesh *dynamicPaint_Modifier_do(DynamicPaintModifierData *pmd, Scene *scen } else { /* Update canvas data for a new frame */ - dynamicPaint_frameUpdate(pmd, scene, ob, dm); + dynamicPaint_frameUpdate(pmd, eval_ctx, scene, ob, dm); /* Return output mesh */ return dynamicPaint_Modifier_apply(pmd, ob, dm); @@ -3743,7 +3740,8 @@ static void dynamic_paint_brush_velocity_compute_cb( } static void dynamicPaint_brushMeshCalculateVelocity( - Scene *scene, Object *ob, DynamicPaintBrushSettings *brush, Vec3f **brushVel, float timescale) + const struct EvaluationContext *eval_ctx, Scene *scene, + Object *ob, DynamicPaintBrushSettings *brush, Vec3f **brushVel, float timescale) { float prev_obmat[4][4]; DerivedMesh *dm_p, *dm_c; @@ -3765,7 +3763,7 @@ static void dynamicPaint_brushMeshCalculateVelocity( scene->r.subframe = prev_sfra; BKE_object_modifier_update_subframe( - scene, ob, true, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint); + eval_ctx, scene, ob, true, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint); dm_p = CDDM_copy(brush->dm); numOfVerts_p = dm_p->getNumVerts(dm_p); mvert_p = dm_p->getVertArray(dm_p); @@ -3776,7 +3774,7 @@ static void dynamicPaint_brushMeshCalculateVelocity( scene->r.subframe = cur_sfra; BKE_object_modifier_update_subframe( - scene, ob, true, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint); + eval_ctx, scene, ob, true, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint); dm_c = brush->dm; numOfVerts_c = dm_c->getNumVerts(dm_c); mvert_c = dm_p->getVertArray(dm_c); @@ -3807,7 +3805,7 @@ static void dynamicPaint_brushMeshCalculateVelocity( } /* calculate velocity for object center point */ -static void dynamicPaint_brushObjectCalculateVelocity(Scene *scene, Object *ob, Vec3f *brushVel, float timescale) +static void dynamicPaint_brushObjectCalculateVelocity(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, Vec3f *brushVel, float timescale) { float prev_obmat[4][4]; float cur_loc[3] = {0.0f}, prev_loc[3] = {0.0f}; @@ -3826,14 +3824,14 @@ static void dynamicPaint_brushObjectCalculateVelocity(Scene *scene, Object *ob, scene->r.cfra = prev_fra; scene->r.subframe = prev_sfra; BKE_object_modifier_update_subframe( - scene, ob, false, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint); + eval_ctx, scene, ob, false, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint); copy_m4_m4(prev_obmat, ob->obmat); /* current frame dm */ scene->r.cfra = cur_fra; scene->r.subframe = cur_sfra; BKE_object_modifier_update_subframe( - scene, ob, false, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint); + eval_ctx, scene, ob, false, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint); /* calculate speed */ mul_m4_v3(prev_obmat, prev_loc); @@ -4205,7 +4203,7 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex( } } -static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, +static int dynamicPaint_paintMesh(const struct EvaluationContext *eval_ctx, DynamicPaintSurface *surface, DynamicPaintBrushSettings *brush, Object *brushOb, BrushMaterials *bMats, @@ -4221,7 +4219,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, const MLoop *mloop = NULL; if (brush->flags & MOD_DPAINT_USES_VELOCITY) - dynamicPaint_brushMeshCalculateVelocity(scene, brushOb, brush, &brushVelocity, timescale); + dynamicPaint_brushMeshCalculateVelocity(eval_ctx, scene, brushOb, brush, &brushVelocity, timescale); if (!brush->dm) return 0; @@ -4711,7 +4709,7 @@ static void dynamic_paint_paint_single_point_cb_ex( } static int dynamicPaint_paintSinglePoint( - DynamicPaintSurface *surface, float *pointCoord, DynamicPaintBrushSettings *brush, + const struct EvaluationContext *eval_ctx, DynamicPaintSurface *surface, float *pointCoord, DynamicPaintBrushSettings *brush, Object *brushOb, BrushMaterials *bMats, Scene *scene, float timescale) { PaintSurfaceData *sData = surface->data; @@ -4719,7 +4717,7 @@ static int dynamicPaint_paintSinglePoint( Vec3f brushVel; if (brush->flags & MOD_DPAINT_USES_VELOCITY) - dynamicPaint_brushObjectCalculateVelocity(scene, brushOb, &brushVel, timescale); + dynamicPaint_brushObjectCalculateVelocity(eval_ctx, scene, brushOb, &brushVel, timescale); const MVert *mvert = brush->dm->getVertArray(brush->dm); @@ -5041,7 +5039,7 @@ static void dynamic_paint_prepare_effect_cb( } static int dynamicPaint_prepareEffectStep( - DynamicPaintSurface *surface, Scene *scene, Object *ob, float **force, float timescale) + const struct EvaluationContext *eval_ctx, DynamicPaintSurface *surface, Scene *scene, Object *ob, float **force, float timescale) { double average_force = 0.0f; float shrink_speed = 0.0f, spread_speed = 0.0f; @@ -5052,7 +5050,7 @@ static int dynamicPaint_prepareEffectStep( /* Init force data if required */ if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) { - ListBase *effectors = pdInitEffectors(scene, ob, NULL, surface->effector_weights, true); + ListBase *effectors = pdInitEffectors(eval_ctx, scene, ob, NULL, surface->effector_weights, true); /* allocate memory for force data (dir vector + strength) */ *force = MEM_mallocN(sData->total_points * 4 * sizeof(float), "PaintEffectForces"); @@ -5884,7 +5882,7 @@ static void dynamic_paint_generate_bake_data_cb( } } -static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, const Scene *scene, Object *ob) +static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, const ViewLayer *view_layer, Object *ob) { PaintSurfaceData *sData = surface->data; PaintBakeData *bData = sData->bData; @@ -5892,7 +5890,7 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, const Sce int index; bool new_bdata = false; const bool do_velocity_data = ((surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) || - (surface_getBrushFlags(surface, scene) & BRUSH_USES_VELOCITY)); + (surface_getBrushFlags(surface, view_layer) & BRUSH_USES_VELOCITY)); const bool do_accel_data = (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) != 0; int canvasNumOfVerts = dm->getNumVerts(dm); @@ -6009,7 +6007,7 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, const Sce /* * Do Dynamic Paint step. Paints scene brush objects of current state/frame to the surface. */ -static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *surface, float timescale, float subframe) +static int dynamicPaint_doStep(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, DynamicPaintSurface *surface, float timescale, float subframe) { PaintSurfaceData *sData = surface->data; PaintBakeData *bData = sData->bData; @@ -6035,9 +6033,9 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su */ { Base *base = NULL; - GroupObject *go = NULL; Object *brushObj = NULL; ModifierData *md = NULL; + ViewLayer *view_layer = eval_ctx->view_layer; /* backup current scene frame */ int scene_frame = scene->r.cfra; @@ -6045,25 +6043,17 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su /* either from group or from all objects */ if (surface->brush_group) - go = surface->brush_group->gobject.first; + base = FIRSTBASE(surface->brush_group->view_layer); else - base = scene->base.first; + base = FIRSTBASE(view_layer); - while (base || go) { + while (base) { brushObj = NULL; /* select object */ - if (surface->brush_group) { - if (go->ob) - brushObj = go->ob; - } - else - brushObj = base->object; + brushObj = base->object; /* next item */ - if (surface->brush_group) - go = go->next; - else - base = base->next; + base = base->next; if (!brushObj) { /* skip item */ @@ -6092,7 +6082,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su /* update object data on this subframe */ if (subframe) { scene_setSubframe(scene, subframe); - BKE_object_modifier_update_subframe(scene, brushObj, true, SUBFRAME_RECURSION, + BKE_object_modifier_update_subframe(eval_ctx, scene, brushObj, true, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint); } /* Prepare materials if required */ @@ -6100,8 +6090,6 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su dynamicPaint_updateBrushMaterials(brushObj, brush->mat, scene, &bMats); /* Apply brush on the surface depending on it's collision type */ - /* Particle brush: */ - if (brush->collision == MOD_DPAINT_COL_PSYS) { if (brush->psys && brush->psys->part && ELEM(brush->psys->part->type, PART_EMITTER, PART_FLUID) && psys_check_enabled(brushObj, brush->psys, G.is_rendering)) @@ -6111,14 +6099,13 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su BKE_scene_frame_get(scene), ADT_RECALC_ANIM); dynamicPaint_paintParticles(surface, brush->psys, brush, timescale); } - } /* Object center distance: */ - else if (brush->collision == MOD_DPAINT_COL_POINT && brushObj != ob) { - dynamicPaint_paintSinglePoint(surface, brushObj->loc, brush, brushObj, &bMats, scene, timescale); + if (brush->collision == MOD_DPAINT_COL_POINT && brushObj != ob) { + dynamicPaint_paintSinglePoint(eval_ctx, surface, brushObj->loc, brush, brushObj, &bMats, scene, timescale); } /* Mesh volume/proximity: */ else if (brushObj != ob) { - dynamicPaint_paintMesh(surface, brush, brushObj, &bMats, scene, timescale); + dynamicPaint_paintMesh(eval_ctx, surface, brush, brushObj, &bMats, scene, timescale); } /* free temp material data */ @@ -6128,7 +6115,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su if (subframe) { scene->r.cfra = scene_frame; scene->r.subframe = scene_subframe; - BKE_object_modifier_update_subframe(scene, brushObj, true, SUBFRAME_RECURSION, + BKE_object_modifier_update_subframe(eval_ctx, scene, brushObj, true, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint); } @@ -6163,7 +6150,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su return setError(canvas, N_("Not enough free memory")); /* Prepare effects and get number of required steps */ - steps = dynamicPaint_prepareEffectStep(surface, scene, ob, &force, timescale); + steps = dynamicPaint_prepareEffectStep(eval_ctx, surface, scene, ob, &force, timescale); for (s = 0; s < steps; s++) { dynamicPaint_doEffectStep(surface, force, prevPoint, timescale, (float)steps); } @@ -6187,7 +6174,9 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su /* * Calculate a single frame and included subframes for surface */ -int dynamicPaint_calculateFrame(DynamicPaintSurface *surface, Scene *scene, Object *cObject, int frame) +int dynamicPaint_calculateFrame( + DynamicPaintSurface *surface, const struct EvaluationContext *eval_ctx, + Scene *scene, Object *cObject, int frame) { float timescale = 1.0f; @@ -6196,7 +6185,7 @@ int dynamicPaint_calculateFrame(DynamicPaintSurface *surface, Scene *scene, Obje dynamicPaint_applySurfaceDisplace(surface, surface->canvas->dm); /* update bake data */ - dynamicPaint_generateBakeData(surface, scene, cObject); + dynamicPaint_generateBakeData(surface, eval_ctx->view_layer, cObject); /* don't do substeps for first frame */ if (surface->substeps && (frame != surface->start_frame)) { @@ -6205,10 +6194,10 @@ int dynamicPaint_calculateFrame(DynamicPaintSurface *surface, Scene *scene, Obje for (st = 1; st <= surface->substeps; st++) { float subframe = ((float) st) / (surface->substeps + 1); - if (!dynamicPaint_doStep(scene, cObject, surface, timescale, subframe)) + if (!dynamicPaint_doStep(eval_ctx, scene, cObject, surface, timescale, subframe)) return 0; } } - return dynamicPaint_doStep(scene, cObject, surface, timescale, 0.0f); + return dynamicPaint_doStep(eval_ctx, scene, cObject, surface, timescale, 0.0f); } diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index be8fcaa6863..0491cbd21f0 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -52,6 +52,7 @@ #include "BKE_mesh.h" #include "BKE_editmesh.h" #include "BKE_editmesh_bvh.h" +#include "BKE_editmesh_tangent.h" #include "DNA_scene_types.h" #include "DNA_object_types.h" @@ -242,392 +243,29 @@ static void emDM_calcLoopNormalsSpaceArray( #endif } - -/** \name Tangent Space Calculation - * \{ */ - -/* Necessary complexity to handle looptri's as quads for correct tangents */ -#define USE_LOOPTRI_DETECT_QUADS - -typedef struct { - const float (*precomputedFaceNormals)[3]; - const float (*precomputedLoopNormals)[3]; - const BMLoop *(*looptris)[3]; - int cd_loop_uv_offset; /* texture coordinates */ - const float (*orco)[3]; - float (*tangent)[4]; /* destination */ - int numTessFaces; - -#ifdef USE_LOOPTRI_DETECT_QUADS - /* map from 'fake' face index to looptri, - * quads will point to the first looptri of the quad */ - const int *face_as_quad_map; - int num_face_as_quad_map; -#endif - -} SGLSLEditMeshToTangent; - -#ifdef USE_LOOPTRI_DETECT_QUADS -/* seems weak but only used on quads */ -static const BMLoop *bm_loop_at_face_index(const BMFace *f, int vert_index) -{ - const BMLoop *l = BM_FACE_FIRST_LOOP(f); - while (vert_index--) { - l = l->next; - } - return l; -} -#endif - -/* interface */ -#include "mikktspace.h" - -static int emdm_ts_GetNumFaces(const SMikkTSpaceContext *pContext) -{ - SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData; - -#ifdef USE_LOOPTRI_DETECT_QUADS - return pMesh->num_face_as_quad_map; -#else - return pMesh->numTessFaces; -#endif -} - -static int emdm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num) -{ -#ifdef USE_LOOPTRI_DETECT_QUADS - SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData; - if (pMesh->face_as_quad_map) { - const BMLoop **lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]]; - if (lt[0]->f->len == 4) { - return 4; - } - } - return 3; -#else - UNUSED_VARS(pContext, face_num); - return 3; -#endif -} - -static void emdm_ts_GetPosition( - const SMikkTSpaceContext *pContext, float r_co[3], - const int face_num, const int vert_index) -{ - //assert(vert_index >= 0 && vert_index < 4); - SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData; - const BMLoop **lt; - const BMLoop *l; - -#ifdef USE_LOOPTRI_DETECT_QUADS - if (pMesh->face_as_quad_map) { - lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]]; - if (lt[0]->f->len == 4) { - l = bm_loop_at_face_index(lt[0]->f, vert_index); - goto finally; - } - /* fall through to regular triangle */ - } - else { - lt = pMesh->looptris[face_num]; - } -#else - lt = pMesh->looptris[face_num]; -#endif - l = lt[vert_index]; - - const float *co; - -finally: - co = l->v->co; - copy_v3_v3(r_co, co); -} - -static void emdm_ts_GetTextureCoordinate( - const SMikkTSpaceContext *pContext, float r_uv[2], - const int face_num, const int vert_index) -{ - //assert(vert_index >= 0 && vert_index < 4); - SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData; - const BMLoop **lt; - const BMLoop *l; - -#ifdef USE_LOOPTRI_DETECT_QUADS - if (pMesh->face_as_quad_map) { - lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]]; - if (lt[0]->f->len == 4) { - l = bm_loop_at_face_index(lt[0]->f, vert_index); - goto finally; - } - /* fall through to regular triangle */ - } - else { - lt = pMesh->looptris[face_num]; - } -#else - lt = pMesh->looptris[face_num]; -#endif - l = lt[vert_index]; - -finally: - if (pMesh->cd_loop_uv_offset != -1) { - const float *uv = BM_ELEM_CD_GET_VOID_P(l, pMesh->cd_loop_uv_offset); - copy_v2_v2(r_uv, uv); - } - else { - const float *orco = pMesh->orco[BM_elem_index_get(l->v)]; - map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]); - } -} - -static void emdm_ts_GetNormal( - const SMikkTSpaceContext *pContext, float r_no[3], - const int face_num, const int vert_index) -{ - //assert(vert_index >= 0 && vert_index < 4); - SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData; - const BMLoop **lt; - const BMLoop *l; - -#ifdef USE_LOOPTRI_DETECT_QUADS - if (pMesh->face_as_quad_map) { - lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]]; - if (lt[0]->f->len == 4) { - l = bm_loop_at_face_index(lt[0]->f, vert_index); - goto finally; - } - /* fall through to regular triangle */ - } - else { - lt = pMesh->looptris[face_num]; - } -#else - lt = pMesh->looptris[face_num]; -#endif - l = lt[vert_index]; - -finally: - if (pMesh->precomputedLoopNormals) { - copy_v3_v3(r_no, pMesh->precomputedLoopNormals[BM_elem_index_get(l)]); - } - else if (BM_elem_flag_test(l->f, BM_ELEM_SMOOTH) == 0) { /* flat */ - if (pMesh->precomputedFaceNormals) { - copy_v3_v3(r_no, pMesh->precomputedFaceNormals[BM_elem_index_get(l->f)]); - } - else { - copy_v3_v3(r_no, l->f->no); - } - } - else { - copy_v3_v3(r_no, l->v->no); - } -} - -static void emdm_ts_SetTSpace( - const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign, - const int face_num, const int vert_index) -{ - //assert(vert_index >= 0 && vert_index < 4); - SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData; - const BMLoop **lt; - const BMLoop *l; - -#ifdef USE_LOOPTRI_DETECT_QUADS - if (pMesh->face_as_quad_map) { - lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]]; - if (lt[0]->f->len == 4) { - l = bm_loop_at_face_index(lt[0]->f, vert_index); - goto finally; - } - /* fall through to regular triangle */ - } - else { - lt = pMesh->looptris[face_num]; - } -#else - lt = pMesh->looptris[face_num]; -#endif - l = lt[vert_index]; - - float *pRes; - -finally: - pRes = pMesh->tangent[BM_elem_index_get(l)]; - copy_v3_v3(pRes, fvTangent); - pRes[3] = fSign; -} - -static void emDM_calc_loop_tangents_thread(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid)) -{ - struct SGLSLEditMeshToTangent *mesh2tangent = taskdata; - /* new computation method */ - { - SMikkTSpaceContext sContext = {NULL}; - SMikkTSpaceInterface sInterface = {NULL}; - sContext.m_pUserData = mesh2tangent; - sContext.m_pInterface = &sInterface; - sInterface.m_getNumFaces = emdm_ts_GetNumFaces; - sInterface.m_getNumVerticesOfFace = emdm_ts_GetNumVertsOfFace; - sInterface.m_getPosition = emdm_ts_GetPosition; - sInterface.m_getTexCoord = emdm_ts_GetTextureCoordinate; - sInterface.m_getNormal = emdm_ts_GetNormal; - sInterface.m_setTSpaceBasic = emdm_ts_SetTSpace; - /* 0 if failed */ - genTangSpaceDefault(&sContext); - } -} - -/** - * \see #DM_calc_loop_tangents, same logic but used arrays instead of #BMesh data. - * - * \note This function is not so normal, its using `bm->ldata` as input, but output's to `dm->loopData`. - * This is done because #CD_TANGENT is cache data used only for drawing. - */ - static void emDM_calc_loop_tangents( DerivedMesh *dm, bool calc_active_tangent, - const char (*tangent_names)[MAX_NAME], int tangent_names_count) + const char (*tangent_names)[MAX_NAME], int tangent_names_len) { EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; BMEditMesh *em = bmdm->em; - BMesh *bm = bmdm->em->bm; - - int act_uv_n = -1; - int ren_uv_n = -1; - bool calc_act = false; - bool calc_ren = false; - char act_uv_name[MAX_NAME]; - char ren_uv_name[MAX_NAME]; - short tangent_mask = 0; - - DM_calc_loop_tangents_step_0( - &bm->ldata, calc_active_tangent, tangent_names, tangent_names_count, - &calc_act, &calc_ren, &act_uv_n, &ren_uv_n, act_uv_name, ren_uv_name, &tangent_mask); - - if ((dm->tangent_mask | tangent_mask) != dm->tangent_mask) { - for (int i = 0; i < tangent_names_count; i++) - if (tangent_names[i][0]) - DM_add_named_tangent_layer_for_uv(&bm->ldata, &dm->loopData, dm->numLoopData, tangent_names[i]); - if ((tangent_mask & DM_TANGENT_MASK_ORCO) && CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, "") == -1) - CustomData_add_layer_named(&dm->loopData, CD_TANGENT, CD_CALLOC, NULL, dm->numLoopData, ""); - if (calc_act && act_uv_name[0]) - DM_add_named_tangent_layer_for_uv(&bm->ldata, &dm->loopData, dm->numLoopData, act_uv_name); - if (calc_ren && ren_uv_name[0]) - DM_add_named_tangent_layer_for_uv(&bm->ldata, &dm->loopData, dm->numLoopData, ren_uv_name); - int totface = em->tottri; -#ifdef USE_LOOPTRI_DETECT_QUADS - int num_face_as_quad_map; - int *face_as_quad_map = NULL; - - /* map faces to quads */ - if (bmdm->em->tottri != bm->totface) { - /* over alloc, since we dont know how many ngon or quads we have */ - - /* map fake face index to looptri */ - face_as_quad_map = MEM_mallocN(sizeof(int) * totface, __func__); - int i, j; - for (i = 0, j = 0; j < totface; i++, j++) { - face_as_quad_map[i] = j; - /* step over all quads */ - if (em->looptris[j][0]->f->len == 4) { - j++; /* skips the nest looptri */ - } - } - num_face_as_quad_map = i; - } - else { - num_face_as_quad_map = totface; - } -#endif - /* Calculation */ - { - TaskScheduler *scheduler = BLI_task_scheduler_get(); - TaskPool *task_pool; - task_pool = BLI_task_pool_create(scheduler, NULL); - - dm->tangent_mask = 0; - /* Calculate tangent layers */ - SGLSLEditMeshToTangent data_array[MAX_MTFACE]; - int index = 0; - int n = 0; - CustomData_update_typemap(&dm->loopData); - const int tangent_layer_num = CustomData_number_of_layers(&dm->loopData, CD_TANGENT); - for (n = 0; n < tangent_layer_num; n++) { - index = CustomData_get_layer_index_n(&dm->loopData, CD_TANGENT, n); - BLI_assert(n < MAX_MTFACE); - SGLSLEditMeshToTangent *mesh2tangent = &data_array[n]; - mesh2tangent->numTessFaces = em->tottri; -#ifdef USE_LOOPTRI_DETECT_QUADS - mesh2tangent->face_as_quad_map = face_as_quad_map; - mesh2tangent->num_face_as_quad_map = num_face_as_quad_map; -#endif - mesh2tangent->precomputedFaceNormals = bmdm->polyNos; /* dm->getPolyDataArray(dm, CD_NORMAL) */ - /* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled), - * have to check this is valid... - */ - mesh2tangent->precomputedLoopNormals = CustomData_get_layer(&dm->loopData, CD_NORMAL); - mesh2tangent->cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, n); - - /* needed for indexing loop-tangents */ - int htype_index = BM_LOOP; - if (mesh2tangent->cd_loop_uv_offset == -1) { - mesh2tangent->orco = dm->getVertDataArray(dm, CD_ORCO); - if (!mesh2tangent->orco) - continue; - /* needed for orco lookups */ - htype_index |= BM_VERT; - dm->tangent_mask |= DM_TANGENT_MASK_ORCO; - } - else { - /* Fill the resulting tangent_mask */ - int uv_ind = CustomData_get_named_layer_index(&bm->ldata, CD_MLOOPUV, dm->loopData.layers[index].name); - int uv_start = CustomData_get_layer_index(&bm->ldata, CD_MLOOPUV); - BLI_assert(uv_ind != -1 && uv_start != -1); - BLI_assert(uv_ind - uv_start < MAX_MTFACE); - dm->tangent_mask |= 1 << (uv_ind - uv_start); - } - - if (mesh2tangent->precomputedFaceNormals) { - /* needed for face normal lookups */ - htype_index |= BM_FACE; - } - BM_mesh_elem_index_ensure(bm, htype_index); - mesh2tangent->looptris = (const BMLoop *(*)[3])em->looptris; - mesh2tangent->tangent = dm->loopData.layers[index].data; - - BLI_task_pool_push(task_pool, emDM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW); - } - - BLI_assert(dm->tangent_mask == tangent_mask); - BLI_task_pool_work_and_wait(task_pool); - BLI_task_pool_free(task_pool); - } -#ifdef USE_LOOPTRI_DETECT_QUADS - if (face_as_quad_map) { - MEM_freeN(face_as_quad_map); - } -#undef USE_LOOPTRI_DETECT_QUADS -#endif + if (CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPUV) == 0) { + return; } - /* Update active layer index */ - int act_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, act_uv_n); - if (act_uv_index >= 0) { - int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, bm->ldata.layers[act_uv_index].name); - CustomData_set_layer_active_index(&dm->loopData, CD_TANGENT, tan_index); - } /* else tangent has been built from orco */ - - /* Update render layer index */ - int ren_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, ren_uv_n); - if (ren_uv_index >= 0) { - int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, bm->ldata.layers[ren_uv_index].name); - CustomData_set_layer_render_index(&dm->loopData, CD_TANGENT, tan_index); - } /* else tangent has been built from orco */ + const float (*poly_normals)[3] = bmdm->polyNos; + const float (*loop_normals)[3] = CustomData_get_layer(&dm->loopData, CD_NORMAL); + const float (*vert_orco)[3] = dm->getVertDataArray(dm, CD_ORCO); /* can be NULL */ + BKE_editmesh_loop_tangent_calc( + em, calc_active_tangent, + tangent_names, tangent_names_len, + poly_normals, loop_normals, + vert_orco, + &dm->loopData, dm->numLoopData, + &dm->tangent_mask); } -/** \} */ - static void emDM_recalcTessellation(DerivedMesh *UNUSED(dm)) { @@ -816,39 +454,6 @@ static void emDM_drawMappedEdgesInterp( } } -static void emDM_drawUVEdges(DerivedMesh *dm) -{ - EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; - BMesh *bm = bmdm->em->bm; - BMFace *efa; - BMIter iter; - - const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - - if (UNLIKELY(cd_loop_uv_offset == -1)) { - return; - } - - glBegin(GL_LINES); - BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) { - BMLoop *l_iter, *l_first; - const float *uv, *uv_prev; - - if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN)) - continue; - - l_iter = l_first = BM_FACE_FIRST_LOOP(efa); - uv_prev = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter->prev, cd_loop_uv_offset))->uv; - do { - uv = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset))->uv; - glVertex2fv(uv); - glVertex2fv(uv_prev); - uv_prev = uv; - } while ((l_iter = l_iter->next) != l_first); - } - glEnd(); -} - static void emDM_foreachMappedLoop( DerivedMesh *dm, void (*func)(void *userData, int vertex_index, int face_index, const float co[3], const float no[3]), @@ -1036,11 +641,11 @@ static void emDM_drawMappedFaces( if (poly_prev != GL_ZERO) glEnd(); glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */ } - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r)); + if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r)); glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); + if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r)); glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); + if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r)); glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]); } else { @@ -1057,23 +662,23 @@ static void emDM_drawMappedFaces( if (!drawSmooth) { glNormal3fv(polyNos[BM_elem_index_get(efa)]); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r)); + if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r)); glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); + if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r)); glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); + if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r)); glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]); } else { - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r)); + if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r)); if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]); else glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]); glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); + if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r)); if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]); else glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]); glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); + if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r)); if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]); else glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]); glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]); @@ -1138,11 +743,11 @@ static void emDM_drawMappedFaces( if (poly_prev != GL_ZERO) glEnd(); glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */ } - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r)); + if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r)); glVertex3fv(ltri[0]->v->co); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); + if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r)); glVertex3fv(ltri[1]->v->co); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); + if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r)); glVertex3fv(ltri[2]->v->co); } else { @@ -1159,23 +764,23 @@ static void emDM_drawMappedFaces( if (!drawSmooth) { glNormal3fv(efa->no); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r)); + if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r)); glVertex3fv(ltri[0]->v->co); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); + if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r)); glVertex3fv(ltri[1]->v->co); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); + if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r)); glVertex3fv(ltri[2]->v->co); } else { - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r)); + if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r)); if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]); else glNormal3fv(ltri[0]->v->no); glVertex3fv(ltri[0]->v->co); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); + if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r)); if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]); else glNormal3fv(ltri[1]->v->no); glVertex3fv(ltri[1]->v->co); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); + if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r)); if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]); else glNormal3fv(ltri[2]->v->no); glVertex3fv(ltri[2]->v->co); @@ -1197,20 +802,6 @@ static void emDM_drawMappedFaces( } } -static void bmdm_get_tri_uv(BMLoop *ltri[3], MLoopUV *luv[3], const int cd_loop_uv_offset) -{ - luv[0] = BM_ELEM_CD_GET_VOID_P(ltri[0], cd_loop_uv_offset); - luv[1] = BM_ELEM_CD_GET_VOID_P(ltri[1], cd_loop_uv_offset); - luv[2] = BM_ELEM_CD_GET_VOID_P(ltri[2], cd_loop_uv_offset); -} - -static void bmdm_get_tri_col(BMLoop *ltri[3], MLoopCol *lcol[3], const int cd_loop_color_offset) -{ - lcol[0] = BM_ELEM_CD_GET_VOID_P(ltri[0], cd_loop_color_offset); - lcol[1] = BM_ELEM_CD_GET_VOID_P(ltri[1], cd_loop_color_offset); - lcol[2] = BM_ELEM_CD_GET_VOID_P(ltri[2], cd_loop_color_offset); -} - static void bmdm_get_tri_colpreview(BMLoop *ls[3], MLoopCol *lcol[3], unsigned char(*color_vert_array)[4]) { lcol[0] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[0]->v)]; @@ -1218,204 +809,6 @@ static void bmdm_get_tri_colpreview(BMLoop *ls[3], MLoopCol *lcol[3], unsigned c lcol[2] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[2]->v)]; } -static void emDM_drawFacesTex_common( - DerivedMesh *dm, - DMSetDrawOptionsTex drawParams, - DMSetDrawOptionsMappedTex drawParamsMapped, - DMCompareDrawOptions compareDrawOptions, - void *userData) -{ - EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; - BMEditMesh *em = bmdm->em; - BMesh *bm = em->bm; - struct BMLoop *(*looptris)[3] = em->looptris; - BMFace *efa; - const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL); - MLoopUV *luv[3], dummyluv = {{0}}; - MLoopCol *lcol[3] = {NULL} /* , dummylcol = {0} */; - const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - const int cd_loop_color_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL); - const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY); - unsigned char(*color_vert_array)[4] = em->derivedVertColor; - bool has_uv = (cd_loop_uv_offset != -1); - bool has_vcol_preview = (color_vert_array != NULL); - bool has_vcol = (cd_loop_color_offset != -1) && (has_vcol_preview == false); - bool has_vcol_any = (has_vcol_preview || has_vcol); - int i; - - (void) compareDrawOptions; - - luv[0] = luv[1] = luv[2] = &dummyluv; - - // dummylcol.r = dummylcol.g = dummylcol.b = dummylcol.a = 255; /* UNUSED */ - - /* always use smooth shading even for flat faces, else vertex colors wont interpolate */ - BM_mesh_elem_index_ensure(bm, BM_FACE); - - /* call again below is ok */ - if (has_vcol_preview) { - BM_mesh_elem_index_ensure(bm, BM_VERT); - } - - if (bmdm->vertexCos) { - /* add direct access */ - const float (*vertexCos)[3] = bmdm->vertexCos; - const float (*vertexNos)[3]; - const float (*polyNos)[3]; - - emDM_ensureVertNormals(bmdm); - emDM_ensurePolyNormals(bmdm); - vertexNos = bmdm->vertexNos; - polyNos = bmdm->polyNos; - - BM_mesh_elem_index_ensure(bm, lnors ? BM_LOOP | BM_VERT : BM_VERT); - - for (i = 0; i < em->tottri; i++) { - BMLoop **ltri = looptris[i]; - MTexPoly *tp = (cd_poly_tex_offset != -1) ? BM_ELEM_CD_GET_VOID_P(ltri[0]->f, cd_poly_tex_offset) : NULL; - /*unsigned char *cp = NULL;*/ /*UNUSED*/ - int drawSmooth = lnors || BM_elem_flag_test(ltri[0]->f, BM_ELEM_SMOOTH); - DMDrawOption draw_option; - - efa = ltri[0]->f; - - if (drawParams) { - draw_option = drawParams(tp, has_vcol, efa->mat_nr); - } - else if (drawParamsMapped) - draw_option = drawParamsMapped(userData, BM_elem_index_get(efa), efa->mat_nr); - else - draw_option = DM_DRAW_OPTION_NORMAL; - - if (draw_option != DM_DRAW_OPTION_SKIP) { - - if (has_uv) bmdm_get_tri_uv(ltri, luv, cd_loop_uv_offset); - if (has_vcol) bmdm_get_tri_col(ltri, lcol, cd_loop_color_offset); - else if (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array); - - glBegin(GL_TRIANGLES); - if (!drawSmooth) { - glNormal3fv(polyNos[BM_elem_index_get(efa)]); - - glTexCoord2fv(luv[0]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r)); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]); - - glTexCoord2fv(luv[1]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]); - - glTexCoord2fv(luv[2]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]); - } - else { - glTexCoord2fv(luv[0]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r)); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]); - else glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]); - - glTexCoord2fv(luv[1]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]); - else glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]); - - glTexCoord2fv(luv[2]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]); - else glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]); - } - glEnd(); - } - } - } - else { - BM_mesh_elem_index_ensure(bm, lnors ? BM_LOOP | BM_VERT : BM_VERT); - - for (i = 0; i < em->tottri; i++) { - BMLoop **ltri = looptris[i]; - MTexPoly *tp = (cd_poly_tex_offset != -1) ? BM_ELEM_CD_GET_VOID_P(ltri[0]->f, cd_poly_tex_offset) : NULL; - /*unsigned char *cp = NULL;*/ /*UNUSED*/ - int drawSmooth = lnors || BM_elem_flag_test(ltri[0]->f, BM_ELEM_SMOOTH); - DMDrawOption draw_option; - - efa = ltri[0]->f; - - if (drawParams) - draw_option = drawParams(tp, has_vcol, efa->mat_nr); - else if (drawParamsMapped) - draw_option = drawParamsMapped(userData, BM_elem_index_get(efa), efa->mat_nr); - else - draw_option = DM_DRAW_OPTION_NORMAL; - - if (draw_option != DM_DRAW_OPTION_SKIP) { - - if (has_uv) bmdm_get_tri_uv(ltri, luv, cd_loop_uv_offset); - if (has_vcol) bmdm_get_tri_col(ltri, lcol, cd_loop_color_offset); - else if (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array); - - glBegin(GL_TRIANGLES); - if (!drawSmooth) { - glNormal3fv(efa->no); - - glTexCoord2fv(luv[0]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r)); - glVertex3fv(ltri[0]->v->co); - - glTexCoord2fv(luv[1]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); - glVertex3fv(ltri[1]->v->co); - - glTexCoord2fv(luv[2]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); - glVertex3fv(ltri[2]->v->co); - } - else { - glTexCoord2fv(luv[0]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r)); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]); - else glNormal3fv(ltri[0]->v->no); - glVertex3fv(ltri[0]->v->co); - - glTexCoord2fv(luv[1]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]); - else glNormal3fv(ltri[1]->v->no); - glVertex3fv(ltri[1]->v->co); - - glTexCoord2fv(luv[2]->uv); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]); - else glNormal3fv(ltri[2]->v->no); - glVertex3fv(ltri[2]->v->co); - } - glEnd(); - } - } - } -} - -static void emDM_drawFacesTex( - DerivedMesh *dm, - DMSetDrawOptionsTex setDrawOptions, - DMCompareDrawOptions compareDrawOptions, - void *userData, DMDrawFlag UNUSED(flag)) -{ - emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData); -} - -static void emDM_drawMappedFacesTex( - DerivedMesh *dm, - DMSetDrawOptionsMappedTex setDrawOptions, - DMCompareDrawOptions compareDrawOptions, - void *userData, DMDrawFlag UNUSED(flag)) -{ - emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData); -} - /** * \note * @@ -2061,14 +1454,8 @@ static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type) if (type == CD_MTFACE || type == CD_MCOL) { const char *bmdata; char *data; - bool has_type_source = false; - if (type == CD_MTFACE) { - has_type_source = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY); - } - else { - has_type_source = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL); - } + bool has_type_source = CustomData_has_layer(&bm->ldata, (type == CD_MTFACE) ? CD_MLOOPUV : CD_MLOOPCOL); if (has_type_source) { /* offset = bm->pdata.layers[index].offset; */ /* UNUSED */ @@ -2084,15 +1471,8 @@ static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type) if (type == CD_MTFACE) { const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV); - const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY); for (i = 0; i < bmdm->em->tottri; i++, data += size) { - BMFace *efa = looptris[i][0]->f; - - // bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY); - bmdata = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset); - - ME_MTEXFACE_CPY(((MTFace *)data), ((const MTexPoly *)bmdata)); for (j = 0; j < 3; j++) { // bmdata = CustomData_bmesh_get(&bm->ldata, looptris[i][j]->head.data, CD_MLOOPUV); bmdata = BM_ELEM_CD_GET_VOID_P(looptris[i][j], cd_loop_uv_offset); @@ -2284,12 +1664,9 @@ DerivedMesh *getEditDerivedBMesh( bmdm->dm.drawMappedEdges = emDM_drawMappedEdges; bmdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp; bmdm->dm.drawMappedFaces = emDM_drawMappedFaces; - bmdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex; bmdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL; bmdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat; - bmdm->dm.drawFacesTex = emDM_drawFacesTex; bmdm->dm.drawFacesGLSL = emDM_drawFacesGLSL; - bmdm->dm.drawUVEdges = emDM_drawUVEdges; bmdm->dm.release = emDM_release; @@ -2799,14 +2176,14 @@ static void cage_mapped_verts_callback( } } -float (*BKE_editmesh_vertexCos_get(BMEditMesh *em, Scene *scene, int *r_numVerts))[3] +float (*BKE_editmesh_vertexCos_get(const struct EvaluationContext *eval_ctx, BMEditMesh *em, Scene *scene, int *r_numVerts))[3] { DerivedMesh *cage, *final; BLI_bitmap *visit_bitmap; struct CageUserData data; float (*cos_cage)[3]; - cage = editbmesh_get_derived_cage_and_final(scene, em->ob, em, CD_MASK_BAREMESH, &final); + cage = editbmesh_get_derived_cage_and_final(eval_ctx, scene, em->ob, em, CD_MASK_BAREMESH, &final); cos_cage = MEM_callocN(sizeof(*cos_cage) * em->bm->totvert, "bmbvh cos_cage"); /* when initializing cage verts, we only want the first cage coordinate for each vertex, diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c index fea3c24d322..c95da3b2569 100644 --- a/source/blender/blenkernel/intern/editmesh.c +++ b/source/blender/blenkernel/intern/editmesh.c @@ -165,26 +165,6 @@ void BKE_editmesh_tessface_calc(BMEditMesh *em) #endif } -void BKE_editmesh_update_linked_customdata(BMEditMesh *em) -{ - BMesh *bm = em->bm; - int act; - - if (CustomData_has_layer(&bm->pdata, CD_MTEXPOLY)) { - act = CustomData_get_active_layer(&bm->pdata, CD_MTEXPOLY); - CustomData_set_layer_active(&bm->ldata, CD_MLOOPUV, act); - - act = CustomData_get_render_layer(&bm->pdata, CD_MTEXPOLY); - CustomData_set_layer_render(&bm->ldata, CD_MLOOPUV, act); - - act = CustomData_get_clone_layer(&bm->pdata, CD_MTEXPOLY); - CustomData_set_layer_clone(&bm->ldata, CD_MLOOPUV, act); - - act = CustomData_get_stencil_layer(&bm->pdata, CD_MTEXPOLY); - CustomData_set_layer_stencil(&bm->ldata, CD_MLOOPUV, act); - } -} - void BKE_editmesh_free_derivedmesh(BMEditMesh *em) { if (em->derivedCage) { diff --git a/source/blender/blenkernel/intern/editmesh_tangent.c b/source/blender/blenkernel/intern/editmesh_tangent.c new file mode 100644 index 00000000000..f725a1793b4 --- /dev/null +++ b/source/blender/blenkernel/intern/editmesh_tangent.c @@ -0,0 +1,431 @@ +/* + * ***** 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 ***** + */ + +/** \file blender/blenkernel/intern/editmesh_tangent.c + * \ingroup bke + */ + +#include "BLI_math.h" +#include "BLI_task.h" + +#include "BKE_DerivedMesh.h" + +#include "BKE_mesh.h" +#include "BKE_mesh_tangent.h" /* for utility functions */ +#include "BKE_editmesh.h" +#include "BKE_editmesh_tangent.h" + +#include "MEM_guardedalloc.h" + +/* interface */ +#include "mikktspace.h" + +/** \name Tangent Space Calculation + * \{ */ + +/* Necessary complexity to handle looptri's as quads for correct tangents */ +#define USE_LOOPTRI_DETECT_QUADS + +typedef struct { + const float (*precomputedFaceNormals)[3]; + const float (*precomputedLoopNormals)[3]; + const BMLoop *(*looptris)[3]; + int cd_loop_uv_offset; /* texture coordinates */ + const float (*orco)[3]; + float (*tangent)[4]; /* destination */ + int numTessFaces; + +#ifdef USE_LOOPTRI_DETECT_QUADS + /* map from 'fake' face index to looptri, + * quads will point to the first looptri of the quad */ + const int *face_as_quad_map; + int num_face_as_quad_map; +#endif + +} SGLSLEditMeshToTangent; + +#ifdef USE_LOOPTRI_DETECT_QUADS +/* seems weak but only used on quads */ +static const BMLoop *bm_loop_at_face_index(const BMFace *f, int vert_index) +{ + const BMLoop *l = BM_FACE_FIRST_LOOP(f); + while (vert_index--) { + l = l->next; + } + return l; +} +#endif + +static int emdm_ts_GetNumFaces(const SMikkTSpaceContext *pContext) +{ + SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData; + +#ifdef USE_LOOPTRI_DETECT_QUADS + return pMesh->num_face_as_quad_map; +#else + return pMesh->numTessFaces; +#endif +} + +static int emdm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num) +{ +#ifdef USE_LOOPTRI_DETECT_QUADS + SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData; + if (pMesh->face_as_quad_map) { + const BMLoop **lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]]; + if (lt[0]->f->len == 4) { + return 4; + } + } + return 3; +#else + UNUSED_VARS(pContext, face_num); + return 3; +#endif +} + +static void emdm_ts_GetPosition( + const SMikkTSpaceContext *pContext, float r_co[3], + const int face_num, const int vert_index) +{ + //assert(vert_index >= 0 && vert_index < 4); + SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData; + const BMLoop **lt; + const BMLoop *l; + +#ifdef USE_LOOPTRI_DETECT_QUADS + if (pMesh->face_as_quad_map) { + lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]]; + if (lt[0]->f->len == 4) { + l = bm_loop_at_face_index(lt[0]->f, vert_index); + goto finally; + } + /* fall through to regular triangle */ + } + else { + lt = pMesh->looptris[face_num]; + } +#else + lt = pMesh->looptris[face_num]; +#endif + l = lt[vert_index]; + + const float *co; + +finally: + co = l->v->co; + copy_v3_v3(r_co, co); +} + +static void emdm_ts_GetTextureCoordinate( + const SMikkTSpaceContext *pContext, float r_uv[2], + const int face_num, const int vert_index) +{ + //assert(vert_index >= 0 && vert_index < 4); + SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData; + const BMLoop **lt; + const BMLoop *l; + +#ifdef USE_LOOPTRI_DETECT_QUADS + if (pMesh->face_as_quad_map) { + lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]]; + if (lt[0]->f->len == 4) { + l = bm_loop_at_face_index(lt[0]->f, vert_index); + goto finally; + } + /* fall through to regular triangle */ + } + else { + lt = pMesh->looptris[face_num]; + } +#else + lt = pMesh->looptris[face_num]; +#endif + l = lt[vert_index]; + +finally: + if (pMesh->cd_loop_uv_offset != -1) { + const float *uv = BM_ELEM_CD_GET_VOID_P(l, pMesh->cd_loop_uv_offset); + copy_v2_v2(r_uv, uv); + } + else { + const float *orco = pMesh->orco[BM_elem_index_get(l->v)]; + map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]); + } +} + +static void emdm_ts_GetNormal( + const SMikkTSpaceContext *pContext, float r_no[3], + const int face_num, const int vert_index) +{ + //assert(vert_index >= 0 && vert_index < 4); + SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData; + const BMLoop **lt; + const BMLoop *l; + +#ifdef USE_LOOPTRI_DETECT_QUADS + if (pMesh->face_as_quad_map) { + lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]]; + if (lt[0]->f->len == 4) { + l = bm_loop_at_face_index(lt[0]->f, vert_index); + goto finally; + } + /* fall through to regular triangle */ + } + else { + lt = pMesh->looptris[face_num]; + } +#else + lt = pMesh->looptris[face_num]; +#endif + l = lt[vert_index]; + +finally: + if (pMesh->precomputedLoopNormals) { + copy_v3_v3(r_no, pMesh->precomputedLoopNormals[BM_elem_index_get(l)]); + } + else if (BM_elem_flag_test(l->f, BM_ELEM_SMOOTH) == 0) { /* flat */ + if (pMesh->precomputedFaceNormals) { + copy_v3_v3(r_no, pMesh->precomputedFaceNormals[BM_elem_index_get(l->f)]); + } + else { + copy_v3_v3(r_no, l->f->no); + } + } + else { + copy_v3_v3(r_no, l->v->no); + } +} + +static void emdm_ts_SetTSpace( + const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign, + const int face_num, const int vert_index) +{ + //assert(vert_index >= 0 && vert_index < 4); + SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData; + const BMLoop **lt; + const BMLoop *l; + +#ifdef USE_LOOPTRI_DETECT_QUADS + if (pMesh->face_as_quad_map) { + lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]]; + if (lt[0]->f->len == 4) { + l = bm_loop_at_face_index(lt[0]->f, vert_index); + goto finally; + } + /* fall through to regular triangle */ + } + else { + lt = pMesh->looptris[face_num]; + } +#else + lt = pMesh->looptris[face_num]; +#endif + l = lt[vert_index]; + + float *pRes; + +finally: + pRes = pMesh->tangent[BM_elem_index_get(l)]; + copy_v3_v3(pRes, fvTangent); + pRes[3] = fSign; +} + +static void emDM_calc_loop_tangents_thread(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid)) +{ + struct SGLSLEditMeshToTangent *mesh2tangent = taskdata; + /* new computation method */ + { + SMikkTSpaceContext sContext = {NULL}; + SMikkTSpaceInterface sInterface = {NULL}; + sContext.m_pUserData = mesh2tangent; + sContext.m_pInterface = &sInterface; + sInterface.m_getNumFaces = emdm_ts_GetNumFaces; + sInterface.m_getNumVerticesOfFace = emdm_ts_GetNumVertsOfFace; + sInterface.m_getPosition = emdm_ts_GetPosition; + sInterface.m_getTexCoord = emdm_ts_GetTextureCoordinate; + sInterface.m_getNormal = emdm_ts_GetNormal; + sInterface.m_setTSpaceBasic = emdm_ts_SetTSpace; + /* 0 if failed */ + genTangSpaceDefault(&sContext); + } +} + +/** + * \see #BKE_mesh_calc_loop_tangent, same logic but used arrays instead of #BMesh data. + * + * \note This function is not so normal, its using `bm->ldata` as input, but output's to `dm->loopData`. + * This is done because #CD_TANGENT is cache data used only for drawing. + */ +void BKE_editmesh_loop_tangent_calc( + BMEditMesh *em, bool calc_active_tangent, + const char (*tangent_names)[MAX_NAME], int tangent_names_len, + const float (*poly_normals)[3], + const float (*loop_normals)[3], + const float (*vert_orco)[3], + /* result */ + CustomData *loopdata_out, + const uint loopdata_out_len, + short *tangent_mask_curr_p) +{ + BMesh *bm = em->bm; + + int act_uv_n = -1; + int ren_uv_n = -1; + bool calc_act = false; + bool calc_ren = false; + char act_uv_name[MAX_NAME]; + char ren_uv_name[MAX_NAME]; + short tangent_mask = 0; + short tangent_mask_curr = *tangent_mask_curr_p; + + BKE_mesh_calc_loop_tangent_step_0( + &bm->ldata, calc_active_tangent, tangent_names, tangent_names_len, + &calc_act, &calc_ren, &act_uv_n, &ren_uv_n, act_uv_name, ren_uv_name, &tangent_mask); + + if ((tangent_mask_curr | tangent_mask) != tangent_mask_curr) { + for (int i = 0; i < tangent_names_len; i++) { + if (tangent_names[i][0]) { + BKE_mesh_add_loop_tangent_named_layer_for_uv( + &bm->ldata, loopdata_out, (int)loopdata_out_len, tangent_names[i]); + } + } + if ((tangent_mask & DM_TANGENT_MASK_ORCO) && CustomData_get_named_layer_index(loopdata_out, CD_TANGENT, "") == -1) + CustomData_add_layer_named(loopdata_out, CD_TANGENT, CD_CALLOC, NULL, (int)loopdata_out_len, ""); + if (calc_act && act_uv_name[0]) + BKE_mesh_add_loop_tangent_named_layer_for_uv(&bm->ldata, loopdata_out, (int)loopdata_out_len, act_uv_name); + if (calc_ren && ren_uv_name[0]) + BKE_mesh_add_loop_tangent_named_layer_for_uv(&bm->ldata, loopdata_out, (int)loopdata_out_len, ren_uv_name); + int totface = em->tottri; +#ifdef USE_LOOPTRI_DETECT_QUADS + int num_face_as_quad_map; + int *face_as_quad_map = NULL; + + /* map faces to quads */ + if (em->tottri != bm->totface) { + /* over alloc, since we dont know how many ngon or quads we have */ + + /* map fake face index to looptri */ + face_as_quad_map = MEM_mallocN(sizeof(int) * totface, __func__); + int i, j; + for (i = 0, j = 0; j < totface; i++, j++) { + face_as_quad_map[i] = j; + /* step over all quads */ + if (em->looptris[j][0]->f->len == 4) { + j++; /* skips the nest looptri */ + } + } + num_face_as_quad_map = i; + } + else { + num_face_as_quad_map = totface; + } +#endif + /* Calculation */ + if (em->tottri != 0) { + TaskScheduler *scheduler = BLI_task_scheduler_get(); + TaskPool *task_pool; + task_pool = BLI_task_pool_create(scheduler, NULL); + + tangent_mask_curr = 0; + /* Calculate tangent layers */ + SGLSLEditMeshToTangent data_array[MAX_MTFACE]; + int index = 0; + int n = 0; + CustomData_update_typemap(loopdata_out); + const int tangent_layer_num = CustomData_number_of_layers(loopdata_out, CD_TANGENT); + for (n = 0; n < tangent_layer_num; n++) { + index = CustomData_get_layer_index_n(loopdata_out, CD_TANGENT, n); + BLI_assert(n < MAX_MTFACE); + SGLSLEditMeshToTangent *mesh2tangent = &data_array[n]; + mesh2tangent->numTessFaces = em->tottri; +#ifdef USE_LOOPTRI_DETECT_QUADS + mesh2tangent->face_as_quad_map = face_as_quad_map; + mesh2tangent->num_face_as_quad_map = num_face_as_quad_map; +#endif + mesh2tangent->precomputedFaceNormals = poly_normals; /* dm->getPolyDataArray(dm, CD_NORMAL) */ + /* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled), + * have to check this is valid... + */ + mesh2tangent->precomputedLoopNormals = loop_normals; + mesh2tangent->cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, n); + + /* needed for indexing loop-tangents */ + int htype_index = BM_LOOP; + if (mesh2tangent->cd_loop_uv_offset == -1) { + mesh2tangent->orco = vert_orco; + if (!mesh2tangent->orco) + continue; + /* needed for orco lookups */ + htype_index |= BM_VERT; + tangent_mask_curr |= DM_TANGENT_MASK_ORCO; + } + else { + /* Fill the resulting tangent_mask */ + int uv_ind = CustomData_get_named_layer_index(&bm->ldata, CD_MLOOPUV, loopdata_out->layers[index].name); + int uv_start = CustomData_get_layer_index(&bm->ldata, CD_MLOOPUV); + BLI_assert(uv_ind != -1 && uv_start != -1); + BLI_assert(uv_ind - uv_start < MAX_MTFACE); + tangent_mask_curr |= 1 << (uv_ind - uv_start); + } + if (mesh2tangent->precomputedFaceNormals) { + /* needed for face normal lookups */ + htype_index |= BM_FACE; + } + BM_mesh_elem_index_ensure(bm, htype_index); + + mesh2tangent->looptris = (const BMLoop *(*)[3])em->looptris; + mesh2tangent->tangent = loopdata_out->layers[index].data; + + BLI_task_pool_push(task_pool, emDM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW); + } + + BLI_assert(tangent_mask_curr == tangent_mask); + BLI_task_pool_work_and_wait(task_pool); + BLI_task_pool_free(task_pool); + } + else { + tangent_mask_curr = tangent_mask; + } +#ifdef USE_LOOPTRI_DETECT_QUADS + if (face_as_quad_map) { + MEM_freeN(face_as_quad_map); + } +#undef USE_LOOPTRI_DETECT_QUADS +#endif + } + + *tangent_mask_curr_p = tangent_mask_curr; + + int act_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, act_uv_n); + if (act_uv_index >= 0) { + int tan_index = CustomData_get_named_layer_index(loopdata_out, CD_TANGENT, bm->ldata.layers[act_uv_index].name); + CustomData_set_layer_active_index(loopdata_out, CD_TANGENT, tan_index); + } /* else tangent has been built from orco */ + + /* Update render layer index */ + int ren_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, ren_uv_n); + if (ren_uv_index >= 0) { + int tan_index = CustomData_get_named_layer_index(loopdata_out, CD_TANGENT, bm->ldata.layers[ren_uv_index].name); + CustomData_set_layer_render_index(loopdata_out, CD_TANGENT, tan_index); + } /* else tangent has been built from orco */ +} + +/** \} */
\ No newline at end of file diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index 749c5897abb..84f12c3a239 100644 --- a/source/blender/blenkernel/intern/effect.c +++ b/source/blender/blenkernel/intern/effect.c @@ -64,6 +64,8 @@ #include "BKE_cdderivedmesh.h" #include "BKE_effect.h" #include "BKE_global.h" +#include "BKE_group.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_modifier.h" #include "BKE_object.h" @@ -71,6 +73,7 @@ #include "BKE_scene.h" #include "BKE_smoke.h" +#include "DEG_depsgraph.h" #include "RE_render_ext.h" #include "RE_shader_ext.h" @@ -145,9 +148,10 @@ void free_partdeflect(PartDeflect *pd) MEM_freeN(pd); } -static EffectorCache *new_effector_cache(Scene *scene, Object *ob, ParticleSystem *psys, PartDeflect *pd) +static EffectorCache *new_effector_cache(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, ParticleSystem *psys, PartDeflect *pd) { EffectorCache *eff = MEM_callocN(sizeof(EffectorCache), "EffectorCache"); + eff->eval_ctx = eval_ctx; eff->scene = scene; eff->ob = ob; eff->psys = psys; @@ -155,7 +159,7 @@ static EffectorCache *new_effector_cache(Scene *scene, Object *ob, ParticleSyste eff->frame = -1; return eff; } -static void add_object_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, Object *ob_src, bool for_simulation) +static void add_object_to_effectors(ListBase **effectors, const struct EvaluationContext *eval_ctx, Scene *scene, EffectorWeights *weights, Object *ob, Object *ob_src, bool for_simulation) { EffectorCache *eff = NULL; @@ -173,14 +177,14 @@ static void add_object_to_effectors(ListBase **effectors, Scene *scene, Effector if (*effectors == NULL) *effectors = MEM_callocN(sizeof(ListBase), "effectors list"); - eff = new_effector_cache(scene, ob, NULL, ob->pd); + eff = new_effector_cache(eval_ctx, scene, ob, NULL, ob->pd); /* make sure imat is up to date */ invert_m4_m4(ob->imat, ob->obmat); BLI_addtail(*effectors, eff); } -static void add_particles_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, ParticleSystem *psys, ParticleSystem *psys_src, bool for_simulation) +static void add_particles_to_effectors(ListBase **effectors, const struct EvaluationContext *eval_ctx, Scene *scene, EffectorWeights *weights, Object *ob, ParticleSystem *psys, ParticleSystem *psys_src, bool for_simulation) { ParticleSettings *part= psys->part; @@ -194,61 +198,59 @@ static void add_particles_to_effectors(ListBase **effectors, Scene *scene, Effec if (*effectors == NULL) *effectors = MEM_callocN(sizeof(ListBase), "effectors list"); - BLI_addtail(*effectors, new_effector_cache(scene, ob, psys, part->pd)); + BLI_addtail(*effectors, new_effector_cache(eval_ctx, scene, ob, psys, part->pd)); } if (part->pd2 && part->pd2->forcefield && (!for_simulation || weights->weight[part->pd2->forcefield] != 0.0f)) { if (*effectors == NULL) *effectors = MEM_callocN(sizeof(ListBase), "effectors list"); - BLI_addtail(*effectors, new_effector_cache(scene, ob, psys, part->pd2)); + BLI_addtail(*effectors, new_effector_cache(eval_ctx, scene, ob, psys, part->pd2)); } } /* returns ListBase handle with objects taking part in the effecting */ -ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src, - EffectorWeights *weights, bool for_simulation) +ListBase *pdInitEffectors( + const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob_src, ParticleSystem *psys_src, + EffectorWeights *weights, bool for_simulation) { + ViewLayer *view_layer; Base *base; - unsigned int layer= ob_src->lay; ListBase *effectors = NULL; - + if (weights->group) { - GroupObject *go; - - for (go= weights->group->gobject.first; go; go= go->next) { - if ( (go->ob->lay & layer) ) { - if ( go->ob->pd && go->ob->pd->forcefield ) - add_object_to_effectors(&effectors, scene, weights, go->ob, ob_src, for_simulation); + view_layer = weights->group->view_layer; + } + else if (eval_ctx) { + view_layer = eval_ctx->view_layer; + } + else { + /* eval_ctx is NULL during deg build */ + view_layer = BKE_view_layer_context_active_PLACEHOLDER(scene); + } - if ( go->ob->particlesystem.first ) { - ParticleSystem *psys= go->ob->particlesystem.first; + for (base = FIRSTBASE(view_layer); base; base = base->next) { + if ((base->flag & BASE_VISIBLED) == 0) { + continue; + } - for ( ; psys; psys=psys->next ) - add_particles_to_effectors(&effectors, scene, weights, go->ob, psys, psys_src, for_simulation); - } - } + if (base->object->pd && base->object->pd->forcefield) { + add_object_to_effectors(&effectors, eval_ctx, scene, weights, base->object, ob_src, for_simulation); } - } - else { - for (base = scene->base.first; base; base= base->next) { - if ( (base->lay & layer) ) { - if ( base->object->pd && base->object->pd->forcefield ) - add_object_to_effectors(&effectors, scene, weights, base->object, ob_src, for_simulation); - if ( base->object->particlesystem.first ) { - ParticleSystem *psys= base->object->particlesystem.first; + if (base->object->particlesystem.first) { + ParticleSystem *psys= base->object->particlesystem.first; - for ( ; psys; psys=psys->next ) - add_particles_to_effectors(&effectors, scene, weights, base->object, psys, psys_src, for_simulation); - } + for (; psys; psys=psys->next) { + add_particles_to_effectors(&effectors, eval_ctx, scene, weights, base->object, psys, psys_src, for_simulation); } } } - - if (for_simulation) - pdPrecalculateEffectors(effectors); - + + if (for_simulation) { + pdPrecalculateEffectors(eval_ctx, effectors); + } + return effectors; } @@ -268,7 +270,7 @@ void pdEndEffectors(ListBase **effectors) } } -static void precalculate_effector(EffectorCache *eff) +static void precalculate_effector(const struct EvaluationContext *eval_ctx, EffectorCache *eff) { unsigned int cfra = (unsigned int)(eff->scene->r.cfra >= 0 ? eff->scene->r.cfra : -eff->scene->r.cfra); if (!eff->pd->rng) @@ -280,7 +282,7 @@ static void precalculate_effector(EffectorCache *eff) Curve *cu= eff->ob->data; if (cu->flag & CU_PATH) { if (eff->ob->curve_cache == NULL || eff->ob->curve_cache->path==NULL || eff->ob->curve_cache->path->data==NULL) - BKE_displist_make_curveTypes(eff->scene, eff->ob, 0); + BKE_displist_make_curveTypes(eval_ctx, eff->scene, eff->ob, 0); if (eff->ob->curve_cache->path && eff->ob->curve_cache->path->data) { where_on_path(eff->ob, 0.0, eff->guide_loc, eff->guide_dir, NULL, &eff->guide_radius, NULL); @@ -301,19 +303,19 @@ static void precalculate_effector(EffectorCache *eff) if (eff->ob) { float old_vel[3]; - BKE_object_where_is_calc_time(eff->scene, eff->ob, cfra - 1.0f); + BKE_object_where_is_calc_time(eval_ctx, eff->scene, eff->ob, cfra - 1.0f); copy_v3_v3(old_vel, eff->ob->obmat[3]); - BKE_object_where_is_calc_time(eff->scene, eff->ob, cfra); + BKE_object_where_is_calc_time(eval_ctx, eff->scene, eff->ob, cfra); sub_v3_v3v3(eff->velocity, eff->ob->obmat[3], old_vel); } } -void pdPrecalculateEffectors(ListBase *effectors) +void pdPrecalculateEffectors(const struct EvaluationContext *eval_ctx, ListBase *effectors) { if (effectors) { EffectorCache *eff = effectors->first; for (; eff; eff=eff->next) - precalculate_effector(eff); + precalculate_effector(eval_ctx, eff); } } @@ -612,6 +614,7 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin } else { ParticleSimulationData sim= {NULL}; + sim.eval_ctx = eff->eval_ctx; sim.scene= eff->scene; sim.ob= eff->ob; sim.psys= eff->psys; diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c index 30ead3ffbb6..a4ed7a9d63f 100644 --- a/source/blender/blenkernel/intern/fluidsim.c +++ b/source/blender/blenkernel/intern/fluidsim.c @@ -65,7 +65,7 @@ // file handling //------------------------------------------------------------------------------- -void initElbeemMesh(struct Scene *scene, struct Object *ob, +void initElbeemMesh(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, int *numVertices, float **vertices, int *numTriangles, int **triangles, int useGlobalCoords, int modifierIndex) @@ -78,7 +78,7 @@ void initElbeemMesh(struct Scene *scene, struct Object *ob, float *verts; int *tris; - dm = mesh_create_derived_index_render(scene, ob, CD_MASK_BAREMESH, modifierIndex); + dm = mesh_create_derived_index_render(eval_ctx, scene, ob, CD_MASK_BAREMESH, modifierIndex); mvert = dm->getVertArray(dm); mloop = dm->getLoopArray(dm); diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c index 686fe3bda93..b656d2cf7c0 100644 --- a/source/blender/blenkernel/intern/freestyle.c +++ b/source/blender/blenkernel/intern/freestyle.c @@ -61,17 +61,21 @@ void BKE_freestyle_config_init(FreestyleConfig *config) BLI_listbase_clear(&config->linesets); } -void BKE_freestyle_config_free(FreestyleConfig *config) +void BKE_freestyle_config_free(FreestyleConfig *config, const bool do_id_user) { FreestyleLineSet *lineset; for (lineset = (FreestyleLineSet *)config->linesets.first; lineset; lineset = lineset->next) { if (lineset->group) { - id_us_min(&lineset->group->id); + if (do_id_user) { + id_us_min(&lineset->group->id); + } lineset->group = NULL; } if (lineset->linestyle) { - id_us_min(&lineset->linestyle->id); + if (do_id_user) { + id_us_min(&lineset->linestyle->id); + } lineset->linestyle = NULL; } } diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index 6dc8cc5aff1..ca6d92efa80 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -45,34 +45,51 @@ #include "BLI_blenlib.h" #include "BLI_utildefines.h" - -#include "BKE_depsgraph.h" +#include "BKE_collection.h" #include "BKE_global.h" #include "BKE_group.h" #include "BKE_icons.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_main.h" #include "BKE_object.h" -#include "BKE_scene.h" /* BKE_scene_base_find */ +#include "BKE_scene.h" -static void free_group_object(GroupObject *go) -{ - MEM_freeN(go); -} +#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf /** Free (or release) any data used by this group (does not free the group itself). */ void BKE_group_free(Group *group) { - /* don't free group itself */ - GroupObject *go; - /* No animdata here. */ + BKE_previewimg_free(&group->preview); - while ((go = BLI_pophead(&group->gobject))) { - free_group_object(go); + if (group->view_layer != NULL) { + BKE_view_layer_free(group->view_layer); + group->view_layer = NULL; } - BKE_previewimg_free(&group->preview); + if (group->collection != NULL) { + BKE_collection_master_free(&group->id, false); + MEM_freeN(group->collection); + group->collection = NULL; + } +} + +/** + * Run when adding new groups or during doversion. + */ +void BKE_group_init(Group *group) +{ + group->collection = MEM_callocN(sizeof(SceneCollection), __func__); + BLI_strncpy(group->collection->name, "Master Collection", sizeof(group->collection->name)); + group->view_layer = BKE_view_layer_group_add(group); + + /* Unlink the master collection. */ + BKE_collection_unlink(group->view_layer, group->view_layer->layer_collections.first); + + /* Create and link a new default collection. */ + SceneCollection *defaut_collection = BKE_collection_add(&group->id, NULL, COLLECTION_TYPE_GROUP_INTERNAL, NULL); + BKE_collection_link(group->view_layer, defaut_collection); } Group *BKE_group_add(Main *bmain, const char *name) @@ -85,7 +102,7 @@ Group *BKE_group_add(Main *bmain, const char *name) group->layer = (1 << 20) - 1; group->preview = NULL; - + BKE_group_init(group); return group; } @@ -99,7 +116,8 @@ Group *BKE_group_add(Main *bmain, const char *name) */ void BKE_group_copy_data(Main *UNUSED(bmain), Group *group_dst, const Group *group_src, const int flag) { - BLI_duplicatelist(&group_dst->gobject, &group_src->gobject); + /* We never handle usercount here for own data. */ + const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; /* Do not copy group's preview (same behavior as for objects). */ if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO temp hack */ @@ -108,6 +126,19 @@ void BKE_group_copy_data(Main *UNUSED(bmain), Group *group_dst, const Group *gro else { group_dst->preview = NULL; } + + group_dst->collection = MEM_dupallocN(group_src->collection); + SceneCollection *master_collection_src = BKE_collection_master(&group_src->id); + SceneCollection *master_collection_dst = BKE_collection_master(&group_dst->id); + + /* Recursively creates a new SceneCollection tree. */ + BKE_collection_copy_data(master_collection_dst, master_collection_src, + flag_subdata); + + group_dst->view_layer = MEM_dupallocN(group_src->view_layer); + BKE_view_layer_copy_data(group_dst->view_layer, group_src->view_layer, + master_collection_dst, master_collection_src, + flag_subdata); } Group *BKE_group_copy(Main *bmain, const Group *group) @@ -125,38 +156,27 @@ void BKE_group_make_local(Main *bmain, Group *group, const bool lib_local) /* external */ static bool group_object_add_internal(Group *group, Object *ob) { - GroupObject *go; - if (group == NULL || ob == NULL) { return false; } - - /* check if the object has been added already */ - if (BLI_findptr(&group->gobject, ob, offsetof(GroupObject, ob))) { + + /* For now always add to master collection of the group. */ + SceneCollection *scene_collection = GROUP_MASTER_COLLECTION(group); + + /* If the object has been added already it returns false. */ + if (BKE_collection_object_add(&group->id, scene_collection, ob) == false) { return false; } - - go = MEM_callocN(sizeof(GroupObject), "groupobject"); - BLI_addtail(&group->gobject, go); - - go->ob = ob; - id_us_ensure_real(&go->ob->id); - + + id_us_ensure_real(&ob->id); return true; } -bool BKE_group_object_add(Group *group, Object *object, Scene *scene, Base *base) +bool BKE_group_object_add(Group *group, Object *object) { if (group_object_add_internal(group, object)) { if ((object->flag & OB_FROMGROUP) == 0) { - - if (scene && base == NULL) - base = BKE_scene_base_find(scene, object); - object->flag |= OB_FROMGROUP; - - if (base) - base->flag |= OB_FROMGROUP; } return true; } @@ -166,24 +186,17 @@ bool BKE_group_object_add(Group *group, Object *object, Scene *scene, Base *base } /* also used for (ob == NULL) */ -static int group_object_unlink_internal(Group *group, Object *ob) +static bool group_object_unlink_internal(Group *group, Object *ob) { - GroupObject *go, *gon; - int removed = 0; - if (group == NULL) return 0; - - go = group->gobject.first; - while (go) { - gon = go->next; - if (go->ob == ob) { - BLI_remlink(&group->gobject, go); - free_group_object(go); - removed = 1; - /* should break here since an object being in a group twice cant happen? */ - } - go = gon; + if (group == NULL) { + return false; } - return removed; + + if (BKE_collections_object_remove(NULL, &group->id, ob, false)) { + return true; + } + + return false; } static bool group_object_cyclic_check_internal(Object *object, Group *group) @@ -200,12 +213,13 @@ static bool group_object_cyclic_check_internal(Object *object, Group *group) if (dup_group == group) return true; else { - GroupObject *gob; - for (gob = dup_group->gobject.first; gob; gob = gob->next) { - if (group_object_cyclic_check_internal(gob->ob, group)) { + FOREACH_GROUP_OBJECT(dup_group, group_object) + { + if (group_object_cyclic_check_internal(group_object, dup_group)) { return true; } } + FOREACH_GROUP_OBJECT_END } /* un-flag the object, it's allowed to have the same group multiple times in parallel */ @@ -223,18 +237,12 @@ bool BKE_group_object_cyclic_check(Main *bmain, Object *object, Group *group) return group_object_cyclic_check_internal(object, group); } -bool BKE_group_object_unlink(Group *group, Object *object, Scene *scene, Base *base) +bool BKE_group_object_unlink(Group *group, Object *object) { if (group_object_unlink_internal(group, object)) { /* object can be NULL */ if (object && BKE_group_object_find(NULL, object) == NULL) { - if (scene && base == NULL) - base = BKE_scene_base_find(scene, object); - object->flag &= ~OB_FROMGROUP; - - if (base) - base->flag &= ~OB_FROMGROUP; } return true; } @@ -249,7 +257,7 @@ bool BKE_group_object_exists(Group *group, Object *ob) return false; } else { - return (BLI_findptr(&group->gobject, ob, offsetof(GroupObject, ob)) != NULL); + return (BLI_findptr(&group->view_layer->object_bases, ob, offsetof(Base, object))); } } @@ -270,17 +278,13 @@ Group *BKE_group_object_find(Group *group, Object *ob) bool BKE_group_is_animated(Group *group, Object *UNUSED(parent)) { - GroupObject *go; - -#if 0 /* XXX OLD ANIMSYS, NLASTRIPS ARE NO LONGER USED */ - if (parent->nlastrips.first) - return 1; -#endif - - for (go = group->gobject.first; go; go = go->next) - if (go->ob && go->ob->proxy) + FOREACH_GROUP_OBJECT(group, object) + { + if (object->proxy) { return true; - + } + } + FOREACH_GROUP_OBJECT_END return false; } @@ -330,10 +334,8 @@ static void group_replaces_nla(Object *parent, Object *target, char mode) * you can draw everything, leaves tags in objects to signal it needs further updating */ /* note: does not work for derivedmesh and render... it recreates all again in convertblender.c */ -void BKE_group_handle_recalc_and_update(EvaluationContext *eval_ctx, Scene *scene, Object *UNUSED(parent), Group *group) +void BKE_group_handle_recalc_and_update(const struct EvaluationContext *eval_ctx, Scene *scene, Object *UNUSED(parent), Group *group) { - GroupObject *go; - #if 0 /* warning, isn't clearing the recalc flag on the object which causes it to run all the time, * not just on frame change. * This isn't working because the animation data is only re-evaluated on frame change so commenting for now @@ -367,12 +369,45 @@ void BKE_group_handle_recalc_and_update(EvaluationContext *eval_ctx, Scene *scen #endif { /* only do existing tags, as set by regular depsgraph */ - for (go = group->gobject.first; go; go = go->next) { - if (go->ob) { - if (go->ob->recalc) { - BKE_object_handle_update(eval_ctx, scene, go->ob); - } + FOREACH_GROUP_OBJECT(group, object) + { + if (object->id.recalc & ID_RECALC_ALL) { + BKE_object_handle_update(eval_ctx, scene, object); } } + FOREACH_GROUP_OBJECT_END + } +} + +/* ******** Dependency graph evaluation ******** */ + +static void group_eval_layer_collections( + const struct EvaluationContext *eval_ctx, + Group *group, + ListBase *layer_collections, + LayerCollection *parent_layer_collection) +{ + BLI_LISTBASE_FOREACH (LayerCollection *, layer_collection, layer_collections) { + /* Evaluate layer collection itself. */ + BKE_layer_eval_layer_collection(eval_ctx, + layer_collection, + parent_layer_collection); + /* Evaluate nested collections. */ + group_eval_layer_collections(eval_ctx, + group, + &layer_collection->layer_collections, + layer_collection); } } + +void BKE_group_eval_view_layers(const struct EvaluationContext *eval_ctx, + Group *group) +{ + DEBUG_PRINT("%s on %s (%p)\n", __func__, group->id.name, group); + BKE_layer_eval_layer_collection_pre(eval_ctx, &group->id, group->view_layer); + group_eval_layer_collections(eval_ctx, + group, + &group->view_layer->layer_collections, + NULL); + BKE_layer_eval_layer_collection_post(eval_ctx, group->view_layer); +} diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index a98a1b13402..a407fd0bae8 100644 --- a/source/blender/blenkernel/intern/icons.c +++ b/source/blender/blenkernel/intern/icons.c @@ -42,6 +42,7 @@ #include "DNA_material_types.h" #include "DNA_object_types.h" #include "DNA_scene_types.h" +#include "DNA_screen_types.h" #include "DNA_texture_types.h" #include "DNA_world_types.h" #include "DNA_brush_types.h" @@ -252,6 +253,7 @@ PreviewImage **BKE_previewimg_id_get_p(const ID *id) ID_PRV_CASE(ID_OB, Object); ID_PRV_CASE(ID_GR, Group); ID_PRV_CASE(ID_SCE, Scene); + ID_PRV_CASE(ID_SCR, bScreen); #undef ID_PRV_CASE default: break; diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c index 70d037d85f3..487635f06ad 100644 --- a/source/blender/blenkernel/intern/idcode.c +++ b/source/blender/blenkernel/intern/idcode.c @@ -81,8 +81,9 @@ static IDType idtypes[] = { { ID_PA, "ParticleSettings", "particles", BLT_I18NCONTEXT_ID_PARTICLESETTINGS, IDTYPE_FLAGS_ISLINKABLE }, { ID_PAL, "Palettes", "palettes", BLT_I18NCONTEXT_ID_PALETTE, IDTYPE_FLAGS_ISLINKABLE }, { ID_PC, "PaintCurve", "paint_curves", BLT_I18NCONTEXT_ID_PAINTCURVE, IDTYPE_FLAGS_ISLINKABLE }, + { ID_LP, "LightProbe", "light_probes", BLT_I18NCONTEXT_ID_LIGHTPROBE, IDTYPE_FLAGS_ISLINKABLE }, { ID_SCE, "Scene", "scenes", BLT_I18NCONTEXT_ID_SCENE, IDTYPE_FLAGS_ISLINKABLE }, - { ID_SCR, "Screen", "screens", BLT_I18NCONTEXT_ID_SCREEN, 0 }, + { ID_SCR, "Screen", "screens", BLT_I18NCONTEXT_ID_SCREEN, IDTYPE_FLAGS_ISLINKABLE }, { ID_SEQ, "Sequence", "sequences", BLT_I18NCONTEXT_ID_SEQUENCE, 0 }, /* not actually ID data */ { ID_SPK, "Speaker", "speakers", BLT_I18NCONTEXT_ID_SPEAKER, IDTYPE_FLAGS_ISLINKABLE }, { ID_SO, "Sound", "sounds", BLT_I18NCONTEXT_ID_SOUND, IDTYPE_FLAGS_ISLINKABLE }, @@ -91,6 +92,7 @@ static IDType idtypes[] = { { ID_VF, "VFont", "fonts", BLT_I18NCONTEXT_ID_VFONT, IDTYPE_FLAGS_ISLINKABLE }, { ID_WO, "World", "worlds", BLT_I18NCONTEXT_ID_WORLD, IDTYPE_FLAGS_ISLINKABLE }, { ID_WM, "WindowManager", "window_managers", BLT_I18NCONTEXT_ID_WINDOWMANAGER, 0 }, + { ID_WS, "WorkSpace", "workspaces", BLT_I18NCONTEXT_ID_WORKSPACE, IDTYPE_FLAGS_ISLINKABLE }, /** Keep last, not an ID exactly, only include for completeness */ { ID_ID, "ID", "ids", BLT_I18NCONTEXT_ID_ID, 0 }, /* plural is fake */ @@ -203,6 +205,7 @@ int BKE_idcode_to_idfilter(const short idcode) CASE_IDFILTER(PA); CASE_IDFILTER(PAL); CASE_IDFILTER(PC); + CASE_IDFILTER(LP); CASE_IDFILTER(SCE); CASE_IDFILTER(SPK); CASE_IDFILTER(SO); @@ -210,6 +213,7 @@ int BKE_idcode_to_idfilter(const short idcode) CASE_IDFILTER(TXT); CASE_IDFILTER(VF); CASE_IDFILTER(WO); + CASE_IDFILTER(WS); default: return 0; } @@ -247,6 +251,7 @@ short BKE_idcode_from_idfilter(const int idfilter) CASE_IDFILTER(PA); CASE_IDFILTER(PAL); CASE_IDFILTER(PC); + CASE_IDFILTER(LP); CASE_IDFILTER(SCE); CASE_IDFILTER(SPK); CASE_IDFILTER(SO); @@ -294,6 +299,7 @@ int BKE_idcode_to_index(const short idcode) CASE_IDINDEX(PA); CASE_IDINDEX(PAL); CASE_IDINDEX(PC); + CASE_IDINDEX(LP); CASE_IDINDEX(SCE); CASE_IDINDEX(SCR); CASE_IDINDEX(SPK); @@ -303,6 +309,7 @@ int BKE_idcode_to_index(const short idcode) CASE_IDINDEX(VF); CASE_IDINDEX(WM); CASE_IDINDEX(WO); + CASE_IDINDEX(WS); } BLI_assert(0); diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c index 45b41fa01ed..33a665ba06e 100644 --- a/source/blender/blenkernel/intern/idprop.c +++ b/source/blender/blenkernel/intern/idprop.c @@ -476,6 +476,7 @@ static IDProperty *IDP_CopyGroup(const IDProperty *prop, const int flag) BLI_assert(prop->type == IDP_GROUP); newp = idp_generic_copy(prop, flag); newp->len = prop->len; + newp->subtype = prop->subtype; for (link = prop->data.group.first; link; link = link->next) { BLI_addtail(&newp->data.group, IDP_CopyProperty_ex(link, flag)); @@ -602,8 +603,9 @@ void IDP_ReplaceInGroup(IDProperty *group, IDProperty *prop) /** * If a property is missing in \a dest, add it. + * Do it recursively. */ -void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, const bool do_overwrite) +void IDP_MergeGroup_ex(IDProperty *dest, const IDProperty *src, const bool do_overwrite, const int flag) { IDProperty *prop; @@ -612,14 +614,30 @@ void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, const bool do_overw if (do_overwrite) { for (prop = src->data.group.first; prop; prop = prop->next) { - IDProperty *copy = IDP_CopyProperty(prop); + if (prop->type == IDP_GROUP) { + IDProperty *prop_exist = IDP_GetPropertyFromGroup(dest, prop->name); + + if (prop_exist != NULL) { + IDP_MergeGroup_ex(prop_exist, prop, do_overwrite, flag); + continue; + } + } + + IDProperty *copy = IDP_CopyProperty_ex(prop, flag); IDP_ReplaceInGroup(dest, copy); } } else { for (prop = src->data.group.first; prop; prop = prop->next) { - if (IDP_GetPropertyFromGroup(dest, prop->name) == NULL) { - IDProperty *copy = IDP_CopyProperty(prop); + IDProperty *prop_exist = IDP_GetPropertyFromGroup(dest, prop->name); + if (prop_exist != NULL) { + if (prop->type == IDP_GROUP) { + IDP_MergeGroup_ex(prop_exist, prop, do_overwrite, flag); + continue; + } + } + else { + IDProperty *copy = IDP_CopyProperty_ex(prop, flag); dest->len++; BLI_addtail(&dest->data.group, copy); } @@ -628,6 +646,15 @@ void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, const bool do_overw } /** + * If a property is missing in \a dest, add it. + * Do it recursively. + */ +void IDP_MergeGroup(IDProperty *dest, const IDProperty *src, const bool do_overwrite) +{ + IDP_MergeGroup_ex(dest, src, do_overwrite, 0); +} + +/** * This function has a sanity check to make sure ID properties with the same name don't * get added to the group. * @@ -1067,4 +1094,15 @@ void IDP_ClearProperty(IDProperty *prop) prop->len = prop->totallen = 0; } +void IDP_Reset(IDProperty *prop, const IDProperty *reference) +{ + if (prop == NULL) { + return; + } + IDP_ClearProperty(prop); + if (reference != NULL) { + IDP_MergeGroup(prop, reference, true); + } +} + /** \} */ diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index bd2373a59d5..d720dc41abf 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -81,6 +81,7 @@ #include "BKE_scene.h" #include "BKE_node.h" #include "BKE_sequencer.h" /* seq_foreground_frame_get() */ +#include "BKE_workspace.h" #include "BLF_api.h" @@ -2609,19 +2610,19 @@ void BKE_image_walk_all_users(const Main *mainp, void *customdata, } } + for (Camera *cam = mainp->camera.first; cam; cam = cam->id.next) { + for (CameraBGImage *bgpic = cam->bg_images.first; bgpic; bgpic = bgpic->next) { + callback(bgpic->ima, &bgpic->iuser, customdata); + } + } + /* image window, compo node users */ for (wm = mainp->wm.first; wm; wm = wm->id.next) { /* only 1 wm */ for (win = wm->windows.first; win; win = win->next) { - ScrArea *sa; - for (sa = win->screen->areabase.first; sa; sa = sa->next) { - if (sa->spacetype == SPACE_VIEW3D) { - View3D *v3d = sa->spacedata.first; - BGpic *bgpic; - for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) { - callback(bgpic->ima, &bgpic->iuser, customdata); - } - } - else if (sa->spacetype == SPACE_IMAGE) { + const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook); + + for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) { + if (sa->spacetype == SPACE_IMAGE) { SpaceImage *sima = sa->spacedata.first; callback(sima->image, &sima->iuser, customdata); } diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c index 3a4c920d8fb..931fc09d235 100644 --- a/source/blender/blenkernel/intern/lamp.c +++ b/source/blender/blenkernel/intern/lamp.c @@ -69,6 +69,7 @@ void BKE_lamp_init(Lamp *la) la->bufsize = 512; la->clipsta = 0.5f; la->clipend = 40.0f; + la->bleedexp = 2.5f; la->samp = 3; la->bias = 1.0f; la->soft = 3.0f; @@ -101,6 +102,14 @@ void BKE_lamp_init(Lamp *la) la->sky_colorspace = BLI_XYZ_CIE; la->sky_exposure = 1.0f; la->shadow_frustum_size = 10.0f; + la->cascade_max_dist = 1000.0f; + la->cascade_count = 4; + la->cascade_exponent = 0.8f; + la->cascade_fade = 0.1f; + la->contact_dist = 1.0f; + la->contact_bias = 0.03f; + la->contact_spread = 0.2f; + la->contact_thickness = 0.5f; curvemapping_initialize(la->curfalloff); } @@ -215,41 +224,3 @@ void BKE_lamp_free(Lamp *la) BKE_icon_id_delete(&la->id); la->id.icon_id = 0; } - -/* Calculate all drivers for lamps, see material_drivers_update for why this is a bad hack */ - -static void lamp_node_drivers_update(Scene *scene, bNodeTree *ntree, float ctime) -{ - bNode *node; - - /* nodetree itself */ - if (ntree->adt && ntree->adt->drivers.first) - BKE_animsys_evaluate_animdata(scene, &ntree->id, ntree->adt, ctime, ADT_RECALC_DRIVERS); - - /* nodes */ - for (node = ntree->nodes.first; node; node = node->next) - if (node->id && node->type == NODE_GROUP) - lamp_node_drivers_update(scene, (bNodeTree *)node->id, ctime); -} - -void lamp_drivers_update(Scene *scene, Lamp *la, float ctime) -{ - /* Prevent infinite recursion by checking (and tagging the lamp) as having been visited already - * (see BKE_scene_update_tagged()). This assumes la->id.tag & LIB_TAG_DOIT isn't set by anything else - * in the meantime... [#32017] */ - if (la->id.tag & LIB_TAG_DOIT) - return; - - la->id.tag |= LIB_TAG_DOIT; - - /* lamp itself */ - if (la->adt && la->adt->drivers.first) - BKE_animsys_evaluate_animdata(scene, &la->id, la->adt, ctime, ADT_RECALC_DRIVERS); - - /* nodes */ - if (la->nodetree) - lamp_node_drivers_update(scene, la->nodetree, ctime); - - la->id.tag &= ~LIB_TAG_DOIT; -} - diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c index ea4c3f380ff..d92d0d9edbf 100644 --- a/source/blender/blenkernel/intern/lattice.c +++ b/source/blender/blenkernel/intern/lattice.c @@ -53,7 +53,6 @@ #include "BKE_anim.h" #include "BKE_cdderivedmesh.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_displist.h" #include "BKE_global.h" #include "BKE_key.h" @@ -67,11 +66,6 @@ #include "BKE_deform.h" -/* Workaround for cyclic dependency with curves. - * In such case curve_cache might not be ready yet, - */ -#define CYCLIC_DEPENDENCY_WORKAROUND - int BKE_lattice_index_from_uvw(Lattice *lt, const int u, const int v, const int w) { @@ -314,6 +308,8 @@ void BKE_lattice_free(Lattice *lt) { BKE_animdata_free(<->id, false); + BKE_lattice_batch_cache_free(lt); + MEM_SAFE_FREE(lt->def); if (lt->dvert) { BKE_defvert_array_free(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw); @@ -602,7 +598,7 @@ static bool where_on_path_deform(Object *ob, float ctime, float vec[4], float di /* co: local coord, result local too */ /* returns quaternion for rotation, using cd->no_rot_axis */ /* axis is using another define!!! */ -static bool calc_curve_deform(Scene *scene, Object *par, float co[3], +static bool calc_curve_deform(Object *par, float co[3], const short axis, CurveDeform *cd, float r_quat[4]) { Curve *cu = par->data; @@ -610,12 +606,10 @@ static bool calc_curve_deform(Scene *scene, Object *par, float co[3], short index; const bool is_neg_axis = (axis > 2); - /* to be sure, mostly after file load, also cyclic dependencies */ -#ifdef CYCLIC_DEPENDENCY_WORKAROUND if (par->curve_cache == NULL) { - BKE_displist_make_curveTypes(scene, par, false); + /* Happens with a cyclic dependencies. */ + return false; } -#endif if (par->curve_cache->path == NULL) { return false; /* happens on append, cyclic dependencies and empty curves */ @@ -706,7 +700,7 @@ static bool calc_curve_deform(Scene *scene, Object *par, float co[3], } void curve_deform_verts( - Scene *scene, Object *cuOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3], + Object *cuOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3], int numVerts, const char *vgroup, short defaxis) { Curve *cu; @@ -765,7 +759,7 @@ void curve_deform_verts( if (weight > 0.0f) { mul_m4_v3(cd.curvespace, vertexCos[a]); copy_v3_v3(vec, vertexCos[a]); - calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL); + calc_curve_deform(cuOb, vec, defaxis, &cd, NULL); interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight); mul_m4_v3(cd.objectspace, vertexCos[a]); } @@ -788,7 +782,7 @@ void curve_deform_verts( if (weight > 0.0f) { /* already in 'cd.curvespace', prev for loop */ copy_v3_v3(vec, vertexCos[a]); - calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL); + calc_curve_deform(cuOb, vec, defaxis, &cd, NULL); interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight); mul_m4_v3(cd.objectspace, vertexCos[a]); } @@ -799,7 +793,7 @@ void curve_deform_verts( if (cu->flag & CU_DEFORM_BOUNDS_OFF) { for (a = 0; a < numVerts; a++) { mul_m4_v3(cd.curvespace, vertexCos[a]); - calc_curve_deform(scene, cuOb, vertexCos[a], defaxis, &cd, NULL); + calc_curve_deform(cuOb, vertexCos[a], defaxis, &cd, NULL); mul_m4_v3(cd.objectspace, vertexCos[a]); } } @@ -814,7 +808,7 @@ void curve_deform_verts( for (a = 0; a < numVerts; a++) { /* already in 'cd.curvespace', prev for loop */ - calc_curve_deform(scene, cuOb, vertexCos[a], defaxis, &cd, NULL); + calc_curve_deform(cuOb, vertexCos[a], defaxis, &cd, NULL); mul_m4_v3(cd.objectspace, vertexCos[a]); } } @@ -824,7 +818,7 @@ void curve_deform_verts( /* input vec and orco = local coord in armature space */ /* orco is original not-animated or deformed reference point */ /* result written in vec and mat */ -void curve_deform_vector(Scene *scene, Object *cuOb, Object *target, +void curve_deform_vector(Object *cuOb, Object *target, float orco[3], float vec[3], float mat[3][3], int no_rot_axis) { CurveDeform cd; @@ -843,7 +837,7 @@ void curve_deform_vector(Scene *scene, Object *cuOb, Object *target, mul_m4_v3(cd.curvespace, vec); - if (calc_curve_deform(scene, cuOb, vec, target->trackflag, &cd, quat)) { + if (calc_curve_deform(cuOb, vec, target->trackflag, &cd, quat)) { float qmat[3][3]; quat_to_mat3(qmat, quat); @@ -1033,7 +1027,7 @@ void BKE_lattice_vertexcos_apply(struct Object *ob, float (*vertexCos)[3]) } } -void BKE_lattice_modifiers_calc(Scene *scene, Object *ob) +void BKE_lattice_modifiers_calc(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob) { Lattice *lt = ob->data; VirtualModifierData virtualModifierData; @@ -1060,7 +1054,7 @@ void BKE_lattice_modifiers_calc(Scene *scene, Object *ob) if (mti->type != eModifierTypeType_OnlyDeform) continue; if (!vertexCos) vertexCos = BKE_lattice_vertexcos_get(ob, &numVerts); - mti->deformVerts(md, ob, NULL, vertexCos, numVerts, 0); + mti->deformVerts(md, eval_ctx, ob, NULL, vertexCos, numVerts, 0); } /* always displist to make this work like derivedmesh */ @@ -1234,8 +1228,24 @@ void BKE_lattice_translate(Lattice *lt, float offset[3], bool do_keys) /* **** Depsgraph evaluation **** */ -void BKE_lattice_eval_geometry(EvaluationContext *UNUSED(eval_ctx), +void BKE_lattice_eval_geometry(const struct EvaluationContext *UNUSED(eval_ctx), Lattice *UNUSED(latt)) { } +/* Draw Engine */ +void (*BKE_lattice_batch_cache_dirty_cb)(Lattice *lt, int mode) = NULL; +void (*BKE_lattice_batch_cache_free_cb)(Lattice *lt) = NULL; + +void BKE_lattice_batch_cache_dirty(Lattice *lt, int mode) +{ + if (lt->batch_cache) { + BKE_lattice_batch_cache_dirty_cb(lt, mode); + } +} +void BKE_lattice_batch_cache_free(Lattice *lt) +{ + if (lt->batch_cache) { + BKE_lattice_batch_cache_free_cb(lt); + } +} diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c new file mode 100644 index 00000000000..cb7b72bdabd --- /dev/null +++ b/source/blender/blenkernel/intern/layer.c @@ -0,0 +1,2363 @@ +/* + * ***** 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. + * + * Contributor(s): Dalai Felinto + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/layer.c + * \ingroup bke + */ + +#include <string.h> + +#include "BLI_listbase.h" +#include "BLI_string.h" +#include "BLI_string_utf8.h" +#include "BLI_string_utils.h" +#include "BLT_translation.h" + +#include "BKE_collection.h" +#include "BKE_freestyle.h" +#include "BKE_global.h" +#include "BKE_group.h" +#include "BKE_idprop.h" +#include "BKE_layer.h" +#include "BKE_main.h" +#include "BKE_node.h" +#include "BKE_workspace.h" + +#include "DEG_depsgraph.h" + +#include "DNA_group_types.h" +#include "DNA_ID.h" +#include "DNA_layer_types.h" +#include "DNA_object_types.h" +#include "DNA_node_types.h" +#include "DNA_scene_types.h" +#include "DNA_windowmanager_types.h" +#include "DNA_workspace_types.h" + +#include "DRW_engine.h" + +#include "MEM_guardedalloc.h" + +#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf + +/* prototype */ +struct EngineSettingsCB_Type; +static void layer_collections_sync_flags(ListBase *layer_collections_dst, const ListBase *layer_collections_src); +static void layer_collection_free(ViewLayer *view_layer, LayerCollection *lc); +static void layer_collection_objects_populate(ViewLayer *view_layer, LayerCollection *lc, ListBase *objects); +static LayerCollection *layer_collection_add(ViewLayer *view_layer, LayerCollection *parent, SceneCollection *sc); +static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc); +static IDProperty *collection_engine_settings_create(struct EngineSettingsCB_Type *ces_type, const bool populate); +static IDProperty *collection_engine_get(IDProperty *root, const int type, const char *engine_name); +static void collection_engine_settings_init(IDProperty *root, const bool populate); +static void layer_engine_settings_init(IDProperty *root, const bool populate); +static void object_bases_iterator_next(BLI_Iterator *iter, const int flag); + +/* RenderLayer */ + +/** + * Returns the ViewLayer to be used for rendering + * Most of the time BKE_view_layer_from_workspace_get should be used instead + */ +ViewLayer *BKE_view_layer_from_scene_get(const Scene *scene) +{ + ViewLayer *view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer); + BLI_assert(view_layer); + return view_layer; +} + +/** + * Returns the ViewLayer to be used for drawing, outliner, and other context related areas. + */ +ViewLayer *BKE_view_layer_from_workspace_get(const struct Scene *scene, const struct WorkSpace *workspace) +{ + if (BKE_workspace_use_scene_settings_get(workspace)) { + return BKE_view_layer_from_scene_get(scene); + } + else { + return BKE_workspace_view_layer_get(workspace, scene); + } +} + +/** + * This is a placeholder to know which areas of the code need to be addressed for the Workspace changes. + * Never use this, you should either use BKE_view_layer_from_workspace_get or get ViewLayer explicitly. + */ +ViewLayer *BKE_view_layer_context_active_PLACEHOLDER(const Scene *scene) +{ + return BKE_view_layer_from_scene_get(scene); +} + +static ViewLayer *view_layer_add(const char *name, SceneCollection *master_scene_collection) +{ + if (!name) { + name = DATA_("View Layer"); + } + + IDPropertyTemplate val = {0}; + ViewLayer *view_layer = MEM_callocN(sizeof(ViewLayer), "View Layer"); + view_layer->flag = VIEW_LAYER_RENDER | VIEW_LAYER_FREESTYLE; + + view_layer->properties = IDP_New(IDP_GROUP, &val, ROOT_PROP); + layer_engine_settings_init(view_layer->properties, false); + BLI_strncpy_utf8(view_layer->name, name, sizeof(view_layer->name)); + + /* Link the master collection by default. */ + layer_collection_add(view_layer, NULL, master_scene_collection); + + /* Pure rendering pipeline settings. */ + view_layer->layflag = 0x7FFF; /* solid ztra halo edge strand */ + view_layer->passflag = SCE_PASS_COMBINED | SCE_PASS_Z; + view_layer->pass_alpha_threshold = 0.5f; + BKE_freestyle_config_init(&view_layer->freestyle_config); + + return view_layer; +} + +/** + * Add a new view layer + * by default, a view layer has the master collection + */ +ViewLayer *BKE_view_layer_add(Scene *scene, const char *name) +{ + SceneCollection *sc = BKE_collection_master(&scene->id); + ViewLayer *view_layer = view_layer_add(name, sc); + + BLI_addtail(&scene->view_layers, view_layer); + + /* unique name */ + BLI_uniquename( + &scene->view_layers, view_layer, DATA_("ViewLayer"), '.', + offsetof(ViewLayer, name), sizeof(view_layer->name)); + + return view_layer; +} + +/** + * Add a ViewLayer for a Group + * It should be added only once + */ +ViewLayer *BKE_view_layer_group_add(Group *group) +{ + BLI_assert(group->view_layer == NULL); + SceneCollection *sc = BKE_collection_master(&group->id); + ViewLayer *view_layer = view_layer_add(group->id.name + 2, sc); + return view_layer; +} + +void BKE_view_layer_free(ViewLayer *view_layer) +{ + BKE_view_layer_free_ex(view_layer, true); +} + +/** + * Free (or release) any data used by this ViewLayer. + */ +void BKE_view_layer_free_ex(ViewLayer *view_layer, const bool do_id_user) +{ + view_layer->basact = NULL; + + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + if (base->collection_properties) { + IDP_FreeProperty(base->collection_properties); + MEM_freeN(base->collection_properties); + } + } + BLI_freelistN(&view_layer->object_bases); + + for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) { + layer_collection_free(NULL, lc); + } + BLI_freelistN(&view_layer->layer_collections); + + if (view_layer->properties) { + IDP_FreeProperty(view_layer->properties); + MEM_freeN(view_layer->properties); + } + + if (view_layer->properties_evaluated) { + IDP_FreeProperty(view_layer->properties_evaluated); + MEM_freeN(view_layer->properties_evaluated); + } + + for (ViewLayerEngineData *sled = view_layer->drawdata.first; sled; sled = sled->next) { + if (sled->storage) { + if (sled->free) { + sled->free(sled->storage); + } + MEM_freeN(sled->storage); + } + } + BLI_freelistN(&view_layer->drawdata); + + MEM_SAFE_FREE(view_layer->stats); + + BKE_freestyle_config_free(&view_layer->freestyle_config, do_id_user); + + if (view_layer->id_properties) { + IDP_FreeProperty(view_layer->id_properties); + MEM_freeN(view_layer->id_properties); + } + + MEM_freeN(view_layer); +} + +/** + * Tag all the selected objects of a renderlayer + */ +void BKE_view_layer_selected_objects_tag(ViewLayer *view_layer, const int tag) +{ + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_SELECTED) != 0) { + base->object->flag |= tag; + } + else { + base->object->flag &= ~tag; + } + } +} + +/** + * Return the first ViewLayer for a given id + */ +ViewLayer *BKE_view_layer_first_from_id(const ID *owner_id) +{ + switch (GS(owner_id->name)) { + case ID_SCE: + return ((Scene *)owner_id)->view_layers.first; + case ID_GR: + return ((Group *)owner_id)->view_layer; + default: + BLI_assert(!"ID doesn't support view layers"); + return NULL; + } +} + +static bool find_scene_collection_in_scene_collections(ListBase *lb, const LayerCollection *lc) +{ + for (LayerCollection *lcn = lb->first; lcn; lcn = lcn->next) { + if (lcn == lc) { + return true; + } + if (find_scene_collection_in_scene_collections(&lcn->layer_collections, lc)) { + return true; + } + } + return false; +} + +/** + * Fallback for when a Scene has no camera to use + * + * \param view_layer: in general you want to use the same ViewLayer that is used + * for depsgraph. If rendering you pass the scene active layer, when viewing in the viewport + * you want to get ViewLayer from context. + */ +Object *BKE_view_layer_camera_find(ViewLayer *view_layer) +{ + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + if (base->object->type == OB_CAMERA) { + return base->object; + } + } + + return NULL; +} + +/** + * Find the ViewLayer a LayerCollection belongs to + */ +ViewLayer *BKE_view_layer_find_from_collection(const ID *owner_id, LayerCollection *lc) +{ + switch (GS(owner_id->name)) { + case ID_GR: + return ((Group *)owner_id)->view_layer; + case ID_SCE: + { + Scene *scene = (Scene *)owner_id; + for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + if (find_scene_collection_in_scene_collections(&view_layer->layer_collections, lc)) { + return view_layer; + } + } + return NULL; + } + default: + BLI_assert(!"ID doesn't support scene layers"); + return NULL; + } +} + +/* Base */ + +Base *BKE_view_layer_base_find(ViewLayer *view_layer, Object *ob) +{ + return BLI_findptr(&view_layer->object_bases, ob, offsetof(Base, object)); +} + +void BKE_view_layer_base_deselect_all(ViewLayer *view_layer) +{ + Base *base; + + for (base = view_layer->object_bases.first; base; base = base->next) { + base->flag &= ~BASE_SELECTED; + } +} + +void BKE_view_layer_base_select(struct ViewLayer *view_layer, Base *selbase) +{ + view_layer->basact = selbase; + if ((selbase->flag & BASE_SELECTABLED) != 0) { + selbase->flag |= BASE_SELECTED; + } +} + +/****************************************************************************/ +/* Copying functions for datablocks that use ViewLayer/SceneCollection */ + +/* Find the equivalent SceneCollection in the new tree */ +static SceneCollection *scene_collection_from_new_tree( + SceneCollection *sc_reference, SceneCollection *sc_dst, SceneCollection *sc_src) +{ + if (sc_src == sc_reference) { + return sc_dst; + } + + for (SceneCollection *nsc_src = sc_src->scene_collections.first, *nsc_dst = sc_dst->scene_collections.first; + nsc_src; + nsc_src = nsc_src->next, nsc_dst = nsc_dst->next) + { + SceneCollection *found = scene_collection_from_new_tree(sc_reference, nsc_dst, nsc_src); + if (found != NULL) { + return found; + } + } + return NULL; +} + +static void layer_collection_sync_flags( + LayerCollection *layer_collection_dst, + const LayerCollection *layer_collection_src) +{ + layer_collection_dst->flag = layer_collection_src->flag; + + if (layer_collection_dst->properties != NULL) { + IDP_FreeProperty(layer_collection_dst->properties); + MEM_SAFE_FREE(layer_collection_dst->properties); + } + + if (layer_collection_src->properties != NULL) { + layer_collection_dst->properties = IDP_CopyProperty(layer_collection_src->properties); + } + + layer_collections_sync_flags(&layer_collection_dst->layer_collections, + &layer_collection_src->layer_collections); +} + +static void layer_collections_sync_flags(ListBase *layer_collections_dst, const ListBase *layer_collections_src) +{ + BLI_assert(BLI_listbase_count(layer_collections_dst) == BLI_listbase_count(layer_collections_src)); + LayerCollection *layer_collection_dst = (LayerCollection *)layer_collections_dst->first; + const LayerCollection *layer_collection_src = (const LayerCollection *)layer_collections_src->first; + while (layer_collection_dst != NULL) { + layer_collection_sync_flags(layer_collection_dst, layer_collection_src); + layer_collection_dst = layer_collection_dst->next; + layer_collection_src = layer_collection_src->next; + } +} + +static bool layer_collection_sync_if_match( + ListBase *lb, + const SceneCollection *scene_collection_dst, + const SceneCollection *scene_collection_src) +{ + for (LayerCollection *layer_collection = lb->first; + layer_collection; + layer_collection = layer_collection->next) + { + if (layer_collection->scene_collection == scene_collection_src) { + LayerCollection *layer_collection_dst = + BLI_findptr( + lb, + scene_collection_dst, + offsetof(LayerCollection, scene_collection)); + + if (layer_collection_dst != NULL) { + layer_collection_sync_flags(layer_collection_dst, layer_collection); + } + return true; + } + else { + if (layer_collection_sync_if_match( + &layer_collection->layer_collections, + scene_collection_dst, + scene_collection_src)) + { + return true; + } + } + } + return false; +} + +/** + * Sync sibling collections across all view layers + * + * Make sure every linked instance of \a scene_collection_dst has the same values + * (flags, overrides, ...) as the corresponding scene_collection_src. + * + * \note expect scene_collection_dst to be scene_collection_src->next, and it also + * expects both collections to have the same ammount of sub-collections. + */ +void BKE_layer_collection_sync_flags( + ID *owner_id, + SceneCollection *scene_collection_dst, + SceneCollection *scene_collection_src) +{ + for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) { + for (LayerCollection *layer_collection = view_layer->layer_collections.first; + layer_collection; + layer_collection = layer_collection->next) + { + layer_collection_sync_if_match( + &layer_collection->layer_collections, + scene_collection_dst, + scene_collection_src); + } + } +} + +/* recreate the LayerCollection tree */ +static void layer_collections_recreate( + ViewLayer *view_layer_dst, ListBase *lb_src, SceneCollection *mc_dst, SceneCollection *mc_src) +{ + for (LayerCollection *lc_src = lb_src->first; lc_src; lc_src = lc_src->next) { + SceneCollection *sc_dst = scene_collection_from_new_tree(lc_src->scene_collection, mc_dst, mc_src); + BLI_assert(sc_dst); + + /* instead of synchronizing both trees we simply re-create it */ + BKE_collection_link(view_layer_dst, sc_dst); + } +} + +/** + * Only copy internal data of ViewLayer from source to already allocated/initialized destination. + * + * \param mc_src Master Collection the source ViewLayer links in. + * \param mc_dst Master Collection the destination ViewLayer links in. + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_view_layer_copy_data( + ViewLayer *view_layer_dst, ViewLayer *view_layer_src, SceneCollection *mc_dst, SceneCollection *mc_src, + const int flag) +{ + IDPropertyTemplate val = {0}; + + if (view_layer_dst->id_properties != NULL) { + view_layer_dst->id_properties = IDP_CopyProperty_ex(view_layer_dst->id_properties, flag); + } + BKE_freestyle_config_copy(&view_layer_dst->freestyle_config, &view_layer_src->freestyle_config, flag); + + view_layer_dst->stats = NULL; + view_layer_dst->properties_evaluated = NULL; + view_layer_dst->properties = IDP_New(IDP_GROUP, &val, ROOT_PROP); + IDP_MergeGroup_ex(view_layer_dst->properties, view_layer_src->properties, true, flag); + + /* we start fresh with no overrides and no visibility flags set + * instead of syncing both trees we simply unlink and relink the scene collection */ + BLI_listbase_clear(&view_layer_dst->layer_collections); + BLI_listbase_clear(&view_layer_dst->object_bases); + BLI_listbase_clear(&view_layer_dst->drawdata); + + layer_collections_recreate(view_layer_dst, &view_layer_src->layer_collections, mc_dst, mc_src); + + /* Now we handle the syncing for visibility, selectability, ... */ + layer_collections_sync_flags(&view_layer_dst->layer_collections, &view_layer_src->layer_collections); + + Object *active_ob = OBACT(view_layer_src); + for (Base *base_src = view_layer_src->object_bases.first, *base_dst = view_layer_dst->object_bases.first; + base_src; + base_src = base_src->next, base_dst = base_dst->next) + { + base_dst->flag = base_src->flag; + base_dst->flag_legacy = base_src->flag_legacy; + + if (base_dst->object == active_ob) { + view_layer_dst->basact = base_dst; + } + } +} + +/** + * Find and return the ListBase of LayerCollection that has \a lc_child as one of its directly + * nested LayerCollection. + * + * \param lb_parent Initial ListBase of LayerCollection to look into recursively + * usually the view layer's collection list + */ +static ListBase *find_layer_collection_parent_list_base(ListBase *lb_parent, const LayerCollection *lc_child) +{ + for (LayerCollection *lc_nested = lb_parent->first; lc_nested; lc_nested = lc_nested->next) { + if (lc_nested == lc_child) { + return lb_parent; + } + + ListBase *found = find_layer_collection_parent_list_base(&lc_nested->layer_collections, lc_child); + if (found != NULL) { + return found; + } + } + + return NULL; +} + +/** + * Makes a shallow copy of a LayerCollection + * + * Add a new collection in the same level as the old one (linking if necessary), + * and copy all the collection data across them. + */ +struct LayerCollection *BKE_layer_collection_duplicate(struct ID *owner_id, struct LayerCollection *layer_collection) +{ + SceneCollection *scene_collection, *scene_collection_new; + + scene_collection = layer_collection->scene_collection; + scene_collection_new = BKE_collection_duplicate(owner_id, scene_collection); + + LayerCollection *layer_collection_new = NULL; + + /* If the original layer_collection was directly linked to the view layer + we need to link the new scene collection here as well. */ + for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) { + if (BLI_findindex(&view_layer->layer_collections, layer_collection) != -1) { + layer_collection_new = BKE_collection_link(view_layer, scene_collection_new); + layer_collection_sync_flags(layer_collection_new, layer_collection); + + if (layer_collection_new != layer_collection->next) { + BLI_remlink(&view_layer->layer_collections, layer_collection_new); + BLI_insertlinkafter(&view_layer->layer_collections, layer_collection, layer_collection_new); + } + break; + } + } + + /* Otherwise just try to find the corresponding layer collection to return it back. */ + if (layer_collection_new == NULL) { + for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) { + ListBase *layer_collections_parent; + layer_collections_parent = find_layer_collection_parent_list_base( + &view_layer->layer_collections, + layer_collection); + if (layer_collections_parent != NULL) { + layer_collection_new = BLI_findptr( + layer_collections_parent, + scene_collection_new, + offsetof(LayerCollection, scene_collection)); + break; + } + } + } + return layer_collection_new; +} + +static void view_layer_object_base_unref(ViewLayer *view_layer, Base *base) +{ + base->refcount--; + + /* It only exists in the RenderLayer */ + if (base->refcount == 0) { + if (view_layer->basact == base) { + view_layer->basact = NULL; + } + + if (base->collection_properties) { + IDP_FreeProperty(base->collection_properties); + MEM_freeN(base->collection_properties); + } + + BLI_remlink(&view_layer->object_bases, base); + MEM_freeN(base); + } +} + +/** + * Return the base if existent, or create it if necessary + * Always bump the refcount + */ +static Base *object_base_add(ViewLayer *view_layer, Object *ob) +{ + Base *base; + base = BKE_view_layer_base_find(view_layer, ob); + + if (base == NULL) { + base = MEM_callocN(sizeof(Base), "Object Base"); + + /* Do not bump user count, leave it for SceneCollections. */ + base->object = ob; + BLI_addtail(&view_layer->object_bases, base); + + IDPropertyTemplate val = {0}; + base->collection_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP); + } + + base->refcount++; + return base; +} + +/* LayerCollection */ + +static void layer_collection_objects_unpopulate(ViewLayer *view_layer, LayerCollection *lc) +{ + if (view_layer) { + for (LinkData *link = lc->object_bases.first; link; link = link->next) { + view_layer_object_base_unref(view_layer, link->data); + } + } + + BLI_freelistN(&lc->object_bases); +} + +/** + * When freeing the entire ViewLayer at once we don't bother with unref + * otherwise ViewLayer is passed to keep the syncing of the LayerCollection tree + */ +static void layer_collection_free(ViewLayer *view_layer, LayerCollection *lc) +{ + layer_collection_objects_unpopulate(view_layer, lc); + BLI_freelistN(&lc->overrides); + + if (lc->properties) { + IDP_FreeProperty(lc->properties); + MEM_freeN(lc->properties); + } + + if (lc->properties_evaluated) { + IDP_FreeProperty(lc->properties_evaluated); + MEM_freeN(lc->properties_evaluated); + } + + for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) { + layer_collection_free(view_layer, nlc); + } + + BLI_freelistN(&lc->layer_collections); +} + +/** + * Free (or release) LayerCollection from ViewLayer + * (does not free the LayerCollection itself). + */ +void BKE_layer_collection_free(ViewLayer *view_layer, LayerCollection *lc) +{ + layer_collection_free(view_layer, lc); +} + +/* LayerCollection */ + +/** + * Recursively get the collection for a given index + */ +static LayerCollection *collection_from_index(ListBase *lb, const int number, int *i) +{ + for (LayerCollection *lc = lb->first; lc; lc = lc->next) { + if (*i == number) { + return lc; + } + + (*i)++; + + LayerCollection *lc_nested = collection_from_index(&lc->layer_collections, number, i); + if (lc_nested) { + return lc_nested; + } + } + return NULL; +} + +/** + * Get the collection for a given index + */ +LayerCollection *BKE_layer_collection_from_index(ViewLayer *view_layer, const int index) +{ + int i = 0; + return collection_from_index(&view_layer->layer_collections, index, &i); +} + +/** + * Get the active collection + */ +LayerCollection *BKE_layer_collection_get_active(ViewLayer *view_layer) +{ + int i = 0; + return collection_from_index(&view_layer->layer_collections, view_layer->active_collection, &i); +} + + +/** + * Return layer collection to add new object(s). + * Create one if none exists. + */ +LayerCollection *BKE_layer_collection_get_active_ensure(Scene *scene, ViewLayer *view_layer) +{ + LayerCollection *lc = BKE_layer_collection_get_active(view_layer); + + if (lc == NULL) { + BLI_assert(BLI_listbase_is_empty(&view_layer->layer_collections)); + /* When there is no collection linked to this ViewLayer, create one. */ + SceneCollection *sc = BKE_collection_add(&scene->id, NULL, COLLECTION_TYPE_NONE, NULL); + lc = BKE_collection_link(view_layer, sc); + /* New collection has to be the active one. */ + BLI_assert(lc == BKE_layer_collection_get_active(view_layer)); + } + + return lc; +} + +/** + * Recursively get the count of collections + */ +static int collection_count(ListBase *lb) +{ + int i = 0; + for (LayerCollection *lc = lb->first; lc; lc = lc->next) { + i += collection_count(&lc->layer_collections) + 1; + } + return i; +} + +/** + * Get the total number of collections + * (including all the nested collections) + */ +int BKE_layer_collection_count(ViewLayer *view_layer) +{ + return collection_count(&view_layer->layer_collections); +} + +/** + * Recursively get the index for a given collection + */ +static int index_from_collection(ListBase *lb, const LayerCollection *lc, int *i) +{ + for (LayerCollection *lcol = lb->first; lcol; lcol = lcol->next) { + if (lcol == lc) { + return *i; + } + + (*i)++; + + int i_nested = index_from_collection(&lcol->layer_collections, lc, i); + if (i_nested != -1) { + return i_nested; + } + } + return -1; +} + +/** + * Return -1 if not found + */ +int BKE_layer_collection_findindex(ViewLayer *view_layer, const LayerCollection *lc) +{ + int i = 0; + return index_from_collection(&view_layer->layer_collections, lc, &i); +} + +/** + * Lookup the listbase that contains \a lc. + */ +static ListBase *layer_collection_listbase_find(ListBase *lb, LayerCollection *lc) +{ + for (LayerCollection *lc_iter = lb->first; lc_iter; lc_iter = lc_iter->next) { + if (lc_iter == lc) { + return lb; + } + + ListBase *lb_child_result; + if ((lb_child_result = layer_collection_listbase_find(&lc_iter->layer_collections, lc))) { + return lb_child_result; + } + } + + return NULL; +} + +#if 0 +/** + * Lookup the listbase that contains \a sc. + */ +static ListBase *scene_collection_listbase_find(ListBase *lb, SceneCollection *sc) +{ + for (SceneCollection *sc_iter = lb->first; sc_iter; sc_iter = sc_iter->next) { + if (sc_iter == sc) { + return lb; + } + + ListBase *lb_child_result; + if ((lb_child_result = scene_collection_listbase_find(&sc_iter->scene_collections, sc))) { + return lb_child_result; + } + } + + return NULL; +} +#endif + +/* ---------------------------------------------------------------------- */ +/* Outliner drag and drop */ + +/** + * Nest a LayerCollection into another one + * Both collections must be from the same ViewLayer, return true if succeded. + * + * The LayerCollection will effectively be moved into the + * new (nested) position. So all the settings, overrides, ... go with it, and + * if the collection was directly linked to the ViewLayer it's then unlinked. + * + * For the other ViewLayers we simply resync the tree, without changing directly + * linked collections (even if they link to the same SceneCollection) + * + * \param lc_src LayerCollection to nest into \a lc_dst + * \param lc_dst LayerCollection to have \a lc_src inserted into + */ + +static void layer_collection_swap( + ViewLayer *view_layer, ListBase *lb_a, ListBase *lb_b, + LayerCollection *lc_a, LayerCollection *lc_b) +{ + if (lb_a == NULL) { + lb_a = layer_collection_listbase_find(&view_layer->layer_collections, lc_a); + } + + if (lb_b == NULL) { + lb_b = layer_collection_listbase_find(&view_layer->layer_collections, lc_b); + } + + BLI_assert(lb_a); + BLI_assert(lb_b); + + BLI_listbases_swaplinks(lb_a, lb_b, lc_a, lc_b); +} + +/** + * Move \a lc_src into \a lc_dst. Both have to be stored in \a view_layer. + * If \a lc_src is directly linked to the ViewLayer it's unlinked + */ +bool BKE_layer_collection_move_into(const ID *owner_id, LayerCollection *lc_dst, LayerCollection *lc_src) +{ + ViewLayer *view_layer = BKE_view_layer_find_from_collection(owner_id, lc_src); + bool is_directly_linked = false; + + if ((!view_layer) || (view_layer != BKE_view_layer_find_from_collection(owner_id, lc_dst))) { + return false; + } + + /* We can't nest the collection into itself */ + if (lc_src->scene_collection == lc_dst->scene_collection) { + return false; + } + + /* Collection is already where we wanted it to be */ + if (lc_dst->layer_collections.last == lc_src) { + return false; + } + + /* Collection is already where we want it to be in the scene tree + * but we want to swap it in the layer tree still */ + if (lc_dst->scene_collection->scene_collections.last == lc_src->scene_collection) { + LayerCollection *lc_swap = lc_dst->layer_collections.last; + layer_collection_swap(view_layer, &lc_dst->layer_collections, NULL, lc_dst->layer_collections.last, lc_src); + + if (BLI_findindex(&view_layer->layer_collections, lc_swap) != -1) { + BKE_collection_unlink(view_layer, lc_swap); + } + return true; + } + else { + LayerCollection *lc_temp; + is_directly_linked = BLI_findindex(&view_layer->layer_collections, lc_src) != -1; + + if (!is_directly_linked) { + /* lc_src will be invalid after BKE_collection_move_into! + * so we swap it with lc_temp to preserve its settings */ + lc_temp = BKE_collection_link(view_layer, lc_src->scene_collection); + layer_collection_swap(view_layer, &view_layer->layer_collections, NULL, lc_temp, lc_src); + } + + if (!BKE_collection_move_into(owner_id, lc_dst->scene_collection, lc_src->scene_collection)) { + if (!is_directly_linked) { + /* Swap back and remove */ + layer_collection_swap(view_layer, NULL, NULL, lc_temp, lc_src); + BKE_collection_unlink(view_layer, lc_temp); + } + return false; + } + } + + LayerCollection *lc_new = BLI_findptr( + &lc_dst->layer_collections, lc_src->scene_collection, offsetof(LayerCollection, scene_collection)); + BLI_assert(lc_new); + layer_collection_swap(view_layer, &lc_dst->layer_collections, NULL, lc_new, lc_src); + + /* If it's directly linked, unlink it after the swap */ + if (BLI_findindex(&view_layer->layer_collections, lc_new) != -1) { + BKE_collection_unlink(view_layer, lc_new); + } + + return true; +} + +/** + * Move \a lc_src above \a lc_dst. Both have to be stored in \a view_layer. + * If \a lc_src is directly linked to the ViewLayer it's unlinked + */ +bool BKE_layer_collection_move_above(const ID *owner_id, LayerCollection *lc_dst, LayerCollection *lc_src) +{ + ViewLayer *view_layer = BKE_view_layer_find_from_collection(owner_id, lc_src); + const bool is_directly_linked_src = BLI_findindex(&view_layer->layer_collections, lc_src) != -1; + const bool is_directly_linked_dst = BLI_findindex(&view_layer->layer_collections, lc_dst) != -1; + + if ((!view_layer) || (view_layer != BKE_view_layer_find_from_collection(owner_id, lc_dst))) { + return false; + } + + /* Collection is already where we wanted it to be */ + if (lc_dst->prev == lc_src) { + return false; + } + + /* Collection is already where we want it to be in the scene tree + * but we want to swap it in the layer tree still */ + if (lc_dst->prev && lc_dst->prev->scene_collection == lc_src->scene_collection) { + LayerCollection *lc_swap = lc_dst->prev; + layer_collection_swap(view_layer, NULL, NULL, lc_dst->prev, lc_src); + + if (BLI_findindex(&view_layer->layer_collections, lc_swap) != -1) { + BKE_collection_unlink(view_layer, lc_swap); + } + return true; + } + /* We don't allow to move above/below a directly linked collection + * unless the source collection is also directly linked */ + else if (is_directly_linked_dst) { + /* Both directly linked to the ViewLayer, just need to swap */ + if (is_directly_linked_src) { + BLI_remlink(&view_layer->layer_collections, lc_src); + BLI_insertlinkbefore(&view_layer->layer_collections, lc_dst, lc_src); + return true; + } + else { + return false; + } + } + else { + LayerCollection *lc_temp; + + if (!is_directly_linked_src) { + /* lc_src will be invalid after BKE_collection_move_into! + * so we swap it with lc_temp to preserve its settings */ + lc_temp = BKE_collection_link(view_layer, lc_src->scene_collection); + layer_collection_swap(view_layer, &view_layer->layer_collections, NULL, lc_temp, lc_src); + } + + if (!BKE_collection_move_above(owner_id, lc_dst->scene_collection, lc_src->scene_collection)) { + if (!is_directly_linked_src) { + /* Swap back and remove */ + layer_collection_swap(view_layer, NULL, NULL, lc_temp, lc_src); + BKE_collection_unlink(view_layer, lc_temp); + } + return false; + } + } + + LayerCollection *lc_new = lc_dst->prev; + BLI_assert(lc_new); + layer_collection_swap(view_layer, NULL, NULL, lc_new, lc_src); + + /* If it's directly linked, unlink it after the swap */ + if (BLI_findindex(&view_layer->layer_collections, lc_new) != -1) { + BKE_collection_unlink(view_layer, lc_new); + } + + return true; +} + +/** + * Move \a lc_src below \a lc_dst. Both have to be stored in \a view_layer. + * If \a lc_src is directly linked to the ViewLayer it's unlinked + */ +bool BKE_layer_collection_move_below(const ID *owner_id, LayerCollection *lc_dst, LayerCollection *lc_src) +{ + ViewLayer *view_layer = BKE_view_layer_find_from_collection(owner_id, lc_src); + const bool is_directly_linked_src = BLI_findindex(&view_layer->layer_collections, lc_src) != -1; + const bool is_directly_linked_dst = BLI_findindex(&view_layer->layer_collections, lc_dst) != -1; + + if ((!view_layer) || (view_layer != BKE_view_layer_find_from_collection(owner_id, lc_dst))) { + return false; + } + + /* Collection is already where we wanted it to be */ + if (lc_dst->next == lc_src) { + return false; + } + + /* Collection is already where we want it to be in the scene tree + * but we want to swap it in the layer tree still */ + if (lc_dst->next && lc_dst->next->scene_collection == lc_src->scene_collection) { + LayerCollection *lc_swap = lc_dst->next; + layer_collection_swap(view_layer, NULL, NULL, lc_dst->next, lc_src); + + if (BLI_findindex(&view_layer->layer_collections, lc_swap) != -1) { + BKE_collection_unlink(view_layer, lc_swap); + } + return true; + } + /* We don't allow to move above/below a directly linked collection + * unless the source collection is also directly linked */ + else if (is_directly_linked_dst) { + /* Both directly linked to the ViewLayer, just need to swap */ + if (is_directly_linked_src) { + BLI_remlink(&view_layer->layer_collections, lc_src); + BLI_insertlinkafter(&view_layer->layer_collections, lc_dst, lc_src); + return true; + } + else { + return false; + } + } + else { + LayerCollection *lc_temp; + + if (!is_directly_linked_src) { + /* lc_src will be invalid after BKE_collection_move_into! + * so we swap it with lc_temp to preserve its settings */ + lc_temp = BKE_collection_link(view_layer, lc_src->scene_collection); + layer_collection_swap(view_layer, &view_layer->layer_collections, NULL, lc_temp, lc_src); + } + + if (!BKE_collection_move_below(owner_id, lc_dst->scene_collection, lc_src->scene_collection)) { + if (!is_directly_linked_src) { + /* Swap back and remove */ + layer_collection_swap(view_layer, NULL, NULL, lc_temp, lc_src); + BKE_collection_unlink(view_layer, lc_temp); + } + return false; + } + } + + LayerCollection *lc_new = lc_dst->next; + BLI_assert(lc_new); + layer_collection_swap(view_layer, NULL, NULL, lc_new, lc_src); + + /* If it's directly linked, unlink it after the swap */ + if (BLI_findindex(&view_layer->layer_collections, lc_new) != -1) { + BKE_collection_unlink(view_layer, lc_new); + } + + return true; +} + +static bool layer_collection_resync(ViewLayer *view_layer, LayerCollection *lc, const SceneCollection *sc) +{ + if (lc->scene_collection == sc) { + ListBase collections = {NULL}; + BLI_movelisttolist(&collections, &lc->layer_collections); + + for (SceneCollection *sc_nested = sc->scene_collections.first; sc_nested; sc_nested = sc_nested->next) { + LayerCollection *lc_nested = BLI_findptr(&collections, sc_nested, offsetof(LayerCollection, scene_collection)); + if (lc_nested) { + BLI_remlink(&collections, lc_nested); + BLI_addtail(&lc->layer_collections, lc_nested); + } + else { + layer_collection_add(view_layer, lc, sc_nested); + } + } + + for (LayerCollection *lc_nested = collections.first; lc_nested; lc_nested = lc_nested->next) { + layer_collection_free(view_layer, lc_nested); + } + BLI_freelistN(&collections); + + BLI_assert(BLI_listbase_count(&lc->layer_collections) == + BLI_listbase_count(&sc->scene_collections)); + + return true; + } + + for (LayerCollection *lc_nested = lc->layer_collections.first; lc_nested; lc_nested = lc_nested->next) { + if (layer_collection_resync(view_layer, lc_nested, sc)) { + return true; + } + } + + return false; +} + +/** + * Update the scene layers so that any LayerCollection that points + * to \a sc is re-synced again + */ +void BKE_layer_collection_resync(const ID *owner_id, const SceneCollection *sc) +{ + for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) { + for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) { + layer_collection_resync(view_layer, lc, sc); + } + } +} + +/* ---------------------------------------------------------------------- */ + +/** + * Select all the objects of this layer collection + * + * It also select the objects that are in nested collections. + * \note Recursive + */ +void BKE_layer_collection_objects_select(struct LayerCollection *layer_collection) +{ + if ((layer_collection->flag & COLLECTION_DISABLED) || + ((layer_collection->flag & COLLECTION_SELECTABLE) == 0)) + { + return; + } + + for (LinkData *link = layer_collection->object_bases.first; link; link = link->next) { + Base *base = link->data; + if (base->flag & BASE_SELECTABLED) { + base->flag |= BASE_SELECTED; + } + } + + for (LayerCollection *iter = layer_collection->layer_collections.first; iter; iter = iter->next) { + BKE_layer_collection_objects_select(iter); + } +} + +/* ---------------------------------------------------------------------- */ + +/** + * Link a collection to a renderlayer + * The collection needs to be created separately + */ +LayerCollection *BKE_collection_link(ViewLayer *view_layer, SceneCollection *sc) +{ + LayerCollection *lc = layer_collection_add(view_layer, NULL, sc); + view_layer->active_collection = BKE_layer_collection_findindex(view_layer, lc); + return lc; +} + +/** + * Unlink a collection base from a renderlayer + * The corresponding collection is not removed from the master collection + */ +void BKE_collection_unlink(ViewLayer *view_layer, LayerCollection *lc) +{ + BKE_layer_collection_free(view_layer, lc); + BLI_remlink(&view_layer->layer_collections, lc); + MEM_freeN(lc); + view_layer->active_collection = 0; +} + +/** + * Recursively enable nested collections + */ +static void layer_collection_enable(ViewLayer *view_layer, LayerCollection *lc) +{ + layer_collection_objects_populate(view_layer, lc, &lc->scene_collection->objects); + + for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) { + layer_collection_enable(view_layer, nlc); + } +} + +/** + * Enable collection + * Add its objects bases to ViewLayer + * + * Only around for doversion. + */ +void BKE_collection_enable(ViewLayer *view_layer, LayerCollection *lc) +{ + if ((lc->flag & COLLECTION_DISABLED) == 0) { + return; + } + + lc->flag &= ~COLLECTION_DISABLED; + layer_collection_enable(view_layer, lc); +} + +static void layer_collection_object_add(ViewLayer *view_layer, LayerCollection *lc, Object *ob) +{ + Base *base = object_base_add(view_layer, ob); + + /* Only add an object once. */ + if (BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data))) { + return; + } + + bool is_visible = ((lc->flag & COLLECTION_VIEWPORT) != 0) && ((lc->flag & COLLECTION_DISABLED) == 0); + bool is_selectable = is_visible && ((lc->flag & COLLECTION_SELECTABLE) != 0); + + if (is_visible) { + base->flag |= BASE_VISIBLED; + } + + if (is_selectable) { + base->flag |= BASE_SELECTABLED; + } + + BLI_addtail(&lc->object_bases, BLI_genericNodeN(base)); +} + +static void layer_collection_object_remove(ViewLayer *view_layer, LayerCollection *lc, Object *ob) +{ + Base *base; + base = BKE_view_layer_base_find(view_layer, ob); + + LinkData *link = BLI_findptr(&lc->object_bases, base, offsetof(LinkData, data)); + BLI_remlink(&lc->object_bases, link); + MEM_freeN(link); + + view_layer_object_base_unref(view_layer, base); +} + +static void layer_collection_objects_populate(ViewLayer *view_layer, LayerCollection *lc, ListBase *objects) +{ + for (LinkData *link = objects->first; link; link = link->next) { + layer_collection_object_add(view_layer, lc, link->data); + } +} + +static void layer_collection_populate(ViewLayer *view_layer, LayerCollection *lc, SceneCollection *sc) +{ + layer_collection_objects_populate(view_layer, lc, &sc->objects); + + for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) { + layer_collection_add(view_layer, lc, nsc); + } +} + +static LayerCollection *layer_collection_add(ViewLayer *view_layer, LayerCollection *parent, SceneCollection *sc) +{ + IDPropertyTemplate val = {0}; + LayerCollection *lc = MEM_callocN(sizeof(LayerCollection), "Collection Base"); + + lc->scene_collection = sc; + lc->flag = COLLECTION_SELECTABLE | COLLECTION_VIEWPORT | COLLECTION_RENDER; + + lc->properties = IDP_New(IDP_GROUP, &val, ROOT_PROP); + collection_engine_settings_init(lc->properties, false); + + if (parent != NULL) { + BLI_addtail(&parent->layer_collections, lc); + } + else { + BLI_addtail(&view_layer->layer_collections, lc); + } + + layer_collection_populate(view_layer, lc, sc); + + return lc; +} + +/* ---------------------------------------------------------------------- */ + +/** + * See if render layer has the scene collection linked directly, or indirectly (nested) + */ +bool BKE_view_layer_has_collection(ViewLayer *view_layer, const SceneCollection *sc) +{ + for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) { + if (find_layer_collection_by_scene_collection(lc, sc) != NULL) { + return true; + } + } + return false; +} + +/** + * See if the object is in any of the scene layers of the scene + */ +bool BKE_scene_has_object(Scene *scene, Object *ob) +{ + for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + Base *base = BKE_view_layer_base_find(view_layer, ob); + if (base) { + return true; + } + } + return false; +} + + +/* ---------------------------------------------------------------------- */ +/* Syncing */ + +static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc) +{ + if (lc->scene_collection == sc) { + return lc; + } + + for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) { + LayerCollection *found = find_layer_collection_by_scene_collection(nlc, sc); + if (found) { + return found; + } + } + return NULL; +} + +/** + * Add a new LayerCollection for all the ViewLayers that have sc_parent + */ +void BKE_layer_sync_new_scene_collection(ID *owner_id, const SceneCollection *sc_parent, SceneCollection *sc) +{ + for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) { + for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) { + LayerCollection *lc_parent = find_layer_collection_by_scene_collection(lc, sc_parent); + if (lc_parent) { + layer_collection_add(view_layer, lc_parent, sc); + } + } + } +} + +/** + * Add a corresponding ObjectBase to all the equivalent LayerCollection + */ +void BKE_layer_sync_object_link(const ID *owner_id, SceneCollection *sc, Object *ob) +{ + for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) { + for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) { + LayerCollection *found = find_layer_collection_by_scene_collection(lc, sc); + if (found) { + layer_collection_object_add(view_layer, found, ob); + } + } + } +} + +/** + * Remove the equivalent object base to all layers that have this collection + */ +void BKE_layer_sync_object_unlink(const ID *owner_id, SceneCollection *sc, Object *ob) +{ + for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) { + for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) { + LayerCollection *found = find_layer_collection_by_scene_collection(lc, sc); + if (found) { + layer_collection_object_remove(view_layer, found, ob); + } + } + } +} + +/* ---------------------------------------------------------------------- */ +/* Override */ + +/** + * Add a new datablock override + */ +void BKE_override_view_layer_datablock_add(ViewLayer *view_layer, int id_type, const char *data_path, const ID *owner_id) +{ + UNUSED_VARS(view_layer, id_type, data_path, owner_id); + TODO_LAYER_OVERRIDE; +} + +/** + * Add a new int override + */ +void BKE_override_view_layer_int_add(ViewLayer *view_layer, int id_type, const char *data_path, const int value) +{ + UNUSED_VARS(view_layer, id_type, data_path, value); + TODO_LAYER_OVERRIDE; +} + +/** + * Add a new boolean override + */ +void BKE_override_layer_collection_boolean_add(struct LayerCollection *layer_collection, int id_type, const char *data_path, const bool value) +{ + UNUSED_VARS(layer_collection, id_type, data_path, value); + TODO_LAYER_OVERRIDE; +} + +/* ---------------------------------------------------------------------- */ +/* Engine Settings */ + +ListBase R_layer_collection_engines_settings_callbacks = {NULL, NULL}; +ListBase R_view_layer_engines_settings_callbacks = {NULL, NULL}; + +typedef struct EngineSettingsCB_Type { + struct EngineSettingsCB_Type *next, *prev; + + char name[MAX_NAME]; /* engine name */ + + EngineSettingsCB callback; + +} EngineSettingsCB_Type; + +static void create_engine_settings_scene(IDProperty *root, EngineSettingsCB_Type *es_type) +{ + if (collection_engine_get(root, COLLECTION_MODE_NONE, es_type->name)) { + return; + } + + IDProperty *props = collection_engine_settings_create(es_type, true); + IDP_AddToGroup(root, props); +} + +static void create_layer_collection_engine_settings_scene(Scene *scene, EngineSettingsCB_Type *es_type) +{ + create_engine_settings_scene(scene->collection_properties, es_type); +} + +static void create_view_layer_engine_settings_scene(Scene *scene, EngineSettingsCB_Type *es_type) +{ + create_engine_settings_scene(scene->layer_properties, es_type); +} + +static void create_layer_collection_engine_settings_collection(LayerCollection *lc, EngineSettingsCB_Type *es_type) +{ + if (BKE_layer_collection_engine_collection_get(lc, COLLECTION_MODE_NONE, es_type->name)) { + return; + } + + IDProperty *props = collection_engine_settings_create(es_type, false); + IDP_AddToGroup(lc->properties, props); + + for (LayerCollection *lcn = lc->layer_collections.first; lcn; lcn = lcn->next) { + create_layer_collection_engine_settings_collection(lcn, es_type); + } +} + +static void create_layer_collection_engines_settings_scene(Scene *scene, EngineSettingsCB_Type *es_type) +{ + /* Populate the scene with the new settings. */ + create_layer_collection_engine_settings_scene(scene, es_type); + + for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) { + create_layer_collection_engine_settings_collection(lc, es_type); + } + } +} + +static void create_view_layer_engines_settings_scene(Scene *scene, EngineSettingsCB_Type *es_type) +{ + /* Populate the scene with the new settings. */ + create_view_layer_engine_settings_scene(scene, es_type); +} + +static void create_view_layer_engines_settings_layer(ViewLayer *view_layer, EngineSettingsCB_Type *es_type) +{ + if (BKE_view_layer_engine_layer_get(view_layer, COLLECTION_MODE_NONE, es_type->name)) { + return; + } + + IDProperty *props = collection_engine_settings_create(es_type, false); + IDP_AddToGroup(view_layer->properties, props); +} + +static EngineSettingsCB_Type *engine_settings_callback_register(const char *engine_name, EngineSettingsCB func, ListBase *lb) +{ + EngineSettingsCB_Type *es_type; + + /* Cleanup in case it existed. */ + es_type = BLI_findstring(lb, engine_name, offsetof(EngineSettingsCB_Type, name)); + + if (es_type) { + BLI_remlink(lb, es_type); + MEM_freeN(es_type); + } + + es_type = MEM_callocN(sizeof(EngineSettingsCB_Type), __func__); + BLI_strncpy_utf8(es_type->name, engine_name, sizeof(es_type->name)); + es_type->callback = func; + BLI_addtail(lb, es_type); + + return es_type; +} + +void BKE_layer_collection_engine_settings_callback_register( + Main *bmain, const char *engine_name, EngineSettingsCB func) +{ + EngineSettingsCB_Type *es_type = + engine_settings_callback_register(engine_name, func, &R_layer_collection_engines_settings_callbacks); + + if (bmain) { + /* Populate all of the collections of the scene with those settings. */ + for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) { + create_layer_collection_engines_settings_scene(scene, es_type); + } + } +} + +void BKE_view_layer_engine_settings_callback_register( + Main *bmain, const char *engine_name, EngineSettingsCB func) +{ + EngineSettingsCB_Type *es_type = + engine_settings_callback_register(engine_name, func, &R_view_layer_engines_settings_callbacks); + + if (bmain) { + /* Populate all of the collections of the scene with those settings. */ + for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) { + create_view_layer_engines_settings_scene(scene, es_type); + + for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + create_view_layer_engines_settings_layer(view_layer, es_type); + } + } + } +} + +void BKE_layer_collection_engine_settings_callback_free(void) +{ + BLI_freelistN(&R_layer_collection_engines_settings_callbacks); +} + +void BKE_view_layer_engine_settings_callback_free(void) +{ + BLI_freelistN(&R_view_layer_engines_settings_callbacks); +} + +/** + * Create a root IDProperty for this engine + * + * \param populate whether we want to pre-fill the collection with the default properties + */ +static IDProperty *collection_engine_settings_create(EngineSettingsCB_Type *es_type, const bool populate) +{ + IDProperty *props; + IDPropertyTemplate val = {0}; + + props = IDP_New(IDP_GROUP, &val, es_type->name); + props->subtype = IDP_GROUP_SUB_ENGINE_RENDER; + + /* properties */ + if (populate) { + es_type->callback(NULL, props); + } + + return props; +} + +static void layer_collection_create_mode_settings_object(IDProperty *root, const bool populate) +{ + IDProperty *props; + IDPropertyTemplate val = {0}; + + props = IDP_New(IDP_GROUP, &val, "ObjectMode"); + props->subtype = IDP_GROUP_SUB_MODE_OBJECT; + + /* properties */ + if (populate) { + OBJECT_collection_settings_create(props); + } + + IDP_AddToGroup(root, props); +} + +static void layer_collection_create_mode_settings_edit(IDProperty *root, const bool populate) +{ + IDProperty *props; + IDPropertyTemplate val = {0}; + + props = IDP_New(IDP_GROUP, &val, "EditMode"); + props->subtype = IDP_GROUP_SUB_MODE_EDIT; + + /* properties */ + if (populate) { + EDIT_MESH_collection_settings_create(props); + } + + IDP_AddToGroup(root, props); +} + +static void layer_collection_create_mode_settings_paint_weight(IDProperty *root, const bool populate) +{ + IDProperty *props; + IDPropertyTemplate val = {0}; + + props = IDP_New(IDP_GROUP, &val, "WeightPaintMode"); + props->subtype = IDP_GROUP_SUB_MODE_PAINT_WEIGHT; + + /* properties */ + if (populate) { + PAINT_WEIGHT_collection_settings_create(props); + } + + IDP_AddToGroup(root, props); +} + +static void layer_collection_create_mode_settings_paint_vertex(IDProperty *root, const bool populate) +{ + IDProperty *props; + IDPropertyTemplate val = {0}; + + props = IDP_New(IDP_GROUP, &val, "VertexPaintMode"); + props->subtype = IDP_GROUP_SUB_MODE_PAINT_VERTEX; + + /* properties */ + if (populate) { + PAINT_VERTEX_collection_settings_create(props); + } + + IDP_AddToGroup(root, props); +} + +static void layer_collection_create_render_settings(IDProperty *root, const bool populate) +{ + EngineSettingsCB_Type *es_type; + for (es_type = R_layer_collection_engines_settings_callbacks.first; es_type; es_type = es_type->next) { + IDProperty *props = collection_engine_settings_create(es_type, populate); + IDP_AddToGroup(root, props); + } +} + +static void view_layer_create_render_settings(IDProperty *root, const bool populate) +{ + EngineSettingsCB_Type *es_type; + for (es_type = R_view_layer_engines_settings_callbacks.first; es_type; es_type = es_type->next) { + IDProperty *props = collection_engine_settings_create(es_type, populate); + IDP_AddToGroup(root, props); + } +} + +static void collection_create_mode_settings(IDProperty *root, const bool populate) +{ + /* XXX TODO: put all those engines in the R_engines_settings_callbacks + * and have IDP_AddToGroup outside the callbacks */ + layer_collection_create_mode_settings_object(root, populate); + layer_collection_create_mode_settings_edit(root, populate); + layer_collection_create_mode_settings_paint_weight(root, populate); + layer_collection_create_mode_settings_paint_vertex(root, populate); +} + +static void layer_create_mode_settings(IDProperty *root, const bool populate) +{ + TODO_LAYER; /* XXX like collection_create_mode_settings */ + UNUSED_VARS(root, populate); +} + +static int idproperty_group_subtype(const int mode_type) +{ + int idgroup_type; + + switch (mode_type) { + case COLLECTION_MODE_OBJECT: + idgroup_type = IDP_GROUP_SUB_MODE_OBJECT; + break; + case COLLECTION_MODE_EDIT: + idgroup_type = IDP_GROUP_SUB_MODE_EDIT; + break; + case COLLECTION_MODE_PAINT_WEIGHT: + idgroup_type = IDP_GROUP_SUB_MODE_PAINT_WEIGHT; + break; + case COLLECTION_MODE_PAINT_VERTEX: + idgroup_type = IDP_GROUP_SUB_MODE_PAINT_VERTEX; + break; + default: + case COLLECTION_MODE_NONE: + return IDP_GROUP_SUB_ENGINE_RENDER; + break; + } + + return idgroup_type; +} + +/** + * Return collection enginne settings for either Object s of LayerCollection s + */ +static IDProperty *collection_engine_get( + IDProperty *root, const int type, const char *engine_name) +{ + const int subtype = idproperty_group_subtype(type); + + if (subtype == IDP_GROUP_SUB_ENGINE_RENDER) { + return IDP_GetPropertyFromGroup(root, engine_name); + } + else { + IDProperty *prop; + for (prop = root->data.group.first; prop; prop = prop->next) { + if (prop->subtype == subtype) { + return prop; + } + } + } + + BLI_assert(false); + return NULL; +} + +/** + * Return collection engine settings from Object for specified engine of mode + */ +IDProperty *BKE_layer_collection_engine_evaluated_get(Object *ob, const int type, const char *engine_name) +{ + return collection_engine_get(ob->base_collection_properties, type, engine_name); +} +/** + * Return layer collection engine settings for specified engine + */ +IDProperty *BKE_layer_collection_engine_collection_get(LayerCollection *lc, const int type, const char *engine_name) +{ + return collection_engine_get(lc->properties, type, engine_name); +} + +/** + * Return layer collection engine settings for specified engine in the scene + */ +IDProperty *BKE_layer_collection_engine_scene_get(Scene *scene, const int type, const char *engine_name) +{ + return collection_engine_get(scene->collection_properties, type, engine_name); +} + +/** + * Return scene layer engine settings for specified engine in the scene + */ +IDProperty *BKE_view_layer_engine_scene_get(Scene *scene, const int type, const char *engine_name) +{ + return collection_engine_get(scene->layer_properties, type, engine_name); +} + +/** + * Return scene layer engine settings for specified engine + */ +IDProperty *BKE_view_layer_engine_layer_get(ViewLayer *view_layer, const int type, const char *engine_name) +{ + return collection_engine_get(view_layer->properties, type, engine_name); +} + +/** + * Return scene layer evaluated engine settings for specified engine + */ +IDProperty *BKE_view_layer_engine_evaluated_get(ViewLayer *view_layer, const int type, const char *engine_name) +{ + return collection_engine_get(view_layer->properties_evaluated, type, engine_name); +} + +/* ---------------------------------------------------------------------- */ +/* Engine Settings Properties */ + +void BKE_collection_engine_property_add_float(IDProperty *props, const char *name, float value) +{ + IDPropertyTemplate val = {0}; + val.f = value; + IDP_AddToGroup(props, IDP_New(IDP_FLOAT, &val, name)); +} + +void BKE_collection_engine_property_add_float_array( + IDProperty *props, const char *name, const float *values, const int array_length) +{ + IDPropertyTemplate val = {0}; + val.array.len = array_length; + val.array.type = IDP_FLOAT; + + IDProperty *idprop = IDP_New(IDP_ARRAY, &val, name); + memcpy(IDP_Array(idprop), values, sizeof(float) * idprop->len); + IDP_AddToGroup(props, idprop); +} + +void BKE_collection_engine_property_add_int(IDProperty *props, const char *name, int value) +{ + IDPropertyTemplate val = {0}; + val.i = value; + IDP_AddToGroup(props, IDP_New(IDP_INT, &val, name)); +} + +void BKE_collection_engine_property_add_bool(IDProperty *props, const char *name, bool value) +{ + IDPropertyTemplate val = {0}; + val.i = value; + IDP_AddToGroup(props, IDP_New(IDP_INT, &val, name)); +} + +int BKE_collection_engine_property_value_get_int(IDProperty *props, const char *name) +{ + IDProperty *idprop = IDP_GetPropertyFromGroup(props, name); + return idprop ? IDP_Int(idprop) : 0; +} + +float BKE_collection_engine_property_value_get_float(IDProperty *props, const char *name) +{ + IDProperty *idprop = IDP_GetPropertyFromGroup(props, name); + return idprop ? IDP_Float(idprop) : 0.0f; +} + +const float *BKE_collection_engine_property_value_get_float_array(IDProperty *props, const char *name) +{ + IDProperty *idprop = IDP_GetPropertyFromGroup(props, name); + return idprop ? IDP_Array(idprop) : NULL; +} + +bool BKE_collection_engine_property_value_get_bool(IDProperty *props, const char *name) +{ + IDProperty *idprop = IDP_GetPropertyFromGroup(props, name); + return idprop ? IDP_Int(idprop) : 0; +} + +void BKE_collection_engine_property_value_set_int(IDProperty *props, const char *name, int value) +{ + IDProperty *idprop = IDP_GetPropertyFromGroup(props, name); + IDP_Int(idprop) = value; +} + +void BKE_collection_engine_property_value_set_float(IDProperty *props, const char *name, float value) +{ + IDProperty *idprop = IDP_GetPropertyFromGroup(props, name); + IDP_Float(idprop) = value; +} + +void BKE_collection_engine_property_value_set_float_array(IDProperty *props, const char *name, const float *values) +{ + IDProperty *idprop = IDP_GetPropertyFromGroup(props, name); + memcpy(IDP_Array(idprop), values, sizeof(float) * idprop->len); +} + +void BKE_collection_engine_property_value_set_bool(IDProperty *props, const char *name, bool value) +{ + IDProperty *idprop = IDP_GetPropertyFromGroup(props, name); + IDP_Int(idprop) = value; +} + +/* Engine Settings recalculate */ + +/* get all the default settings defined in scene and merge them here */ +static void collection_engine_settings_init(IDProperty *root, const bool populate) +{ + /* render engines */ + layer_collection_create_render_settings(root, populate); + + /* mode engines */ + collection_create_mode_settings(root, populate); +} + +/* get all the default settings defined in scene and merge them here */ +static void layer_engine_settings_init(IDProperty *root, const bool populate) +{ + /* render engines */ + view_layer_create_render_settings(root, populate); + + /* mode engines */ + layer_create_mode_settings(root, populate); +} + +/** + * Initialize the layer collection render setings + * It's used mainly for scenes + */ +void BKE_layer_collection_engine_settings_create(IDProperty *root) +{ + collection_engine_settings_init(root, true); +} + +/** + * Initialize the render setings + * It's used mainly for scenes + */ +void BKE_view_layer_engine_settings_create(IDProperty *root) +{ + layer_engine_settings_init(root, true); +} + +/** + * Reference of IDProperty group scene collection settings + * Used when reading blendfiles, to see if there is any missing settings. + */ +static struct { + struct { + IDProperty *collection_properties; + IDProperty *render_settings; + } scene; + IDProperty *view_layer; + IDProperty *layer_collection; +} root_reference = { + .scene = {NULL, NULL}, + .view_layer = NULL, + .layer_collection = NULL, +}; + +/** + * Free the reference scene collection settings IDProperty group. + */ +static void engine_settings_validate_init(void) +{ + IDPropertyTemplate val = {0}; + + /* LayerCollection engine settings. */ + if (root_reference.scene.collection_properties == NULL) { + root_reference.scene.collection_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP); + collection_engine_settings_init(root_reference.scene.collection_properties, true); + } + + if (root_reference.layer_collection == NULL) { + root_reference.layer_collection = IDP_New(IDP_GROUP, &val, ROOT_PROP); + collection_engine_settings_init(root_reference.layer_collection, false); + } + + /* Render engine setting. */ + if (root_reference.scene.render_settings == NULL) { + root_reference.scene.render_settings = IDP_New(IDP_GROUP, &val, ROOT_PROP); + layer_engine_settings_init(root_reference.scene.render_settings, true); + } + + if (root_reference.view_layer == NULL) { + root_reference.view_layer = IDP_New(IDP_GROUP, &val, ROOT_PROP); + layer_engine_settings_init(root_reference.view_layer, false); + } +} + +/** + * Free the reference scene collection settings IDProperty group. + */ +static void layer_collection_engine_settings_validate_free(void) +{ + IDProperty *idprops[] = { + root_reference.scene.render_settings, + root_reference.scene.collection_properties, + root_reference.view_layer, + root_reference.layer_collection, + NULL, + }; + + IDProperty **idprop = &idprops[0]; + while (*idprop) { + if (*idprop) { + IDP_FreeProperty(*idprop); + MEM_freeN(*idprop); + *idprop = NULL; + idprop++; + } + } +} + +/** + * Make sure Scene has all required collection settings. + */ +void BKE_layer_collection_engine_settings_validate_scene(Scene *scene) +{ + if (root_reference.scene.collection_properties == NULL) { + engine_settings_validate_init(); + } + + if (scene->collection_properties == NULL) { + IDPropertyTemplate val = {0}; + scene->collection_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP); + BKE_layer_collection_engine_settings_create(scene->collection_properties); + } + else { + IDP_MergeGroup(scene->collection_properties, root_reference.scene.collection_properties, false); + } +} + +/** + * Maker sure LayerCollection has all required collection settings. + */ +void BKE_layer_collection_engine_settings_validate_collection(LayerCollection *lc) +{ + if (root_reference.layer_collection == NULL) { + engine_settings_validate_init(); + } + + BLI_assert(lc->properties != NULL); + IDP_MergeGroup(lc->properties, root_reference.layer_collection, false); +} + +/** + * Make sure Scene has all required collection settings. + */ +void BKE_view_layer_engine_settings_validate_scene(Scene *scene) +{ + if (root_reference.scene.render_settings == NULL) { + engine_settings_validate_init(); + } + + if (scene->layer_properties == NULL) { + IDPropertyTemplate val = {0}; + scene->layer_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP); + BKE_view_layer_engine_settings_create(scene->layer_properties); + } + else { + IDP_MergeGroup(scene->layer_properties, root_reference.scene.render_settings, false); + } +} + +/** + * Make sure Scene has all required collection settings. + */ +void BKE_view_layer_engine_settings_validate_layer(ViewLayer *view_layer) +{ + if (root_reference.view_layer == NULL) { + engine_settings_validate_init(); + } + + IDP_MergeGroup(view_layer->properties, root_reference.view_layer, false); +} + +/* ---------------------------------------------------------------------- */ +/* Iterators */ + +static void object_bases_iterator_begin(BLI_Iterator *iter, void *data_in, const int flag) +{ + ViewLayer *view_layer = data_in; + Base *base = view_layer->object_bases.first; + + /* when there are no objects */ + if (base == NULL) { + iter->valid = false; + return; + } + + iter->data = base; + + if ((base->flag & flag) == 0) { + object_bases_iterator_next(iter, flag); + } + else { + iter->current = base; + } +} + +static void object_bases_iterator_next(BLI_Iterator *iter, const int flag) +{ + Base *base = ((Base *)iter->data)->next; + + while (base) { + if ((base->flag & flag) != 0) { + iter->current = base; + iter->data = base; + return; + } + base = base->next; + } + + iter->valid = false; +} + +static void objects_iterator_begin(BLI_Iterator *iter, void *data_in, const int flag) +{ + object_bases_iterator_begin(iter, data_in, flag); + + if (iter->valid) { + iter->current = ((Base *)iter->current)->object; + } +} + +static void objects_iterator_next(BLI_Iterator *iter, const int flag) +{ + object_bases_iterator_next(iter, flag); + + if (iter->valid) { + iter->current = ((Base *)iter->current)->object; + } +} + +void BKE_selected_objects_iterator_begin(BLI_Iterator *iter, void *data_in) +{ + objects_iterator_begin(iter, data_in, BASE_SELECTED); +} + +void BKE_selected_objects_iterator_next(BLI_Iterator *iter) +{ + objects_iterator_next(iter, BASE_SELECTED); +} + +void BKE_selected_objects_iterator_end(BLI_Iterator *UNUSED(iter)) +{ + /* do nothing */ +} + +void BKE_visible_objects_iterator_begin(BLI_Iterator *iter, void *data_in) +{ + objects_iterator_begin(iter, data_in, BASE_VISIBLED); +} + +void BKE_visible_objects_iterator_next(BLI_Iterator *iter) +{ + objects_iterator_next(iter, BASE_VISIBLED); +} + +void BKE_visible_objects_iterator_end(BLI_Iterator *UNUSED(iter)) +{ + /* do nothing */ +} + +void BKE_selected_bases_iterator_begin(BLI_Iterator *iter, void *data_in) +{ + object_bases_iterator_begin(iter, data_in, BASE_SELECTED); +} + +void BKE_selected_bases_iterator_next(BLI_Iterator *iter) +{ + object_bases_iterator_next(iter, BASE_SELECTED); +} + +void BKE_selected_bases_iterator_end(BLI_Iterator *UNUSED(iter)) +{ + /* do nothing */ +} + +void BKE_visible_bases_iterator_begin(BLI_Iterator *iter, void *data_in) +{ + object_bases_iterator_begin(iter, data_in, BASE_VISIBLED); +} + +void BKE_visible_bases_iterator_next(BLI_Iterator *iter) +{ + object_bases_iterator_next(iter, BASE_VISIBLED); +} + +void BKE_visible_bases_iterator_end(BLI_Iterator *UNUSED(iter)) +{ + /* do nothing */ +} + +void BKE_renderable_objects_iterator_begin(BLI_Iterator *iter, void *data_in) +{ + ObjectsRenderableIteratorData *data = data_in; + + /* Tag objects to prevent going over the same object twice. */ + for (Scene *scene = data->scene; scene; scene = scene->set) { + for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + base->object->id.flag |= LIB_TAG_DOIT; + } + } + } + + ViewLayer *view_layer = data->scene->view_layers.first; + data->iter.view_layer = view_layer; + + data->base_temp.next = view_layer->object_bases.first; + data->iter.base = &data->base_temp; + + data->iter.set = NULL; + + iter->data = data_in; + BKE_renderable_objects_iterator_next(iter); +} + +void BKE_renderable_objects_iterator_next(BLI_Iterator *iter) +{ + /* Set it early in case we need to exit and we are running from within a loop. */ + iter->skip = true; + + ObjectsRenderableIteratorData *data = iter->data; + Base *base = data->iter.base->next; + + /* There is still a base in the current scene layer. */ + if (base != NULL) { + Object *ob = base->object; + + /* We need to set the iter.base even if the rest fail otherwise + * we keep checking the exactly same base over and over again. */ + data->iter.base = base; + + if (ob->id.flag & LIB_TAG_DOIT) { + ob->id.flag &= ~LIB_TAG_DOIT; + + if ((base->flag & BASE_VISIBLED) != 0) { + iter->skip = false; + iter->current = ob; + } + } + return; + } + + /* Time to go to the next scene layer. */ + if (data->iter.set == NULL) { + while ((data->iter.view_layer = data->iter.view_layer->next)) { + ViewLayer *view_layer = data->iter.view_layer; + if (view_layer->flag & VIEW_LAYER_RENDER) { + data->base_temp.next = view_layer->object_bases.first; + data->iter.base = &data->base_temp; + return; + } + } + + /* Setup the "set" for the next iteration. */ + data->scene_temp.set = data->scene; + data->iter.set = &data->scene_temp; + return; + } + + /* Look for an object in the next set. */ + while ((data->iter.set = data->iter.set->set)) { + ViewLayer *view_layer = BKE_view_layer_from_scene_get(data->iter.set); + data->base_temp.next = view_layer->object_bases.first; + data->iter.base = &data->base_temp; + return; + } + + iter->valid = false; +} + +void BKE_renderable_objects_iterator_end(BLI_Iterator *UNUSED(iter)) +{ + /* Do nothing - iter->data was static allocated, we can't free it. */ +} + +/* Evaluation */ + +/** + * Reset props + * + * If props_ref is pasted, copy props from it + */ +static void idproperty_reset(IDProperty **props, IDProperty *props_ref) +{ + IDPropertyTemplate val = {0}; + + if (*props) { + IDP_FreeProperty(*props); + MEM_freeN(*props); + } + *props = IDP_New(IDP_GROUP, &val, ROOT_PROP); + + if (props_ref) { + IDP_MergeGroup(*props, props_ref, true); + } +} + +void BKE_layer_eval_layer_collection_pre(const struct EvaluationContext *UNUSED(eval_ctx), + ID *owner_id, ViewLayer *view_layer) +{ + DEBUG_PRINT("%s on %s (%p)\n", __func__, view_layer->name, view_layer); + Scene *scene = (GS(owner_id->name) == ID_SCE) ? (Scene *)owner_id : NULL; + + for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) { + base->flag &= ~(BASE_VISIBLED | BASE_SELECTABLED); + idproperty_reset(&base->collection_properties, scene ? scene->collection_properties : NULL); + } + + /* Sync properties from scene to scene layer. */ + idproperty_reset(&view_layer->properties_evaluated, scene ? scene->layer_properties : NULL); + IDP_MergeGroup(view_layer->properties_evaluated, view_layer->properties, true); + + /* TODO(sergey): Is it always required? */ + view_layer->flag |= VIEW_LAYER_ENGINE_DIRTY; +} + +static const char *collection_type_lookup[] = +{ + "None", /* COLLECTION_TYPE_NONE */ + "Group Internal", /* COLLECTION_TYPE_GROUP_INTERNAL */ +}; + +/** + * \note We can't use layer_collection->flag because of 3 level nesting (where parent is visible, but not grand-parent) + * So layer_collection->flag_evaluated is expected to be up to date with layer_collection->flag. + */ +static bool layer_collection_visible_get(const EvaluationContext *eval_ctx, LayerCollection *layer_collection) +{ + if (layer_collection->flag_evaluated & COLLECTION_DISABLED) { + return false; + } + + if (eval_ctx->mode == DAG_EVAL_VIEWPORT) { + return (layer_collection->flag_evaluated & COLLECTION_VIEWPORT) != 0; + } + else { + return (layer_collection->flag_evaluated & COLLECTION_RENDER) != 0; + } +} + +void BKE_layer_eval_layer_collection(const EvaluationContext *eval_ctx, + LayerCollection *layer_collection, + LayerCollection *parent_layer_collection) +{ + DEBUG_PRINT("%s on %s (%p) [%s], parent %s (%p) [%s]\n", + __func__, + layer_collection->scene_collection->name, + layer_collection->scene_collection, + collection_type_lookup[layer_collection->scene_collection->type], + (parent_layer_collection != NULL) ? parent_layer_collection->scene_collection->name : "NONE", + (parent_layer_collection != NULL) ? parent_layer_collection->scene_collection : NULL, + (parent_layer_collection != NULL) ? collection_type_lookup[parent_layer_collection->scene_collection->type] : ""); + BLI_assert(layer_collection != parent_layer_collection); + + /* visibility */ + layer_collection->flag_evaluated = layer_collection->flag; + + if (parent_layer_collection != NULL) { + if (layer_collection_visible_get(eval_ctx, parent_layer_collection) == false) { + layer_collection->flag_evaluated |= COLLECTION_DISABLED; + } + + if ((parent_layer_collection->flag_evaluated & COLLECTION_DISABLED) || + (parent_layer_collection->flag_evaluated & COLLECTION_SELECTABLE) == 0) + { + layer_collection->flag_evaluated &= ~COLLECTION_SELECTABLE; + } + } + + const bool is_visible = layer_collection_visible_get(eval_ctx, layer_collection); + const bool is_selectable = is_visible && ((layer_collection->flag_evaluated & COLLECTION_SELECTABLE) != 0); + + /* overrides */ + if (is_visible) { + if (parent_layer_collection == NULL) { + idproperty_reset(&layer_collection->properties_evaluated, layer_collection->properties); + } + else { + idproperty_reset(&layer_collection->properties_evaluated, parent_layer_collection->properties_evaluated); + IDP_MergeGroup(layer_collection->properties_evaluated, layer_collection->properties, true); + } + } + + for (LinkData *link = layer_collection->object_bases.first; link != NULL; link = link->next) { + Base *base = link->data; + + if (is_visible) { + IDP_MergeGroup(base->collection_properties, layer_collection->properties_evaluated, true); + base->flag |= BASE_VISIBLED; + } + + if (is_selectable) { + base->flag |= BASE_SELECTABLED; + } + } +} + +void BKE_layer_eval_layer_collection_post(const struct EvaluationContext *UNUSED(eval_ctx), + ViewLayer *view_layer) +{ + DEBUG_PRINT("%s on %s (%p)\n", __func__, view_layer->name, view_layer); + /* if base is not selectabled, clear select */ + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + if ((base->flag & BASE_SELECTABLED) == 0) { + base->flag &= ~BASE_SELECTED; + } + } +} + +/** + * Free any static allocated memory. + */ +void BKE_layer_exit(void) +{ + layer_collection_engine_settings_validate_free(); +} diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 46f8e637cf8..066b3e34b0d 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -62,6 +62,7 @@ #include "DNA_mask_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" +#include "DNA_lightprobe_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_speaker_types.h" @@ -70,6 +71,7 @@ #include "DNA_vfont_types.h" #include "DNA_windowmanager_types.h" #include "DNA_world_types.h" +#include "DNA_workspace_types.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" @@ -91,7 +93,6 @@ #include "BKE_cachefile.h" #include "BKE_context.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_font.h" #include "BKE_global.h" #include "BKE_group.h" @@ -103,6 +104,7 @@ #include "BKE_lamp.h" #include "BKE_lattice.h" #include "BKE_library.h" +#include "BKE_library_override.h" #include "BKE_library_query.h" #include "BKE_library_remap.h" #include "BKE_linestyle.h" @@ -117,6 +119,7 @@ #include "BKE_paint.h" #include "BKE_particle.h" #include "BKE_packedFile.h" +#include "BKE_lightprobe.h" #include "BKE_sound.h" #include "BKE_speaker.h" #include "BKE_scene.h" @@ -418,6 +421,9 @@ bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local) case ID_SPK: if (!test) BKE_speaker_make_local(bmain, (Speaker *)id, lib_local); return true; + case ID_LP: + if (!test) BKE_lightprobe_make_local(bmain, (LightProbe *)id, lib_local); + return true; case ID_WO: if (!test) BKE_world_make_local(bmain, (World *)id, lib_local); return true; @@ -469,7 +475,11 @@ bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local) case ID_CF: if (!test) BKE_cachefile_make_local(bmain, (CacheFile *)id, lib_local); return true; + case ID_WS: case ID_SCR: + /* A bit special: can be appended but not linked. Return false + * since supporting make-local doesn't make much sense. */ + return false; case ID_LI: case ID_KE: case ID_WM: @@ -589,6 +599,9 @@ bool BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag, con case ID_SPK: BKE_speaker_copy_data(bmain, (Speaker *)*r_newid, (Speaker *)id, flag); break; + case ID_LP: + BKE_lightprobe_copy_data(bmain, (LightProbe *)*r_newid, (LightProbe *)id, flag); + break; case ID_CA: BKE_camera_copy_data(bmain, (Camera *)*r_newid, (Camera *)id, flag); break; @@ -649,6 +662,7 @@ bool BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag, con case ID_LI: case ID_SCR: case ID_WM: + case ID_WS: case ID_IP: BLI_assert(0); /* Should have been rejected at start of function! */ break; @@ -680,6 +694,75 @@ bool id_copy(Main *bmain, const ID *id, ID **newid, bool test) return BKE_id_copy_ex(bmain, id, newid, 0, test); } +/** Does a mere memory swap over the whole IDs data (including type-specific memory). + * \note Most internal ID data itself is not swapped (only IDProperties are). */ +void BKE_id_swap(Main *bmain, ID *id_a, ID *id_b) +{ + BLI_assert(GS(id_a->name) == GS(id_b->name)); + + const ID id_a_back = *id_a; + const ID id_b_back = *id_b; + +#define CASE_SWAP(_gs, _type) \ + case _gs: \ + SWAP(_type, *(_type *)id_a, *(_type *)id_b); \ + break + + switch ((ID_Type)GS(id_a->name)) { + CASE_SWAP(ID_SCE, Scene); + CASE_SWAP(ID_LI, Library); + CASE_SWAP(ID_OB, Object); + CASE_SWAP(ID_ME, Mesh); + CASE_SWAP(ID_CU, Curve); + CASE_SWAP(ID_MB, MetaBall); + CASE_SWAP(ID_MA, Material); + CASE_SWAP(ID_TE, Tex); + CASE_SWAP(ID_IM, Image); + CASE_SWAP(ID_LT, Lattice); + CASE_SWAP(ID_LA, Lamp); + CASE_SWAP(ID_LP, LightProbe); + CASE_SWAP(ID_CA, Camera); + CASE_SWAP(ID_KE, Key); + CASE_SWAP(ID_WO, World); + CASE_SWAP(ID_SCR, bScreen); + CASE_SWAP(ID_VF, VFont); + CASE_SWAP(ID_TXT, Text); + CASE_SWAP(ID_SPK, Speaker); + CASE_SWAP(ID_SO, bSound); + CASE_SWAP(ID_GR, Group); + CASE_SWAP(ID_AR, bArmature); + CASE_SWAP(ID_AC, bAction); + CASE_SWAP(ID_NT, bNodeTree); + CASE_SWAP(ID_BR, Brush); + CASE_SWAP(ID_PA, ParticleSettings); + CASE_SWAP(ID_WM, wmWindowManager); + CASE_SWAP(ID_WS, WorkSpace); + CASE_SWAP(ID_GD, bGPdata); + CASE_SWAP(ID_MC, MovieClip); + CASE_SWAP(ID_MSK, Mask); + CASE_SWAP(ID_LS, FreestyleLineStyle); + CASE_SWAP(ID_PAL, Palette); + CASE_SWAP(ID_PC, PaintCurve); + CASE_SWAP(ID_CF, CacheFile); + case ID_IP: + break; /* Deprecated. */ + } + +#undef CASE_SWAP + + /* Restore original ID's internal data. */ + *id_a = id_a_back; + *id_b = id_b_back; + + /* Exception: IDProperties. */ + id_a->properties = id_b_back.properties; + id_b->properties = id_a_back.properties; + + /* Swap will have broken internal references to itself, restore them. */ + BKE_libblock_relink_ex(bmain, id_a, id_b, id_a, false); + BKE_libblock_relink_ex(bmain, id_b, id_a, id_b, false); +} + /** Does *not* set ID->newid pointer. */ bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop) { @@ -845,6 +928,8 @@ ListBase *which_libbase(Main *mainlib, short type) return &(mainlib->text); case ID_SPK: return &(mainlib->speaker); + case ID_LP: + return &(mainlib->lightprobe); case ID_SO: return &(mainlib->sound); case ID_GR: @@ -875,6 +960,8 @@ ListBase *which_libbase(Main *mainlib, short type) return &(mainlib->paintcurves); case ID_CF: return &(mainlib->cachefiles); + case ID_WS: + return &(mainlib->workspaces); } return NULL; } @@ -960,11 +1047,11 @@ void BKE_main_lib_objects_recalc_all(Main *bmain) /* flag for full recalc */ for (ob = bmain->object.first; ob; ob = ob->id.next) { if (ID_IS_LINKED(ob)) { - DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); } } - DAG_id_type_tag(bmain, ID_OB); + DEG_id_type_tag(bmain, ID_OB); } /** @@ -1013,6 +1100,7 @@ int set_listbasepointers(Main *main, ListBase **lb) lb[INDEX_ID_BR] = &(main->brush); lb[INDEX_ID_PA] = &(main->particle); lb[INDEX_ID_SPK] = &(main->speaker); + lb[INDEX_ID_LP] = &(main->lightprobe); lb[INDEX_ID_WO] = &(main->world); lb[INDEX_ID_MC] = &(main->movieclip); @@ -1020,6 +1108,7 @@ int set_listbasepointers(Main *main, ListBase **lb) lb[INDEX_ID_OB] = &(main->object); lb[INDEX_ID_LS] = &(main->linestyle); /* referenced by scenes */ lb[INDEX_ID_SCE] = &(main->scene); + lb[INDEX_ID_WS] = &(main->workspaces); /* before wm, so it's freed after it! */ lb[INDEX_ID_WM] = &(main->wm); lb[INDEX_ID_MSK] = &(main->mask); @@ -1072,6 +1161,7 @@ size_t BKE_libblock_get_alloc_info(short type, const char **name) CASE_RETURN(ID_VF, VFont); CASE_RETURN(ID_TXT, Text); CASE_RETURN(ID_SPK, Speaker); + CASE_RETURN(ID_LP, LightProbe); CASE_RETURN(ID_SO, bSound); CASE_RETURN(ID_GR, Group); CASE_RETURN(ID_AR, bArmature); @@ -1087,6 +1177,7 @@ size_t BKE_libblock_get_alloc_info(short type, const char **name) CASE_RETURN(ID_PAL, Palette); CASE_RETURN(ID_PC, PaintCurve); CASE_RETURN(ID_CF, CacheFile); + CASE_RETURN(ID_WS, WorkSpace); } return 0; #undef CASE_RETURN @@ -1143,7 +1234,7 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int fl /* TODO to be removed from here! */ if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0) { - DAG_id_type_tag(bmain, type); + DEG_id_type_tag(bmain, type); } } else { @@ -1202,6 +1293,9 @@ void BKE_libblock_init_empty(ID *id) case ID_SPK: BKE_speaker_init((Speaker *)id); break; + case ID_LP: + BKE_lightprobe_init((LightProbe *)id); + break; case ID_CA: BKE_camera_init((Camera *)id); break; @@ -1322,11 +1416,20 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int fla new_id->properties = IDP_CopyProperty_ex(id->properties, flag); } + /* XXX Again... We need a way to control what we copy in a much more refined way. + * We cannot always copy this, some internal copying will die on it! */ + /* For now, upper level code will have to do that itself when required. */ +#if 0 + if (id->override != NULL) { + BKE_override_copy(new_id, id); + } +#endif + /* the duplicate should get a copy of the animdata */ id_copy_animdata(bmain, new_id, (flag & LIB_ID_COPY_ACTIONS) != 0 && (flag & LIB_ID_CREATE_NO_MAIN) == 0); if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0 && (flag & LIB_ID_CREATE_NO_MAIN) == 0) { - DAG_id_type_tag(bmain, GS(new_id->name)); + DEG_id_type_tag(bmain, GS(new_id->name)); } *r_newid = new_id; diff --git a/source/blender/blenkernel/intern/library_override.c b/source/blender/blenkernel/intern/library_override.c new file mode 100644 index 00000000000..8b8658921b5 --- /dev/null +++ b/source/blender/blenkernel/intern/library_override.c @@ -0,0 +1,752 @@ +/* + * ***** 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) 2016 by Blender Foundation. + * All rights reserved. + * + * Contributor(s): Bastien Montagne. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/library_override.c + * \ingroup bke + */ + +#include <stdlib.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_ID.h" +#include "DNA_object_types.h" + +#include "DEG_depsgraph.h" +#include "BKE_library.h" +#include "BKE_library_override.h" +#include "BKE_library_remap.h" +#include "BKE_main.h" + +#include "BLI_utildefines.h" +#include "BLI_listbase.h" +#include "BLI_string.h" + +#include "RNA_access.h" +#include "RNA_types.h" + +#include "PIL_time.h" +#include "PIL_time_utildefines.h" + +#define OVERRIDE_AUTO_CHECK_DELAY 0.2 /* 200ms between auto-override checks. */ + +static void bke_override_property_copy(IDOverrideStaticProperty *op_dst, IDOverrideStaticProperty *op_src); +static void bke_override_property_operation_copy(IDOverrideStaticPropertyOperation *opop_dst, IDOverrideStaticPropertyOperation *opop_src); + +static void bke_override_property_clear(IDOverrideStaticProperty *op); +static void bke_override_property_operation_clear(IDOverrideStaticPropertyOperation *opop); + +/** Initialize empty overriding of \a reference_id by \a local_id. */ +IDOverrideStatic *BKE_override_static_init(ID *local_id, ID *reference_id) +{ + /* If reference_id is NULL, we are creating an override template for purely local data. + * Else, reference *must* be linked data. */ + BLI_assert(reference_id == NULL || reference_id->lib != NULL); + BLI_assert(local_id->override_static == NULL); + + ID *ancestor_id; + for (ancestor_id = reference_id; + ancestor_id != NULL && ancestor_id->override_static != NULL && ancestor_id->override_static->reference != NULL; + ancestor_id = ancestor_id->override_static->reference); + + if (ancestor_id != NULL && ancestor_id->override_static != NULL) { + /* Original ID has a template, use it! */ + BKE_override_static_copy(local_id, ancestor_id); + if (local_id->override_static->reference != reference_id) { + id_us_min(local_id->override_static->reference); + local_id->override_static->reference = reference_id; + id_us_plus(local_id->override_static->reference); + } + return local_id->override_static; + } + + /* Else, generate new empty override. */ + local_id->override_static = MEM_callocN(sizeof(*local_id->override_static), __func__); + local_id->override_static->reference = reference_id; + id_us_plus(local_id->override_static->reference); + local_id->tag &= ~LIB_TAG_OVERRIDESTATIC_OK; + /* TODO do we want to add tag or flag to referee to mark it as such? */ + return local_id->override_static; +} + +/** Deep copy of a whole override from \a src_id to \a dst_id. */ +void BKE_override_static_copy(ID *dst_id, const ID *src_id) +{ + BLI_assert(src_id->override_static != NULL); + + if (dst_id->override_static != NULL) { + if (src_id->override_static == NULL) { + BKE_override_static_free(&dst_id->override_static); + return; + } + else { + BKE_override_static_clear(dst_id->override_static); + } + } + else if (src_id->override_static == NULL) { + return; + } + else { + BKE_override_static_init(dst_id, NULL); + } + + /* Source is already overriding data, we copy it but reuse its reference for dest ID. + * otherwise, source is only an override template, it then becomes reference of dest ID. */ + dst_id->override_static->reference = src_id->override_static->reference ? src_id->override_static->reference : (ID *)src_id; + id_us_plus(dst_id->override_static->reference); + + BLI_duplicatelist(&dst_id->override_static->properties, &src_id->override_static->properties); + for (IDOverrideStaticProperty *op_dst = dst_id->override_static->properties.first, *op_src = src_id->override_static->properties.first; + op_dst; + op_dst = op_dst->next, op_src = op_src->next) + { + bke_override_property_copy(op_dst, op_src); + } + + dst_id->tag &= ~LIB_TAG_OVERRIDESTATIC_OK; +} + +/** Clear any overriding data from given \a override. */ +void BKE_override_static_clear(IDOverrideStatic *override) +{ + BLI_assert(override != NULL); + + for (IDOverrideStaticProperty *op = override->properties.first; op; op = op->next) { + bke_override_property_clear(op); + } + BLI_freelistN(&override->properties); + + id_us_min(override->reference); + /* override->storage should never be refcounted... */ +} + +/** Free given \a override. */ +void BKE_override_static_free(struct IDOverrideStatic **override) +{ + BLI_assert(*override != NULL); + + BKE_override_static_clear(*override); + MEM_freeN(*override); + *override = NULL; +} + +static ID *override_static_create_from(Main *bmain, ID *reference_id) +{ + ID *local_id; + + if (!id_copy(bmain, reference_id, (ID **)&local_id, false)) { + return NULL; + } + id_us_min(local_id); + + BKE_override_static_init(local_id, reference_id); + local_id->flag |= LIB_OVERRIDE_STATIC_AUTO; + + return local_id; +} + + +/** Create an overriden local copy of linked reference. */ +ID *BKE_override_static_create_from_id(Main *bmain, ID *reference_id) +{ + BLI_assert(reference_id != NULL); + BLI_assert(reference_id->lib != NULL); + + ID *local_id = override_static_create_from(bmain, reference_id); + + /* Remapping, we obviously only want to affect local data (and not our own reference pointer to overriden ID). */ + BKE_libblock_remap(bmain, reference_id, local_id, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_STATIC_OVERRIDE); + + return local_id; +} + +/** Create overriden local copies of all tagged data-blocks in given Main. + * + * \note Set id->newid of overridden libs with newly created overrides, caller is responsible to clean those pointers + * before/after usage as needed. + * + * \return \a true on success, \a false otherwise. + */ +bool BKE_override_static_create_from_tag(Main *bmain) +{ + ListBase *lbarray[MAX_LIBARRAY]; + int a; + bool ret = true; + + const int num_types = a = set_listbasepointers(bmain, lbarray); + while (a--) { + for (ID *reference_id = lbarray[a]->first; reference_id != NULL; reference_id = reference_id->next) { + if ((reference_id->tag & LIB_TAG_DOIT) != 0 && reference_id->lib != NULL) { + if ((reference_id->newid = override_static_create_from(bmain, reference_id)) == NULL) { + ret = false; + } + } + } + } + + /* Remapping, we obviously only want to affect local data (and not our own reference pointer to overriden ID). */ + a = num_types; + while (a--) { + for (ID *reference_id = lbarray[a]->first; reference_id != NULL; reference_id = reference_id->next) { + if ((reference_id->tag & LIB_TAG_DOIT) != 0 && reference_id->lib != NULL && reference_id->newid != NULL) { + ID *local_id = reference_id->newid; + BKE_libblock_remap(bmain, reference_id, local_id, + ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_STATIC_OVERRIDE); + } + } + } + + return ret; +} + +/** + * Find override property from given RNA path, if it exists. + */ +IDOverrideStaticProperty *BKE_override_static_property_find(IDOverrideStatic *override, const char *rna_path) +{ + /* XXX TODO we'll most likely want a runtime ghash to store that mapping at some point. */ + return BLI_findstring_ptr(&override->properties, rna_path, offsetof(IDOverrideStaticProperty, rna_path)); +} + +/** + * Find override property from given RNA path, or create it if it does not exist. + */ +IDOverrideStaticProperty *BKE_override_static_property_get(IDOverrideStatic *override, const char *rna_path, bool *r_created) +{ + /* XXX TODO we'll most likely want a runtime ghash to store taht mapping at some point. */ + IDOverrideStaticProperty *op = BKE_override_static_property_find(override, rna_path); + + if (op == NULL) { + op = MEM_callocN(sizeof(IDOverrideStaticProperty), __func__); + op->rna_path = BLI_strdup(rna_path); + BLI_addtail(&override->properties, op); + + if (r_created) { + *r_created = true; + } + } + else if (r_created) { + *r_created = false; + } + + return op; +} + +void bke_override_property_copy(IDOverrideStaticProperty *op_dst, IDOverrideStaticProperty *op_src) +{ + op_dst->rna_path = BLI_strdup(op_src->rna_path); + BLI_duplicatelist(&op_dst->operations, &op_src->operations); + + for (IDOverrideStaticPropertyOperation *opop_dst = op_dst->operations.first, *opop_src = op_src->operations.first; + opop_dst; + opop_dst = opop_dst->next, opop_src = opop_src->next) + { + bke_override_property_operation_copy(opop_dst, opop_src); + } +} + +void bke_override_property_clear(IDOverrideStaticProperty *op) +{ + BLI_assert(op->rna_path != NULL); + + MEM_freeN(op->rna_path); + + for (IDOverrideStaticPropertyOperation *opop = op->operations.first; opop; opop = opop->next) { + bke_override_property_operation_clear(opop); + } + BLI_freelistN(&op->operations); +} + +/** + * Remove and free given \a override_property from given ID \a override. + */ +void BKE_override_static_property_delete(IDOverrideStatic *override, IDOverrideStaticProperty *override_property) +{ + bke_override_property_clear(override_property); + BLI_freelinkN(&override->properties, override_property); +} + +/** + * Find override property operation from given sub-item(s), if it exists. + */ +IDOverrideStaticPropertyOperation *BKE_override_static_property_operation_find( + IDOverrideStaticProperty *override_property, + const char *subitem_refname, const char *subitem_locname, + const int subitem_refindex, const int subitem_locindex, const bool strict, bool *r_strict) +{ + IDOverrideStaticPropertyOperation *opop; + const int subitem_defindex = -1; + + if (r_strict) { + *r_strict = true; + } + + if (subitem_locname && + (opop = BLI_findstring_ptr(&override_property->operations, subitem_locname, + offsetof(IDOverrideStaticPropertyOperation, subitem_local_name)))) + { + return opop; + } + + if (subitem_refname && + (opop = BLI_findstring_ptr(&override_property->operations, subitem_refname, + offsetof(IDOverrideStaticPropertyOperation, subitem_reference_name)))) + { + return opop; + } + + if ((opop = BLI_listbase_bytes_find(&override_property->operations, &subitem_locindex, sizeof(subitem_locindex), + offsetof(IDOverrideStaticPropertyOperation, subitem_local_index)))) + { + return opop; + } + + if ((opop = BLI_listbase_bytes_find(&override_property->operations, &subitem_refindex, sizeof(subitem_refindex), + offsetof(IDOverrideStaticPropertyOperation, subitem_reference_index)))) + { + return opop; + } + + /* index == -1 means all indices, that is valid fallback in case we requested specific index. */ + if (!strict && (subitem_locindex != subitem_defindex) && + (opop = BLI_listbase_bytes_find(&override_property->operations, &subitem_defindex, sizeof(subitem_defindex), + offsetof(IDOverrideStaticPropertyOperation, subitem_local_index)))) + { + if (r_strict) { + *r_strict = false; + } + return opop; + } + + return NULL; +} + +/** + * Find override property operation from given sub-item(s), or create it if it does not exist. + */ +IDOverrideStaticPropertyOperation *BKE_override_static_property_operation_get( + IDOverrideStaticProperty *override_property, const short operation, + const char *subitem_refname, const char *subitem_locname, + const int subitem_refindex, const int subitem_locindex, + const bool strict, bool *r_strict, bool *r_created) +{ + IDOverrideStaticPropertyOperation *opop = BKE_override_static_property_operation_find(override_property, + subitem_refname, subitem_locname, + subitem_refindex, subitem_locindex, + strict, r_strict); + + if (opop == NULL) { + opop = MEM_callocN(sizeof(IDOverrideStaticPropertyOperation), __func__); + opop->operation = operation; + if (subitem_locname) { + opop->subitem_local_name = BLI_strdup(subitem_locname); + } + if (subitem_refname) { + opop->subitem_reference_name = BLI_strdup(subitem_refname); + } + opop->subitem_local_index = subitem_locindex; + opop->subitem_reference_index = subitem_refindex; + + BLI_addtail(&override_property->operations, opop); + + if (r_created) { + *r_created = true; + } + } + else if (r_created) { + *r_created = false; + } + + return opop; +} + +void bke_override_property_operation_copy(IDOverrideStaticPropertyOperation *opop_dst, IDOverrideStaticPropertyOperation *opop_src) +{ + if (opop_src->subitem_reference_name) { + opop_dst->subitem_reference_name = BLI_strdup(opop_src->subitem_reference_name); + } + if (opop_src->subitem_local_name) { + opop_dst->subitem_local_name = BLI_strdup(opop_src->subitem_local_name); + } +} + +void bke_override_property_operation_clear(IDOverrideStaticPropertyOperation *opop) +{ + if (opop->subitem_reference_name) { + MEM_freeN(opop->subitem_reference_name); + } + if (opop->subitem_local_name) { + MEM_freeN(opop->subitem_local_name); + } +} + +/** + * Remove and free given \a override_property_operation from given ID \a override_property. + */ +void BKE_override_static_property_operation_delete( + IDOverrideStaticProperty *override_property, IDOverrideStaticPropertyOperation *override_property_operation) +{ + bke_override_property_operation_clear(override_property_operation); + BLI_freelinkN(&override_property->operations, override_property_operation); +} + +/** + * Check that status of local data-block is still valid against current reference one. + * + * It means that all overridable, but not overridden, properties' local values must be equal to reference ones. + * Clears LIB_TAG_OVERRIDE_OK if they do not. + * + * This is typically used to detect whether some property has been changed in local and a new IDOverrideProperty + * (of IDOverridePropertyOperation) has to be added. + * + * \return true if status is OK, false otherwise. */ +bool BKE_override_static_status_check_local(ID *local) +{ + BLI_assert(local->override_static != NULL); + + ID *reference = local->override_static->reference; + + if (reference == NULL) { + /* This is an override template, local status is always OK! */ + return true; + } + + BLI_assert(GS(local->name) == GS(reference->name)); + + /* Note that reference is assumed always valid, caller has to ensure that itself. */ + + PointerRNA rnaptr_local, rnaptr_reference; + RNA_id_pointer_create(local, &rnaptr_local); + RNA_id_pointer_create(reference, &rnaptr_reference); + + if (!RNA_struct_override_matches( + &rnaptr_local, &rnaptr_reference, NULL, local->override_static, + RNA_OVERRIDE_COMPARE_IGNORE_NON_OVERRIDABLE | RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN, NULL)) + { + local->tag &= ~LIB_TAG_OVERRIDESTATIC_OK; + return false; + } + + return true; +} + +/** + * Check that status of reference data-block is still valid against current local one. + * + * It means that all non-overridden properties' local values must be equal to reference ones. + * Clears LIB_TAG_OVERRIDE_OK if they do not. + * + * This is typically used to detect whether some reference has changed and local needs to be updated against it. + * + * \return true if status is OK, false otherwise. */ +bool BKE_override_static_status_check_reference(ID *local) +{ + BLI_assert(local->override_static != NULL); + + ID *reference = local->override_static->reference; + + if (reference == NULL) { + /* This is an override template, reference is virtual, so its status is always OK! */ + return true; + } + + BLI_assert(GS(local->name) == GS(reference->name)); + + if (reference->override_static && (reference->tag & LIB_TAG_OVERRIDESTATIC_OK) == 0) { + if (!BKE_override_static_status_check_reference(reference)) { + /* If reference is also override of another data-block, and its status is not OK, + * then this override is not OK either. + * Note that this should only happen when reloading libraries... */ + local->tag &= ~LIB_TAG_OVERRIDESTATIC_OK; + return false; + } + } + + PointerRNA rnaptr_local, rnaptr_reference; + RNA_id_pointer_create(local, &rnaptr_local); + RNA_id_pointer_create(reference, &rnaptr_reference); + + if (!RNA_struct_override_matches( + &rnaptr_local, &rnaptr_reference, NULL, local->override_static, + RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN, NULL)) + { + local->tag &= ~LIB_TAG_OVERRIDESTATIC_OK; + return false; + } + + return true; +} + +/** + * Compares local and reference data-blocks and create new override operations as needed, + * or reset to reference values if overriding is not allowed. + * + * \note Defining override operations is only mandatory before saving a .blend file on disk (not for undo!). + * Knowing that info at runtime is only useful for UI/UX feedback. + * + * \note This is by far the biggest operation (the more time-consuming) of the three so far, since it has to go over + * all properties in depth (all overridable ones at least). Generating diff values and applying overrides + * are much cheaper. + * + * \return true is new overriding op was created, or some local data was reset. */ +bool BKE_override_static_operations_create(ID *local) +{ + BLI_assert(local->override_static != NULL); + const bool is_template = (local->override_static->reference == NULL); + bool ret = false; + + if (!is_template && local->flag & LIB_OVERRIDE_STATIC_AUTO) { + PointerRNA rnaptr_local, rnaptr_reference; + RNA_id_pointer_create(local, &rnaptr_local); + RNA_id_pointer_create(local->override_static->reference, &rnaptr_reference); + + eRNAOverrideMatchResult report_flags = 0; + RNA_struct_override_matches( + &rnaptr_local, &rnaptr_reference, NULL, local->override_static, + RNA_OVERRIDE_COMPARE_CREATE | RNA_OVERRIDE_COMPARE_RESTORE, &report_flags); + if (report_flags & RNA_OVERRIDE_MATCH_RESULT_CREATED) { + ret = true; + } +#ifndef NDEBUG + if (report_flags & RNA_OVERRIDE_MATCH_RESULT_RESTORED) { + printf("We did restore some properties of %s from its reference.\n", local->name); + } + if (ret) { + printf("We did generate static override rules for %s\n", local->name); + } + else { + printf("No new static override rules for %s\n", local->name); + } +#endif + } + return ret; +} + +/** Check all overrides from given \a bmain and create/update overriding operations as needed. */ +void BKE_main_override_static_operations_create(Main *bmain) +{ + ListBase *lbarray[MAX_LIBARRAY]; + int base_count, i; + + base_count = set_listbasepointers(bmain, lbarray); + + for (i = 0; i < base_count; i++) { + ListBase *lb = lbarray[i]; + ID *id; + + for (id = lb->first; id; id = id->next) { + /* TODO Maybe we could also add an 'override update' tag e.g. when tagging for DEG update? */ + if (id->lib == NULL && id->override_static != NULL && id->override_static->reference != NULL && (id->flag & LIB_OVERRIDE_STATIC_AUTO)) { + BKE_override_static_operations_create(id); + } + } + } +} + +/** Update given override from its reference (re-applying overriden properties). */ +void BKE_override_static_update(Main *bmain, ID *local) +{ + if (local->override_static == NULL || local->override_static->reference == NULL) { + return; + } + + /* Recursively do 'ancestors' overrides first, if any. */ + if (local->override_static->reference->override_static && (local->override_static->reference->tag & LIB_TAG_OVERRIDESTATIC_OK) == 0) { + BKE_override_static_update(bmain, local->override_static->reference); + } + + /* We want to avoid having to remap here, however creating up-to-date override is much simpler if based + * on reference than on current override. + * So we work on temp copy of reference, and 'swap' its content with local. */ + + /* XXX We need a way to get off-Main copies of IDs (similar to localized mats/texts/ etc.)! + * However, this is whole bunch of code work in itself, so for now plain stupid ID copy will do, + * as innefficient as it is. :/ + * Actually, maybe not! Since we are swapping with original ID's local content, we want to keep + * usercount in correct state when freeing tmp_id (and that usercounts of IDs used by 'new' local data + * also remain correct). */ + /* This would imply change in handling of usercout all over RNA (and possibly all over Blender code). + * Not impossible to do, but would rather see first if extra useless usual user handling is actually + * a (performances) issue here. */ + + ID *tmp_id; + id_copy(bmain, local->override_static->reference, &tmp_id, false); + + if (tmp_id == NULL) { + return; + } + + PointerRNA rnaptr_src, rnaptr_dst, rnaptr_storage_stack, *rnaptr_storage = NULL; + RNA_id_pointer_create(local, &rnaptr_src); + RNA_id_pointer_create(tmp_id, &rnaptr_dst); + if (local->override_static->storage) { + rnaptr_storage = &rnaptr_storage_stack; + RNA_id_pointer_create(local->override_static->storage, rnaptr_storage); + } + + RNA_struct_override_apply(&rnaptr_dst, &rnaptr_src, rnaptr_storage, local->override_static); + + /* This also transfers all pointers (memory) owned by local to tmp_id, and vice-versa. So when we'll free tmp_id, + * we'll actually free old, outdated data from local. */ + BKE_id_swap(bmain, local, tmp_id); + + /* Again, horribly innefficient in our case, we need something off-Main (aka moar generic nolib copy/free stuff)! */ + /* XXX And crashing in complex cases (e.g. because depsgraph uses same data...). */ + BKE_libblock_free_ex(bmain, tmp_id, true, false); + + if (local->override_static->storage) { + /* We know this datablock is not used anywhere besides local->override->storage. */ + /* XXX For until we get fully shadow copies, we still need to ensure storage releases + * its usage of any ID pointers it may have. */ + BKE_libblock_free_ex(bmain, local->override_static->storage, true, false); + local->override_static->storage = NULL; + } + + local->tag |= LIB_TAG_OVERRIDESTATIC_OK; + + /* Full rebuild of Depsgraph! */ + DEG_on_visible_update(bmain, true); /* XXX Is this actual valid replacement for old DAG_relations_tag_update(bmain) ? */ +} + +/** Update all overrides from given \a bmain. */ +void BKE_main_override_static_update(Main *bmain) +{ + ListBase *lbarray[MAX_LIBARRAY]; + int base_count, i; + + base_count = set_listbasepointers(bmain, lbarray); + + for (i = 0; i < base_count; i++) { + ListBase *lb = lbarray[i]; + ID *id; + + for (id = lb->first; id; id = id->next) { + if (id->override_static != NULL && id->lib == NULL) { + BKE_override_static_update(bmain, id); + } + } + } +} + +/*********************************************************************************************************************** + * Storage (how to wtore overriding data into .blend files). + * + * Basically: + * I) Only 'differential' storage needs special handling here. All others (replacing values or + * inserting/removing items from a collection) can be handled with simply storing current content of local data-block. + * II) We store the differential value into a second 'ghost' data-block, which is an empty ID of same type as local one, + * where we only define values that need differential data. + * + * This avoids us having to modify 'real' data-block at write time (and retoring it afterwards), which is inneficient, + * and potentially dangerous (in case of concurrent access...), while not using much extra memory in typical cases. + * It also ensures stored data-block always contains exact same data as "desired" ones (kind of "baked" data-blocks). + */ + +/** Initialize an override storage. */ +OverrideStaticStorage *BKE_override_static_operations_store_initialize(void) +{ + return BKE_main_new(); +} + +/** + * Generate suitable 'write' data (this only affects differential override operations). + * + * Note that \a local ID is no more modified by this call, all extra data are stored in its temp \a storage_id copy. */ +ID *BKE_override_static_operations_store_start(OverrideStaticStorage *override_storage, ID *local) +{ + BLI_assert(local->override_static != NULL); + BLI_assert(override_storage != NULL); + const bool is_template = (local->override_static->reference == NULL); + + if (is_template) { + /* This is actually purely local data with an override template, nothing to do here! */ + return NULL; + } + + /* Forcefully ensure we know about all needed override operations. */ + BKE_override_static_operations_create(local); + + ID *storage_id; +#ifdef DEBUG_OVERRIDE_TIMEIT + TIMEIT_START_AVERAGED(BKE_override_operations_store_start); +#endif + + /* XXX TODO We may also want a specialized handling of things here too, to avoid copying heavy never-overridable + * data (like Mesh geometry etc.)? And also maybe avoid lib refcounting completely (shallow copy...). */ + /* This would imply change in handling of usercout all over RNA (and possibly all over Blender code). + * Not impossible to do, but would rather see first is extra useless usual user handling is actually + * a (performances) issue here, before doing it. */ + id_copy((Main *)override_storage, local, &storage_id, false); + + if (storage_id != NULL) { + PointerRNA rnaptr_reference, rnaptr_final, rnaptr_storage; + RNA_id_pointer_create(local->override_static->reference, &rnaptr_reference); + RNA_id_pointer_create(local, &rnaptr_final); + RNA_id_pointer_create(storage_id, &rnaptr_storage); + + if (!RNA_struct_override_store(&rnaptr_final, &rnaptr_reference, &rnaptr_storage, local->override_static)) { + BKE_libblock_free_ex(override_storage, storage_id, true, false); + storage_id = NULL; + } + } + + local->override_static->storage = storage_id; + +#ifdef DEBUG_OVERRIDE_TIMEIT + TIMEIT_END_AVERAGED(BKE_override_operations_store_start); +#endif + return storage_id; +} + +/** Restore given ID modified by \a BKE_override_operations_store_start, to its original state. */ +void BKE_override_static_operations_store_end(OverrideStaticStorage *UNUSED(override_storage), ID *local) +{ + BLI_assert(local->override_static != NULL); + + /* Nothing else to do here really, we need to keep all temp override storage data-blocks in memory until + * whole file is written anyway (otherwise we'd get mem pointers overlap...). */ + local->override_static->storage = NULL; +} + +void BKE_override_static_operations_store_finalize(OverrideStaticStorage *override_storage) +{ + /* We cannot just call BKE_main_free(override_storage), not until we have option to make 'ghost' copies of IDs + * without increasing usercount of used data-blocks... */ + ListBase *lbarray[MAX_LIBARRAY]; + int base_count, i; + + base_count = set_listbasepointers(override_storage, lbarray); + + for (i = 0; i < base_count; i++) { + ListBase *lb = lbarray[i]; + ID *id; + + while ((id = lb->first)) { + BKE_libblock_free_ex(override_storage, id, true, false); + } + } + + BKE_main_free(override_storage); +} diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c index 8d92ddcb053..0f83dfe7ecf 100644 --- a/source/blender/blenkernel/intern/library_query.c +++ b/source/blender/blenkernel/intern/library_query.c @@ -52,6 +52,7 @@ #include "DNA_mask_types.h" #include "DNA_node_types.h" #include "DNA_object_force_types.h" +#include "DNA_lightprobe_types.h" #include "DNA_rigidbody_types.h" #include "DNA_scene_types.h" #include "DNA_sensor_types.h" @@ -61,6 +62,8 @@ #include "DNA_sound_types.h" #include "DNA_text_types.h" #include "DNA_vfont_types.h" +#include "DNA_windowmanager_types.h" +#include "DNA_workspace_types.h" #include "DNA_world_types.h" #include "BLI_utildefines.h" @@ -69,8 +72,10 @@ #include "BLI_linklist_stack.h" #include "BKE_animsys.h" +#include "BKE_collection.h" #include "BKE_constraint.h" #include "BKE_fcurve.h" +#include "BKE_group.h" #include "BKE_idprop.h" #include "BKE_library.h" #include "BKE_library_query.h" @@ -82,6 +87,7 @@ #include "BKE_sca.h" #include "BKE_sequencer.h" #include "BKE_tracking.h" +#include "BKE_workspace.h" #define FOREACH_FINALIZE _finalize @@ -368,6 +374,10 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call #define CALLBACK_INVOKE(check_id_super, cb_flag) \ FOREACH_CALLBACK_INVOKE(&data, check_id_super, cb_flag) + if (id->override_static != NULL) { + CALLBACK_INVOKE_ID(id->override_static->reference, IDWALK_CB_USER | IDWALK_CB_STATIC_OVERRIDE_REFERENCE); + } + for (; id != NULL; id = (flag & IDWALK_RECURSE) ? BLI_LINKSTACK_POP(data.ids_todo) : NULL) { data.self_id = id; data.cb_flag = ID_IS_LINKED(id) ? IDWALK_CB_INDIRECT_USAGE : 0; @@ -402,8 +412,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call { Scene *scene = (Scene *) id; ToolSettings *toolsett = scene->toolsettings; - SceneRenderLayer *srl; - Base *base; CALLBACK_INVOKE(scene->camera, IDWALK_CB_NOP); CALLBACK_INVOKE(scene->world, IDWALK_CB_USER); @@ -417,31 +425,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call * since basact is just a pointer to one of those items. */ CALLBACK_INVOKE(scene->obedit, IDWALK_CB_NOP); - for (srl = scene->r.layers.first; srl; srl = srl->next) { - FreestyleModuleConfig *fmc; - FreestyleLineSet *fls; - - if (srl->mat_override) { - CALLBACK_INVOKE(srl->mat_override, IDWALK_CB_USER); - } - if (srl->light_override) { - CALLBACK_INVOKE(srl->light_override, IDWALK_CB_USER); - } - for (fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) { - if (fmc->script) { - CALLBACK_INVOKE(fmc->script, IDWALK_CB_NOP); - } - } - for (fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) { - if (fls->group) { - CALLBACK_INVOKE(fls->group, IDWALK_CB_USER); - } - if (fls->linestyle) { - CALLBACK_INVOKE(fls->linestyle, IDWALK_CB_USER); - } - } - } - if (scene->ed) { Sequence *seq; SEQP_BEGIN(scene->ed, seq) @@ -461,8 +444,35 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call CALLBACK_INVOKE(scene->gpd, IDWALK_CB_USER); - for (base = scene->base.first; base; base = base->next) { - CALLBACK_INVOKE(base->object, IDWALK_CB_USER); + FOREACH_SCENE_COLLECTION(scene, sc) + { + for (LinkData *link = sc->objects.first; link; link = link->next) { + CALLBACK_INVOKE_ID(link->data, IDWALK_CB_USER); + } + } + FOREACH_SCENE_COLLECTION_END + + ViewLayer *view_layer; + for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + CALLBACK_INVOKE(base->object, IDWALK_NOP); + } + + for (FreestyleModuleConfig *fmc = view_layer->freestyle_config.modules.first; fmc; fmc = fmc->next) { + if (fmc->script) { + CALLBACK_INVOKE(fmc->script, IDWALK_CB_NOP); + } + } + + for (FreestyleLineSet *fls = view_layer->freestyle_config.linesets.first; fls; fls = fls->next) { + if (fls->group) { + CALLBACK_INVOKE(fls->group, IDWALK_CB_USER); + } + + if (fls->linestyle) { + CALLBACK_INVOKE(fls->linestyle, IDWALK_CB_USER); + } + } } for (TimeMarker *marker = scene->markers.first; marker; marker = marker->next) { @@ -624,31 +634,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call for (i = 0; i < mesh->totcol; i++) { CALLBACK_INVOKE(mesh->mat[i], IDWALK_CB_USER); } - - /* XXX Really not happy with this - probably texface should rather use some kind of - * 'texture slots' and just set indices in each poly/face item - would also save some memory. - * Maybe a nice TODO for blender2.8? */ - if (mesh->mtface || mesh->mtpoly) { - for (i = 0; i < mesh->pdata.totlayer; i++) { - if (mesh->pdata.layers[i].type == CD_MTEXPOLY) { - MTexPoly *txface = (MTexPoly *)mesh->pdata.layers[i].data; - - for (int j = 0; j < mesh->totpoly; j++, txface++) { - CALLBACK_INVOKE(txface->tpage, IDWALK_CB_USER_ONE); - } - } - } - - for (i = 0; i < mesh->fdata.totlayer; i++) { - if (mesh->fdata.layers[i].type == CD_MTFACE) { - MTFace *tface = (MTFace *)mesh->fdata.layers[i].data; - - for (int j = 0; j < mesh->totface; j++, tface++) { - CALLBACK_INVOKE(tface->tpage, IDWALK_CB_USER_ONE); - } - } - } - } break; } @@ -691,6 +676,7 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call library_foreach_ID_as_subdata_link((ID **)&material->nodetree, callback, user_data, flag, &data); } CALLBACK_INVOKE(material->group, IDWALK_CB_USER); + CALLBACK_INVOKE(material->edit_image, IDWALK_CB_USER); break; } @@ -751,13 +737,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call break; } - case ID_SCR: - { - bScreen *screen = (bScreen *) id; - CALLBACK_INVOKE(screen->scene, IDWALK_CB_USER_ONE); - break; - } - case ID_WO: { World *world = (World *) id; @@ -780,13 +759,21 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call break; } + case ID_LP: + { + LightProbe *probe = (LightProbe *) id; + CALLBACK_INVOKE(probe->image, IDWALK_CB_USER); + break; + } + case ID_GR: { Group *group = (Group *) id; - GroupObject *gob; - for (gob = group->gobject.first; gob; gob = gob->next) { - CALLBACK_INVOKE(gob->ob, IDWALK_CB_USER_ONE); + FOREACH_GROUP_BASE(group, base) + { + CALLBACK_INVOKE(base->object, IDWALK_CB_USER_ONE); } + FOREACH_GROUP_BASE_END break; } @@ -968,6 +955,40 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call } break; } + + case ID_WM: + { + wmWindowManager *wm = (wmWindowManager *)id; + + for (wmWindow *win = wm->windows.first; win; win = win->next) { + ID *workspace = (ID *)BKE_workspace_active_get(win->workspace_hook); + + CALLBACK_INVOKE(win->scene, IDWALK_CB_USER_ONE); + + CALLBACK_INVOKE_ID(workspace, IDWALK_CB_NOP); + /* allow callback to set a different workspace */ + BKE_workspace_active_set(win->workspace_hook, (WorkSpace *)workspace); + } + break; + } + + case ID_WS: + { + WorkSpace *workspace = (WorkSpace *)id; + ListBase *layouts = BKE_workspace_layouts_get(workspace); + + for (WorkSpaceLayout *layout = layouts->first; layout; layout = layout->next) { + bScreen *screen = BKE_workspace_layout_screen_get(layout); + + /* CALLBACK_INVOKE expects an actual pointer, not a variable holding the pointer. + * However we can't acess layout->screen here since we are outside the workspace project. */ + CALLBACK_INVOKE(screen, IDWALK_CB_NOP); + /* allow callback to set a different screen */ + BKE_workspace_layout_screen_set(layout, screen); + } + + break; + } case ID_GD: { bGPdata *gpencil = (bGPdata *) id; @@ -979,11 +1000,11 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call } /* Nothing needed for those... */ + case ID_SCR: case ID_IM: case ID_VF: case ID_TXT: case ID_SO: - case ID_WM: case ID_PAL: case ID_PC: case ID_CF: @@ -1111,6 +1132,9 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used) return ELEM(id_type_used, ID_MC); /* WARNING! mask->parent.id, not typed. */ case ID_LS: return (ELEM(id_type_used, ID_TE, ID_OB)); + case ID_LP: + return ELEM(id_type_used, ID_IM); + case ID_WS: case ID_IM: case ID_VF: case ID_TXT: diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c index 31dc46a55f0..6d4c4082810 100644 --- a/source/blender/blenkernel/intern/library_remap.c +++ b/source/blender/blenkernel/intern/library_remap.c @@ -53,6 +53,7 @@ #include "DNA_mask_types.h" #include "DNA_node_types.h" #include "DNA_object_types.h" +#include "DNA_lightprobe_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_speaker_types.h" @@ -60,6 +61,7 @@ #include "DNA_text_types.h" #include "DNA_vfont_types.h" #include "DNA_windowmanager_types.h" +#include "DNA_workspace_types.h" #include "DNA_world_types.h" #include "BLI_blenlib.h" @@ -71,8 +73,8 @@ #include "BKE_brush.h" #include "BKE_camera.h" #include "BKE_cachefile.h" +#include "BKE_collection.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_fcurve.h" #include "BKE_font.h" #include "BKE_group.h" @@ -83,7 +85,9 @@ #include "BKE_key.h" #include "BKE_lamp.h" #include "BKE_lattice.h" +#include "BKE_layer.h" #include "BKE_library.h" +#include "BKE_library_override.h" #include "BKE_library_query.h" #include "BKE_library_remap.h" #include "BKE_linestyle.h" @@ -99,6 +103,7 @@ #include "BKE_object.h" #include "BKE_paint.h" #include "BKE_particle.h" +#include "BKE_lightprobe.h" #include "BKE_sca.h" #include "BKE_speaker.h" #include "BKE_sound.h" @@ -106,8 +111,12 @@ #include "BKE_scene.h" #include "BKE_text.h" #include "BKE_texture.h" +#include "BKE_workspace.h" #include "BKE_world.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #ifdef WITH_PYTHON #include "BPY_extern.h" #endif @@ -173,6 +182,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id } if (*id_p && (*id_p == old_id)) { + const bool is_reference = (cb_flag & IDWALK_CB_STATIC_OVERRIDE_REFERENCE) != 0; const bool is_indirect = (cb_flag & IDWALK_CB_INDIRECT_USAGE) != 0; const bool skip_indirect = (id_remap_data->flag & ID_REMAP_SKIP_INDIRECT_USAGE) != 0; /* Note: proxy usage implies LIB_TAG_EXTERN, so on this aspect it is direct, @@ -183,6 +193,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id const bool is_obj_editmode = (is_obj && BKE_object_is_in_editmode((Object *)id)); const bool is_never_null = ((cb_flag & IDWALK_CB_NEVER_NULL) && (new_id == NULL) && (id_remap_data->flag & ID_REMAP_FORCE_NEVER_NULL_USAGE) == 0); + const bool skip_reference = (id_remap_data->flag & ID_REMAP_SKIP_STATIC_OVERRIDE) != 0; const bool skip_never_null = (id_remap_data->flag & ID_REMAP_SKIP_NEVER_NULL_USAGE) != 0; #ifdef DEBUG_PRINT @@ -199,7 +210,8 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id * (skipped_indirect too). */ if ((is_never_null && skip_never_null) || (is_obj_editmode && (((Object *)id)->data == *id_p) && new_id != NULL) || - (skip_indirect && is_indirect)) + (skip_indirect && is_indirect) || + (is_reference && skip_reference)) { if (is_indirect) { id_remap_data->skipped_indirect++; @@ -212,7 +224,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id } } } - else if (is_never_null || is_obj_editmode) { + else if (is_never_null || is_obj_editmode || is_reference) { id_remap_data->skipped_direct++; } else { @@ -229,7 +241,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id else { if (!is_never_null) { *id_p = new_id; - DAG_id_tag_update_ex(id_remap_data->bmain, id_self, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + DEG_id_tag_update_ex(id_remap_data->bmain, id_self, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); } if (cb_flag & IDWALK_CB_USER) { id_us_min(old_id); @@ -252,17 +264,15 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id } /* Some remapping unfortunately require extra and/or specific handling, tackle those here. */ -static void libblock_remap_data_preprocess_scene_base_unlink( - IDRemap *r_id_remap_data, Scene *sce, Base *base, const bool skip_indirect, const bool is_indirect) +static void libblock_remap_data_preprocess_scene_object_unlink( + IDRemap *r_id_remap_data, Scene *sce, Object *ob, const bool skip_indirect, const bool is_indirect) { if (skip_indirect && is_indirect) { r_id_remap_data->skipped_indirect++; r_id_remap_data->skipped_refcounted++; } else { - id_us_min((ID *)base->object); - BKE_scene_base_unlink(sce, base); - MEM_freeN(base); + BKE_collections_object_remove(r_id_remap_data->bmain, &sce->id, ob, false); if (!is_indirect) { r_id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT; } @@ -283,22 +293,18 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data) /* In case we are unlinking... */ if (!r_id_remap_data->old_id) { /* ... everything from scene. */ - Base *base, *base_next; - for (base = sce->base.first; base; base = base_next) { - base_next = base->next; - libblock_remap_data_preprocess_scene_base_unlink( - r_id_remap_data, sce, base, skip_indirect, is_indirect); + FOREACH_SCENE_OBJECT(sce, ob_iter) + { + libblock_remap_data_preprocess_scene_object_unlink( + r_id_remap_data, sce, ob_iter, skip_indirect, is_indirect); } + FOREACH_SCENE_OBJECT_END } else if (GS(r_id_remap_data->old_id->name) == ID_OB) { /* ... a specific object from scene. */ Object *old_ob = (Object *)r_id_remap_data->old_id; - Base *base = BKE_scene_base_find(sce, old_ob); - - if (base) { - libblock_remap_data_preprocess_scene_base_unlink( - r_id_remap_data, sce, base, skip_indirect, is_indirect); - } + libblock_remap_data_preprocess_scene_object_unlink( + r_id_remap_data, sce, old_ob, skip_indirect, is_indirect); } } break; @@ -340,7 +346,7 @@ static void libblock_remap_data_postprocess_object_update(Main *bmain, Object *o } if (new_ob == NULL) { /* We need to remove NULL-ified groupobjects... */ for (Group *group = bmain->group.first; group; group = group->id.next) { - BKE_group_object_unlink(group, NULL, NULL, NULL); + BKE_group_object_unlink(group, NULL); } } else { @@ -350,7 +356,7 @@ static void libblock_remap_data_postprocess_object_update(Main *bmain, Object *o if (old_ob->type == OB_MBALL) { for (Object *ob = bmain->object.first; ob; ob = ob->id.next) { if (ob->type == OB_MBALL && BKE_mball_is_basis_for(ob, old_ob)) { - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } } } @@ -360,26 +366,21 @@ static void libblock_remap_data_postprocess_group_scene_unlink(Main *UNUSED(bmai { /* Note that here we assume no object has no base (i.e. all objects are assumed instanced * in one scene...). */ - for (Base *base = sce->base.first; base; base = base->next) { - if (base->flag & OB_FROMGROUP) { - Object *ob = base->object; - - if (ob->flag & OB_FROMGROUP) { - Group *grp = BKE_group_object_find(NULL, ob); - - /* Unlinked group (old_id) is still in bmain... */ - if (grp && (&grp->id == old_id || grp->id.us == 0)) { - grp = BKE_group_object_find(grp, ob); - } - if (!grp) { - ob->flag &= ~OB_FROMGROUP; - } + FOREACH_SCENE_OBJECT(sce, ob) + { + if (ob->flag & OB_FROMGROUP) { + Group *grp = BKE_group_object_find(NULL, ob); + + /* Unlinked group (old_id) is still in bmain... */ + if (grp && (&grp->id == old_id || grp->id.us == 0)) { + grp = BKE_group_object_find(grp, ob); } - if (!(ob->flag & OB_FROMGROUP)) { - base->flag &= ~OB_FROMGROUP; + if (!grp) { + ob->flag &= ~OB_FROMGROUP; } } } + FOREACH_SCENE_OBJECT_END } static void libblock_remap_data_postprocess_obdata_relink(Main *UNUSED(bmain), Object *ob, ID *new_id) @@ -594,8 +595,8 @@ void BKE_libblock_remap_locked( libblock_remap_data_postprocess_nodetree_update(bmain, new_id); BKE_main_lock(bmain); - /* Full rebuild of DAG! */ - DAG_relations_tag_update(bmain); + /* Full rebuild of DEG! */ + DEG_relations_tag_update(bmain); } void BKE_libblock_remap(Main *bmain, void *old_idv, void *new_idv, const short remap_flags) @@ -747,6 +748,10 @@ void BKE_libblock_free_data(ID *id, const bool do_id_user) MEM_freeN(id->properties); } + if (id->override_static) { + BKE_override_static_free(&id->override_static); + } + /* XXX TODO remove animdata handling from each type's freeing func, and do it here, like for copy! */ } @@ -811,6 +816,9 @@ void BKE_libblock_free_datablock(ID *id, const int UNUSED(flag)) case ID_SPK: BKE_speaker_free((Speaker *)id); break; + case ID_LP: + BKE_lightprobe_free((LightProbe *)id); + break; case ID_SO: BKE_sound_free((bSound *)id); break; @@ -857,6 +865,9 @@ void BKE_libblock_free_datablock(ID *id, const int UNUSED(flag)) case ID_CF: BKE_cachefile_free((CacheFile *)id); break; + case ID_WS: + BKE_workspace_free((WorkSpace *)id); + break; } } @@ -895,7 +906,7 @@ void BKE_id_free_ex(Main *bmain, void *idv, int flag, const bool use_flag_from_i const short type = GS(id->name); if (bmain && (flag & LIB_ID_FREE_NO_DEG_TAG) == 0) { - DAG_id_type_tag(bmain, type); + DEG_id_type_tag(bmain, type); } #ifdef WITH_PYTHON @@ -958,7 +969,7 @@ void BKE_libblock_free_ex(Main *bmain, void *idv, const bool do_id_user, const b short type = GS(id->name); ListBase *lb = which_libbase(bmain, type); - DAG_id_type_tag(bmain, type); + DEG_id_type_tag(bmain, type); #ifdef WITH_PYTHON #ifdef WITH_PYTHON_SAFETY diff --git a/source/blender/blenkernel/intern/lightprobe.c b/source/blender/blenkernel/intern/lightprobe.c new file mode 100644 index 00000000000..057b6aaaf65 --- /dev/null +++ b/source/blender/blenkernel/intern/lightprobe.c @@ -0,0 +1,101 @@ +/* + * ***** 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) Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/lightprobe.c + * \ingroup bke + */ + +#include "DNA_object_types.h" +#include "DNA_lightprobe_types.h" + +#include "BLI_math.h" +#include "BLI_utildefines.h" + +#include "BKE_animsys.h" +#include "BKE_global.h" +#include "BKE_main.h" +#include "BKE_lightprobe.h" + +void BKE_lightprobe_init(LightProbe *probe) +{ + BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(probe, id)); + + probe->grid_resolution_x = probe->grid_resolution_y = probe->grid_resolution_z = 4; + probe->distinf = 2.5f; + probe->distpar = 2.5f; + probe->falloff = 0.2f; + probe->clipsta = 0.8f; + probe->clipend = 40.0f; + probe->vis_bias = 1.0f; + probe->vis_blur = 0.2f; + probe->intensity = 1.0f; + probe->data_draw_size = 1.0f; + + probe->flag = LIGHTPROBE_FLAG_SHOW_INFLUENCE | LIGHTPROBE_FLAG_SHOW_DATA; +} + +void *BKE_lightprobe_add(Main *bmain, const char *name) +{ + LightProbe *probe; + + probe = BKE_libblock_alloc(bmain, ID_LP, name, 0); + + BKE_lightprobe_init(probe); + + return probe; +} + +/** + * Only copy internal data of LightProbe ID from source to already allocated/initialized destination. + * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs. + * + * WARNING! This function will not handle ID user count! + * + * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). + */ +void BKE_lightprobe_copy_data( + Main *UNUSED(bmain), LightProbe *UNUSED(probe_dst), const LightProbe *UNUSED(probe_src), const int UNUSED(flag)) +{ + /* Nothing to do here. */ +} + +LightProbe *BKE_lightprobe_copy(Main *bmain, const LightProbe *probe) +{ + LightProbe *probe_copy; + BKE_id_copy_ex(bmain, &probe->id, (ID **)&probe_copy, 0, false); + return probe_copy; +} + +void BKE_lightprobe_make_local(Main *bmain, LightProbe *probe, const bool lib_local) +{ + BKE_id_make_local_generic(bmain, &probe->id, true, lib_local); +} + +void BKE_lightprobe_free(LightProbe *probe) +{ + BKE_animdata_free((ID *)probe, false); +} diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c index 0465c5d54f7..2fc4c81cb0b 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -215,12 +215,13 @@ void BKE_linestyle_make_local(struct Main *bmain, FreestyleLineStyle *linestyle, FreestyleLineStyle *BKE_linestyle_active_from_scene(Scene *scene) { - SceneRenderLayer *actsrl = BLI_findlink(&scene->r.layers, scene->r.actlay); - FreestyleConfig *config = &actsrl->freestyleConfig; - FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config); - - if (lineset) { - return lineset->linestyle; + ViewLayer *active_render_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer); + if (active_render_layer) { + FreestyleConfig *config = &active_render_layer->freestyle_config; + FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config); + if (lineset) { + return lineset->linestyle; + } } return NULL; } diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index ff4e7f36018..3256c16e2f6 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -51,7 +51,6 @@ #include "BKE_animsys.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_library.h" #include "BKE_main.h" @@ -62,6 +61,8 @@ #include "BKE_movieclip.h" #include "BKE_image.h" +#include "DEG_depsgraph_build.h" + static struct { ListBase splines; struct GHash *id_hash; @@ -818,7 +819,7 @@ Mask *BKE_mask_new(Main *bmain, const char *name) mask->sfra = 1; mask->efra = 100; - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); return mask; } @@ -1458,18 +1459,6 @@ void BKE_mask_evaluate_all_masks(Main *bmain, float ctime, const bool do_newfram } } -void BKE_mask_update_scene(Main *bmain, Scene *scene) -{ - Mask *mask; - - for (mask = bmain->mask.first; mask; mask = mask->id.next) { - if (mask->id.recalc & ID_RECALC_ALL) { - bool do_new_frame = (mask->id.recalc & ID_RECALC_DATA) != 0; - BKE_mask_evaluate_all_masks(bmain, CFRA, do_new_frame); - } - } -} - void BKE_mask_parent_init(MaskParent *parent) { parent->id_type = ID_MC; diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c index 0d71cc548c7..f60d87f2464 100644 --- a/source/blender/blenkernel/intern/mask_evaluate.c +++ b/source/blender/blenkernel/intern/mask_evaluate.c @@ -42,10 +42,11 @@ #include "DNA_mask_types.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_mask.h" +#include "DEG_depsgraph.h" + unsigned int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height) { diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 0dd7047a376..7235aa0aaf6 100644 --- a/source/blender/blenkernel/intern/material.c +++ b/source/blender/blenkernel/intern/material.c @@ -58,7 +58,6 @@ #include "BKE_animsys.h" #include "BKE_displist.h" #include "BKE_global.h" -#include "BKE_depsgraph.h" #include "BKE_icons.h" #include "BKE_image.h" #include "BKE_library.h" @@ -73,6 +72,8 @@ #include "BKE_editmesh.h" #include "BKE_font.h" +#include "DEG_depsgraph_build.h" + #include "GPU_material.h" /* used in UI and render */ @@ -206,6 +207,8 @@ void BKE_material_init(Material *ma) ma->mode2 = MA_CASTSHADOW; ma->shade_flag = MA_APPROX_OCCLUSION; ma->preview = NULL; + + ma->alpha_threshold = 0.5f; } Material *BKE_material_add(Main *bmain, const char *name) @@ -257,6 +260,8 @@ void BKE_material_copy_data(Main *bmain, Material *ma_dst, const Material *ma_sr } BLI_listbase_clear(&ma_dst->gpumaterial); + + /* TODO Duplicate Engine Settings and set runtime to NULL */ } Material *BKE_material_copy(Main *bmain, const Material *ma) @@ -299,6 +304,8 @@ Material *BKE_material_localize(Material *ma) man->nodetree = ntreeLocalize(ma->nodetree); BLI_listbase_clear(&man->gpumaterial); + + /* TODO Duplicate Engine Settings and set runtime to NULL */ return man; } @@ -454,7 +461,7 @@ void BKE_material_resize_id(Main *bmain, ID *id, short totcol, bool do_id_user) } *totcolp = totcol; - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); } void BKE_material_append_id(Main *bmain, ID *id, Material *ma) @@ -471,7 +478,7 @@ void BKE_material_append_id(Main *bmain, ID *id, Material *ma) id_us_plus((ID *)ma); test_all_objects_materials(bmain, id); - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); } } @@ -505,7 +512,7 @@ Material *BKE_material_pop_id(Main *bmain, ID *id, int index_i, bool update_data material_data_index_remove_id(id, index); } - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); } } @@ -532,7 +539,7 @@ void BKE_material_clear_id(Main *bmain, ID *id, bool update_data) material_data_index_clear_id(id); } - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); } } @@ -627,7 +634,7 @@ void BKE_material_resize_object(Main *bmain, Object *ob, const short totcol, boo if (ob->totcol && ob->actcol == 0) ob->actcol = 1; if (ob->actcol > ob->totcol) ob->actcol = ob->totcol; - DAG_relations_tag_update(bmain); + DEG_relations_tag_update(bmain); } void test_object_materials(Object *ob, ID *id) @@ -967,7 +974,7 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb) if (needtang) ma->mode |= MA_NORMAP_TANG; else ma->mode &= ~MA_NORMAP_TANG; - if (ma->mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) { + if (ma->mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) { needuv = 1; if (r_mode & R_OSA) ma->texco |= TEXCO_OSA; /* for texfaces */ } @@ -1149,61 +1156,6 @@ bool material_in_material(Material *parmat, Material *mat) /* ****************** */ -/* Update drivers for materials in a nodetree */ -static void material_node_drivers_update(Scene *scene, bNodeTree *ntree, float ctime) -{ - bNode *node; - - /* nodetree itself */ - if (ntree->adt && ntree->adt->drivers.first) { - BKE_animsys_evaluate_animdata(scene, &ntree->id, ntree->adt, ctime, ADT_RECALC_DRIVERS); - } - - /* nodes */ - for (node = ntree->nodes.first; node; node = node->next) { - if (node->id) { - if (GS(node->id->name) == ID_MA) { - material_drivers_update(scene, (Material *)node->id, ctime); - } - else if (node->type == NODE_GROUP) { - material_node_drivers_update(scene, (bNodeTree *)node->id, ctime); - } - } - } -} - -/* Calculate all drivers for materials - * FIXME: this is really a terrible method which may result in some things being calculated - * multiple times. However, without proper despgraph support for these things, we are forced - * into this sort of thing... - */ -void material_drivers_update(Scene *scene, Material *ma, float ctime) -{ - //if (G.f & G_DEBUG) - // printf("material_drivers_update(%s, %s)\n", scene->id.name, ma->id.name); - - /* Prevent infinite recursion by checking (and tagging the material) as having been visited already - * (see BKE_scene_update_tagged()). This assumes ma->id.tag & LIB_TAG_DOIT isn't set by anything else - * in the meantime... [#32017] - */ - if (ma->id.tag & LIB_TAG_DOIT) - return; - - ma->id.tag |= LIB_TAG_DOIT; - - /* material itself */ - if (ma->adt && ma->adt->drivers.first) { - BKE_animsys_evaluate_animdata(scene, &ma->id, ma->adt, ctime, ADT_RECALC_DRIVERS); - } - - /* nodes */ - if (ma->nodetree) { - material_node_drivers_update(scene, ma->nodetree, ctime); - } - - ma->id.tag &= ~LIB_TAG_DOIT; -} - bool BKE_object_material_slot_remove(Object *ob) { Material *mao, ***matarar; @@ -1328,6 +1280,14 @@ void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma) bool use_nodes = BKE_scene_use_new_shading_nodes(scene); bool is_bi = BKE_scene_uses_blender_internal(scene) || BKE_scene_uses_blender_game(scene); + + /* XXX, for 2.8 testing & development its useful to have non Cycles/BI engines use material nodes + * In the future we may have some way to check this which each engine can define. + * For now use material slots for Clay/Eevee. + * - Campbell */ + if (!(use_nodes || is_bi)) { + is_bi = true; + } if (!ma) return; @@ -1726,6 +1686,7 @@ void copy_matcopybuf(Material *ma) matcopybuf.nodetree = ntreeCopyTree_ex(ma->nodetree, G.main, false); matcopybuf.preview = NULL; BLI_listbase_clear(&matcopybuf.gpumaterial); + /* TODO Duplicate Engine Settings and set runtime to NULL */ matcopied = 1; } @@ -1781,501 +1742,40 @@ void paste_matcopybuf(Material *ma) ma->nodetree = ntreeCopyTree_ex(matcopybuf.nodetree, G.main, false); } - -/*********************** texface to material convert functions **********************/ -/* encode all the TF information into a single int */ -static int encode_tfaceflag(MTFace *tf, int convertall) +struct Image *BKE_object_material_edit_image_get(Object *ob, short mat_nr) { - /* calculate the flag */ - int flag = tf->mode; - - /* options that change the material offline render */ - if (!convertall) { - flag &= ~TF_OBCOL; - } - - /* clean flags that are not being converted */ - flag &= ~TF_TEX; - flag &= ~TF_SHAREDVERT; - flag &= ~TF_SHAREDCOL; - flag &= ~TF_CONVERTED; - - /* light tface flag is ignored in GLSL mode */ - flag &= ~TF_LIGHT; - - /* 15 is how big the flag can be - hardcoded here and in decode_tfaceflag() */ - flag |= tf->transp << 15; - - /* increase 1 so flag 0 is different than no flag yet */ - return flag + 1; + Material *ma = give_current_material(ob, mat_nr + 1); + return ma ? ma->edit_image : NULL; } -/* set the material options based in the tface flag */ -static void decode_tfaceflag(Material *ma, int flag, int convertall) +struct Image **BKE_object_material_edit_image_get_array(Object *ob) { - int alphablend; - GameSettings *game = &ma->game; - - /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */ - flag -= 1; - - alphablend = flag >> 15; /* encoded in the encode_tfaceflag function */ - (*game).flag = 0; - - /* General Material Options */ - if ((flag & TF_DYNAMIC) == 0) (*game).flag |= GEMAT_NOPHYSICS; - - /* Material Offline Rendering Properties */ - if (convertall) { - if (flag & TF_OBCOL) ma->shade_flag |= MA_OBCOLOR; + Image **image_array = MEM_mallocN(sizeof(Material *) * ob->totcol, __func__); + for (int i = 0; i < ob->totcol; i++) { + image_array[i] = BKE_object_material_edit_image_get(ob, i); } - - /* Special Face Properties */ - if ((flag & TF_TWOSIDE) == 0) (*game).flag |= GEMAT_BACKCULL; - if (flag & TF_INVISIBLE) (*game).flag |= GEMAT_INVISIBLE; - if (flag & TF_BMFONT) (*game).flag |= GEMAT_TEXT; - - /* Face Orientation */ - if (flag & TF_BILLBOARD) (*game).face_orientation |= GEMAT_HALO; - else if (flag & TF_BILLBOARD2) (*game).face_orientation |= GEMAT_BILLBOARD; - else if (flag & TF_SHADOW) (*game).face_orientation |= GEMAT_SHADOW; - - /* Alpha Blend */ - if (flag & TF_ALPHASORT && ELEM(alphablend, TF_ALPHA, TF_ADD)) (*game).alpha_blend = GEMAT_ALPHA_SORT; - else if (alphablend & TF_ALPHA) (*game).alpha_blend = GEMAT_ALPHA; - else if (alphablend & TF_ADD) (*game).alpha_blend = GEMAT_ADD; - else if (alphablend & TF_CLIP) (*game).alpha_blend = GEMAT_CLIP; -} - -/* boolean check to see if the mesh needs a material */ -static int check_tfaceneedmaterial(int flag) -{ - /* check if the flags we have are not deprecated != than default material options - * also if only flags are visible and collision see if all objects using this mesh have this option in physics */ - - /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */ - flag -= 1; - - /* deprecated flags */ - flag &= ~TF_OBCOL; - flag &= ~TF_SHAREDVERT; - flag &= ~TF_SHAREDCOL; - - /* light tface flag is ignored in GLSL mode */ - flag &= ~TF_LIGHT; - - /* automatic detected if tex image has alpha */ - flag &= ~(TF_ALPHA << 15); - /* automatic detected if using texture */ - flag &= ~TF_TEX; - - /* settings for the default NoMaterial */ - if (flag == TF_DYNAMIC) - return 0; - - else - return 1; -} - -/* return number of digits of an integer */ -/* XXX to be optmized or replaced by an equivalent blender internal function */ -static int integer_getdigits(int number) -{ - int i = 0; - if (number == 0) return 1; - - while (number != 0) { - number = (int)(number / 10); - i++; - } - return i; -} - -static void calculate_tface_materialname(char *matname, char *newname, int flag) -{ - /* if flag has only light and collision and material matches those values - * you can do strcpy(name, mat_name); - * otherwise do: */ - int digits = integer_getdigits(flag); - /* clamp the old name, remove the MA prefix and add the .TF.flag suffix - * e.g. matname = "MALoooooooooooooongName"; newname = "Loooooooooooooon.TF.2" */ - BLI_snprintf(newname, MAX_ID_NAME, "%.*s.TF.%0*d", MAX_ID_NAME - (digits + 5), matname, digits, flag); -} - -/* returns -1 if no match */ -static short mesh_getmaterialnumber(Mesh *me, Material *ma) -{ - short a; - - for (a = 0; a < me->totcol; a++) { - if (me->mat[a] == ma) { - return a; - } - } - - return -1; -} - -/* append material */ -static short mesh_addmaterial(Mesh *me, Material *ma) -{ - BKE_material_append_id(G.main, &me->id, NULL); - me->mat[me->totcol - 1] = ma; - - id_us_plus(&ma->id); - - return me->totcol - 1; + return image_array; } -static void set_facetexture_flags(Material *ma, Image *image) +bool BKE_object_material_edit_image_set(Object *ob, short mat_nr, Image *image) { - if (image) { - ma->mode |= MA_FACETEXTURE; - /* we could check if the texture has alpha, but then more meshes sharing the same - * material may need it. Let's make it simple. */ - if (BKE_image_has_alpha(image)) - ma->mode |= MA_FACETEXTURE_ALPHA; - } -} - -/* returns material number */ -static short convert_tfacenomaterial(Main *main, Mesh *me, MTFace *tf, int flag) -{ - Material *ma; - char idname[MAX_ID_NAME]; - short mat_nr = -1; - - /* new material, the name uses the flag*/ - BLI_snprintf(idname, sizeof(idname), "MAMaterial.TF.%0*d", integer_getdigits(flag), flag); - - if ((ma = BLI_findstring(&main->mat, idname + 2, offsetof(ID, name) + 2))) { - mat_nr = mesh_getmaterialnumber(me, ma); - /* assign the material to the mesh */ - if (mat_nr == -1) mat_nr = mesh_addmaterial(me, ma); - - /* if needed set "Face Textures [Alpha]" Material options */ - set_facetexture_flags(ma, tf->tpage); - } - /* create a new material */ - else { - ma = BKE_material_add(main, idname + 2); - - if (ma) { - printf("TexFace Convert: Material \"%s\" created.\n", idname + 2); - mat_nr = mesh_addmaterial(me, ma); - - /* if needed set "Face Textures [Alpha]" Material options */ - set_facetexture_flags(ma, tf->tpage); - - decode_tfaceflag(ma, flag, 1); - /* the final decoding will happen after, outside the main loop - * for now store the flag into the material and change light/tex/collision - * store the flag as a negative number */ - ma->game.flag = -flag; - id_us_min((ID *)ma); - } - else { - printf("Error: Unable to create Material \"%s\" for Mesh \"%s\".", idname + 2, me->id.name + 2); - } - } - - /* set as converted, no need to go bad to this face */ - tf->mode |= TF_CONVERTED; - return mat_nr; -} - -/* Function to fully convert materials */ -static void convert_tfacematerial(Main *main, Material *ma) -{ - Mesh *me; - Material *mat_new; - MFace *mf; - MTFace *tf; - int flag, index; - int a; - short mat_nr; - CustomDataLayer *cdl; - char idname[MAX_ID_NAME]; - - for (me = main->mesh.first; me; me = me->id.next) { - /* check if this mesh uses this material */ - for (a = 0; a < me->totcol; a++) - if (me->mat[a] == ma) break; - - /* no material found */ - if (a == me->totcol) continue; - - /* get the active tface layer */ - index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE); - cdl = (index == -1) ? NULL : &me->fdata.layers[index]; - if (!cdl) continue; - - /* loop over all the faces and stop at the ones that use the material*/ - for (a = 0, mf = me->mface; a < me->totface; a++, mf++) { - if (me->mat[mf->mat_nr] != ma) continue; - - /* texface data for this face */ - tf = ((MTFace *)cdl->data) + a; - flag = encode_tfaceflag(tf, 1); - - /* the name of the new material */ - calculate_tface_materialname(ma->id.name, (char *)&idname, flag); - - if ((mat_new = BLI_findstring(&main->mat, idname + 2, offsetof(ID, name) + 2))) { - /* material already existent, see if the mesh has it */ - mat_nr = mesh_getmaterialnumber(me, mat_new); - /* material is not in the mesh, add it */ - if (mat_nr == -1) mat_nr = mesh_addmaterial(me, mat_new); - } - /* create a new material */ - else { - mat_new = BKE_material_copy(main, ma); - if (mat_new) { - /* rename the material*/ - BLI_strncpy(mat_new->id.name, idname, sizeof(mat_new->id.name)); - id_us_min((ID *)mat_new); - - mat_nr = mesh_addmaterial(me, mat_new); - decode_tfaceflag(mat_new, flag, 1); - } - else { - printf("Error: Unable to create Material \"%s\" for Mesh \"%s.", idname + 2, me->id.name + 2); - mat_nr = mf->mat_nr; - continue; - } - } - - /* if the material has a texture but no texture channel - * set "Face Textures [Alpha]" Material options - * actually we need to run it always, because of old behavior - * of using face texture if any texture channel was present (multitex) */ - //if ((!mat_new->mtex[0]) && (!mat_new->mtex[0]->tex)) - set_facetexture_flags(mat_new, tf->tpage); - - /* set the material number to the face*/ - mf->mat_nr = mat_nr; - } - /* remove material from mesh */ - for (a = 0; a < me->totcol; ) { - if (me->mat[a] == ma) { - BKE_material_pop_id(main, &me->id, a, true); - } - else { - a++; - } - } + Material *ma = give_current_material(ob, mat_nr + 1); + if (ma) { + /* both may be NULL */ + id_us_min((ID *)ma->edit_image); + ma->edit_image = image; + id_us_plus((ID *)ma->edit_image); + return true; } + return false; } - -#define MAT_BGE_DISPUTED -99999 - -int do_version_tface(Main *main) +void BKE_material_eval(const struct EvaluationContext *UNUSED(eval_ctx), Material *material) { - Mesh *me; - Material *ma; - MFace *mf; - MTFace *tf; - CustomDataLayer *cdl; - int a; - int flag; - int index; - - /* Operator in help menu has been removed for 2.7x */ - int fileload = 1; - - /* sometimes mesh has no materials but will need a new one. In those - * cases we need to ignore the mf->mat_nr and only look at the face - * mode because it can be zero as uninitialized or the 1st created material - */ - int nomaterialslots; - - /* alert to user to check the console */ - int nowarning = 1; - - /* mark all the materials to conversion with a flag - * if there is tface create a complete flag for that storing in flag - * if there is tface and flag > 0: creates a new flag based on this face - * if flags are different set flag to -1 - */ - - /* 1st part: marking mesh materials to update */ - for (me = main->mesh.first; me; me = me->id.next) { - if (ID_IS_LINKED(me)) continue; - - /* get the active tface layer */ - index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE); - cdl = (index == -1) ? NULL : &me->fdata.layers[index]; - if (!cdl) continue; - - nomaterialslots = (me->totcol == 0 ? 1 : 0); - - /* loop over all the faces*/ - for (a = 0, mf = me->mface; a < me->totface; a++, mf++) { - /* texface data for this face */ - tf = ((MTFace *)cdl->data) + a; - - /* conversion should happen only once */ - if (fileload) - tf->mode &= ~TF_CONVERTED; - else { - if ((tf->mode & TF_CONVERTED)) continue; - else tf->mode |= TF_CONVERTED; - } - - /* no material slots */ - if (nomaterialslots) { - flag = encode_tfaceflag(tf, 1); - - /* create/find a new material and assign to the face */ - if (check_tfaceneedmaterial(flag)) { - mf->mat_nr = convert_tfacenomaterial(main, me, tf, flag); - } - /* else mark them as no-material to be reverted to 0 later */ - else { - mf->mat_nr = -1; - } - } - else if (mf->mat_nr < me->totcol) { - ma = me->mat[mf->mat_nr]; - - /* no material create one if necessary */ - if (!ma) { - /* find a new material and assign to the face */ - flag = encode_tfaceflag(tf, 1); - - /* create/find a new material and assign to the face */ - if (check_tfaceneedmaterial(flag)) - mf->mat_nr = convert_tfacenomaterial(main, me, tf, flag); - - continue; - } - - /* we can't read from this if it comes from a library, - * at doversion time: direct_link might not have happened on it, - * so ma->mtex is not pointing to valid memory yet. - * later we could, but it's better not */ - else if (ID_IS_LINKED(ma)) - continue; - - /* material already marked as disputed */ - else if (ma->game.flag == MAT_BGE_DISPUTED) - continue; - - /* found a material */ - else { - flag = encode_tfaceflag(tf, ((fileload) ? 0 : 1)); - - /* first time changing this material */ - if (ma->game.flag == 0) - ma->game.flag = -flag; - - /* mark material as disputed */ - else if (ma->game.flag != -flag) { - ma->game.flag = MAT_BGE_DISPUTED; - continue; - } - - /* material ok so far */ - else { - ma->game.flag = -flag; - - /* some people uses multitexture with TexFace by creating a texture - * channel which not necessarily the tf->tpage image. But the game engine - * was enabling it. Now it's required to set "Face Texture [Alpha] in the - * material settings. */ - if (!fileload) - set_facetexture_flags(ma, tf->tpage); - } - } - } - else { - continue; - } - } - - /* if we didn't have material slot and now we do, we need to - * make sure the materials are correct */ - if (nomaterialslots) { - if (me->totcol > 0) { - for (a = 0, mf = me->mface; a < me->totface; a++, mf++) { - if (mf->mat_nr == -1) { - /* texface data for this face */ - tf = ((MTFace *)cdl->data) + a; - mf->mat_nr = convert_tfacenomaterial(main, me, tf, encode_tfaceflag(tf, 1)); - } - } - } - else { - for (a = 0, mf = me->mface; a < me->totface; a++, mf++) { - mf->mat_nr = 0; - } - } - } - + if (G.debug & G_DEBUG_DEPSGRAPH) { + printf("%s on %s (%p)\n", __func__, material->id.name, material); } - - /* 2nd part - conversion */ - /* skip library files */ - - /* we shouldn't loop through the materials created in the loop. make the loop stop at its original length) */ - for (ma = main->mat.first, a = 0; ma; ma = ma->id.next, a++) { - if (ID_IS_LINKED(ma)) continue; - - /* disputed material */ - if (ma->game.flag == MAT_BGE_DISPUTED) { - ma->game.flag = 0; - if (fileload) { - printf("Warning: material \"%s\" skipped.\n", ma->id.name + 2); - nowarning = 0; - } - else { - convert_tfacematerial(main, ma); - } - continue; - } - - /* no conflicts in this material - 90% of cases - * convert from tface system to material */ - else if (ma->game.flag < 0) { - decode_tfaceflag(ma, -(ma->game.flag), 1); - - /* material is good make sure all faces using - * this material are set to converted */ - if (fileload) { - for (me = main->mesh.first; me; me = me->id.next) { - /* check if this mesh uses this material */ - for (a = 0; a < me->totcol; a++) - if (me->mat[a] == ma) break; - - /* no material found */ - if (a == me->totcol) continue; - - /* get the active tface layer */ - index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE); - cdl = (index == -1) ? NULL : &me->fdata.layers[index]; - if (!cdl) continue; - - /* loop over all the faces and stop at the ones that use the material*/ - for (a = 0, mf = me->mface; a < me->totface; a++, mf++) { - if (me->mat[mf->mat_nr] == ma) { - /* texface data for this face */ - tf = ((MTFace *)cdl->data) + a; - tf->mode |= TF_CONVERTED; - } - } - } - } - } - /* material is not used by faces with texface - * set the default flag - do it only once */ - else { - if (fileload) { - ma->game.flag = GEMAT_BACKCULL; - } - } + if ((BLI_listbase_is_empty(&material->gpumaterial) == false)) { + GPU_material_uniform_buffer_tag_dirty(&material->gpumaterial); } - - return nowarning; } - diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index dfc49c996b1..5a0ac86823f 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -57,7 +57,6 @@ #include "BKE_animsys.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_scene.h" #include "BKE_library.h" #include "BKE_library_query.h" @@ -67,6 +66,8 @@ #include "BKE_object.h" #include "BKE_material.h" +//#include "DEG_depsgraph.h" + /* Functions */ /** Free (or release) any data used by this mball (does not free the mball itself). */ @@ -74,6 +75,8 @@ void BKE_mball_free(MetaBall *mb) { BKE_animdata_free((ID *)mb, false); + BKE_mball_batch_cache_free(mb); + MEM_SAFE_FREE(mb->mat); BLI_freelistN(&mb->elems); @@ -119,6 +122,7 @@ void BKE_mball_copy_data(Main *UNUSED(bmain), MetaBall *mb_dst, const MetaBall * mb_dst->editelems = NULL; mb_dst->lastelem = NULL; + mb_dst->batch_cache = NULL; } MetaBall *BKE_mball_copy(Main *bmain, const MetaBall *mb) @@ -325,7 +329,7 @@ void BKE_mball_properties_copy(Scene *scene, Object *active_object) int basisnr, obnr; char basisname[MAX_ID_NAME], obname[MAX_ID_NAME]; SceneBaseIter iter; - EvaluationContext *eval_ctx = G.main->eval_ctx; + struct EvaluationContext *eval_ctx = G.main->eval_ctx; BLI_split_name_num(basisname, &basisnr, active_object->id.name + 2, '.'); @@ -362,27 +366,25 @@ void BKE_mball_properties_copy(Scene *scene, Object *active_object) */ Object *BKE_mball_basis_find(Scene *scene, Object *basis) { - Scene *sce_iter = scene; - Base *base; - Object *ob, *bob = basis; + Object *bob = basis; int basisnr, obnr; char basisname[MAX_ID_NAME], obname[MAX_ID_NAME]; - SceneBaseIter iter; - EvaluationContext *eval_ctx = G.main->eval_ctx; BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.'); - BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL); - while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) { - if ((ob->type == OB_MBALL) && !(base->flag & OB_FROMDUPLI)) { - if (ob != bob) { - BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.'); - - /* object ob has to be in same "group" ... it means, that it has to have same base of its name */ - if (STREQ(obname, basisname)) { - if (obnr < basisnr) { - basis = ob; - basisnr = obnr; + for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + Object *ob = base->object; + if ((ob->type == OB_MBALL) && !(base->flag & OB_FROMDUPLI)) { + if (ob != bob) { + BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.'); + + /* object ob has to be in same "group" ... it means, that it has to have same base of its name */ + if (STREQ(obname, basisname)) { + if (obnr < basisnr) { + basis = ob; + basisnr = obnr; + } } } } @@ -539,7 +541,51 @@ void BKE_mball_select_swap(struct MetaBall *mb) /* **** Depsgraph evaluation **** */ -void BKE_mball_eval_geometry(EvaluationContext *UNUSED(eval_ctx), +void BKE_mball_eval_geometry(const struct EvaluationContext *UNUSED(eval_ctx), MetaBall *UNUSED(mball)) { } + +/* Draw Engine */ + +/* use for draw-manager only. */ +void BKE_mball_element_calc_display_m3x4(float r_scale_xform[3][4], + const float obmat[4][4], + const float local_pos[3]) +{ + float world_pos[3], scamat[3][3]; + mul_v3_m4v3(world_pos, obmat, local_pos); + copy_m3_m4(scamat, obmat); + { + /* Get the normalized inverse matrix to extract only + * the scale of Scamat */ + float iscamat[3][3]; + invert_m3_m3(iscamat, scamat); + normalize_m3(iscamat); + mul_m3_m3_post(scamat, iscamat); + } + + copy_v3_v3(r_scale_xform[0], scamat[0]); + copy_v3_v3(r_scale_xform[1], scamat[1]); + copy_v3_v3(r_scale_xform[2], scamat[2]); + + r_scale_xform[0][3] = world_pos[0]; + r_scale_xform[1][3] = world_pos[1]; + r_scale_xform[2][3] = world_pos[2]; +} + +void (*BKE_mball_batch_cache_dirty_cb)(MetaBall *mb, int mode) = NULL; +void (*BKE_mball_batch_cache_free_cb)(MetaBall *mb) = NULL; + +void BKE_mball_batch_cache_dirty(MetaBall *mb, int mode) +{ + if (mb->batch_cache) { + BKE_mball_batch_cache_dirty_cb(mb, mode); + } +} +void BKE_mball_batch_cache_free(MetaBall *mb) +{ + if (mb->batch_cache) { + BKE_mball_batch_cache_free_cb(mb); + } +} diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c index a1ae3a7f572..5e63b5c1607 100644 --- a/source/blender/blenkernel/intern/mball_tessellate.c +++ b/source/blender/blenkernel/intern/mball_tessellate.c @@ -48,11 +48,12 @@ #include "BKE_global.h" -#include "BKE_depsgraph.h" #include "BKE_scene.h" #include "BKE_displist.h" #include "BKE_mball_tessellate.h" /* own include */ +#include "DEG_depsgraph.h" + #include "BLI_strict_flags.h" /* experimental (faster) normal calculation */ @@ -1055,7 +1056,7 @@ static void polygonize(PROCESS *process) * Iterates over ALL objects in the scene and all of its sets, including * making all duplis(not only metas). Copies metas to mainb array. * Computes bounding boxes for building BVH. */ -static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *ob) +static void init_meta(const EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *ob) { Scene *sce_iter = scene; Base *base; @@ -1080,7 +1081,7 @@ static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scen zero_size = 0; ml = NULL; - if (bob == ob && (base->flag & OB_FROMDUPLI) == 0) { + if (bob == ob && (base->flag_legacy & OB_FROMDUPLI) == 0) { mb = ob->data; if (mb->editelems) ml = mb->editelems->first; @@ -1232,7 +1233,7 @@ static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scen } } -void BKE_mball_polygonize(EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase) +void BKE_mball_polygonize(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase) { MetaBall *mb; DispList *dl; diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index bf937267b83..3217c234718 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -59,7 +59,6 @@ #include "BKE_multires.h" #include "BKE_key.h" #include "BKE_mball.h" -#include "BKE_depsgraph.h" /* these 2 are only used by conversion functions */ #include "BKE_curve.h" /* -- */ @@ -127,7 +126,7 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2 for (i = 0; i < c1->totlayer; i++) { if (ELEM(c1->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY, - CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) + CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT)) { i1++; } @@ -135,7 +134,7 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2 for (i = 0; i < c2->totlayer; i++) { if (ELEM(c2->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY, - CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) + CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT)) { i2++; } @@ -149,14 +148,14 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2 i1 = 0; i2 = 0; for (i = 0; i < tot; i++) { while (i1 < c1->totlayer && !ELEM(l1->type, CD_MVERT, CD_MEDGE, CD_MPOLY, - CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) + CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT)) { i1++; l1++; } while (i2 < c2->totlayer && !ELEM(l2->type, CD_MVERT, CD_MEDGE, CD_MPOLY, - CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT)) + CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT)) { i2++; l2++; @@ -324,7 +323,7 @@ static void mesh_ensure_tessellation_customdata(Mesh *me) * Callers could also check but safer to do here - campbell */ } else { - const int tottex_original = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY); + const int tottex_original = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); const int totcol_original = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL); const int tottex_tessface = CustomData_number_of_layers(&me->fdata, CD_MTFACE); @@ -335,7 +334,7 @@ static void mesh_ensure_tessellation_customdata(Mesh *me) { BKE_mesh_tessface_clear(me); - CustomData_from_bmeshpoly(&me->fdata, &me->pdata, &me->ldata, me->totface); + CustomData_from_bmeshpoly(&me->fdata, &me->ldata, me->totface); /* TODO - add some --debug-mesh option */ if (G.debug & G_DEBUG) { @@ -344,7 +343,7 @@ static void mesh_ensure_tessellation_customdata(Mesh *me) * and check if there was any data to begin with, for now just print the warning with * some info to help troubleshoot whats going on - campbell */ printf("%s: warning! Tessellation uvs or vcol data got out of sync, " - "had to reset!\n CD_MTFACE: %d != CD_MTEXPOLY: %d || CD_MCOL: %d != CD_MLOOPCOL: %d\n", + "had to reset!\n CD_MTFACE: %d != CD_MLOOPUV: %d || CD_MCOL: %d != CD_MLOOPCOL: %d\n", __func__, tottex_tessface, tottex_original, totcol_tessface, totcol_original); } } @@ -388,6 +387,48 @@ void BKE_mesh_ensure_skin_customdata(Mesh *me) } } +bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me) +{ + BMesh *bm = me->edit_btmesh ? me->edit_btmesh->bm : NULL; + bool changed = false; + if (bm) { + if (!CustomData_has_layer(&bm->pdata, CD_FACEMAP)) { + BM_data_layer_add(bm, &bm->pdata, CD_FACEMAP); + changed = true; + } + } + else { + if (!CustomData_has_layer(&me->pdata, CD_FACEMAP)) { + CustomData_add_layer(&me->pdata, + CD_FACEMAP, + CD_DEFAULT, + NULL, + me->totpoly); + changed = true; + } + } + return changed; +} + +bool BKE_mesh_clear_facemap_customdata(struct Mesh *me) +{ + BMesh *bm = me->edit_btmesh ? me->edit_btmesh->bm : NULL; + bool changed = false; + if (bm) { + if (CustomData_has_layer(&bm->pdata, CD_FACEMAP)) { + BM_data_layer_free(bm, &bm->pdata, CD_FACEMAP); + changed = true; + } + } + else { + if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) { + CustomData_free_layers(&me->pdata, CD_FACEMAP, me->totpoly); + changed = true; + } + } + return changed; +} + /* this ensures grouped customdata (e.g. mtexpoly and mloopuv and mtface, or * mloopcol and mcol) have the same relative active/render/clone/mask indices. * @@ -396,14 +437,11 @@ void BKE_mesh_ensure_skin_customdata(Mesh *me) * versions of the mesh. - campbell*/ static void mesh_update_linked_customdata(Mesh *me, const bool do_ensure_tess_cd) { - if (me->edit_btmesh) - BKE_editmesh_update_linked_customdata(me->edit_btmesh); - if (do_ensure_tess_cd) { mesh_ensure_tessellation_customdata(me); } - CustomData_bmesh_update_active_layers(&me->fdata, &me->pdata, &me->ldata); + CustomData_bmesh_update_active_layers(&me->fdata, &me->ldata); } void BKE_mesh_update_customdata_pointers(Mesh *me, const bool do_ensure_tess_cd) @@ -422,7 +460,6 @@ void BKE_mesh_update_customdata_pointers(Mesh *me, const bool do_ensure_tess_cd) me->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY); me->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP); - me->mtpoly = CustomData_get_layer(&me->pdata, CD_MTEXPOLY); me->mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL); me->mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV); } @@ -442,6 +479,8 @@ void BKE_mesh_free(Mesh *me) { BKE_animdata_free(&me->id, false); + BKE_mesh_batch_cache_free(me); + CustomData_free(&me->vdata, me->totvert); CustomData_free(&me->edata, me->totedge); CustomData_free(&me->fdata, me->totface); @@ -529,6 +568,7 @@ void BKE_mesh_copy_data(Main *bmain, Mesh *me_dst, const Mesh *me_src, const int BKE_mesh_update_customdata_pointers(me_dst, do_tessface); me_dst->edit_btmesh = NULL; + me_dst->batch_cache = NULL; me_dst->mselect = MEM_dupallocN(me_dst->mselect); me_dst->bb = MEM_dupallocN(me_dst->bb); @@ -586,33 +626,44 @@ bool BKE_mesh_uv_cdlayer_rename_index(Mesh *me, const int poly_index, const int ldata = &me->ldata; fdata = &me->fdata; } - cdlp = &pdata->layers[poly_index]; + cdlu = &ldata->layers[loop_index]; - cdlf = fdata && do_tessface ? &fdata->layers[face_index] : NULL; + cdlp = (poly_index != -1) ? &pdata->layers[poly_index] : NULL; + cdlf = (face_index != -1) && fdata && do_tessface ? &fdata->layers[face_index] : NULL; - if (cdlp->name != new_name) { + if (cdlu->name != new_name) { /* Mesh validate passes a name from the CD layer as the new name, * Avoid memcpy from self to self in this case. */ - BLI_strncpy(cdlp->name, new_name, sizeof(cdlp->name)); - CustomData_set_layer_unique_name(pdata, cdlp - pdata->layers); + BLI_strncpy(cdlu->name, new_name, sizeof(cdlu->name)); + CustomData_set_layer_unique_name(ldata, loop_index); + } + + if (cdlp == NULL && cdlf == NULL) { + return false; } /* Loop until we do have exactly the same name for all layers! */ - for (i = 1; !STREQ(cdlp->name, cdlu->name) || (cdlf && !STREQ(cdlp->name, cdlf->name)); i++) { + for (i = 1; + (cdlp && !STREQ(cdlu->name, cdlp->name)) || + (cdlf && !STREQ(cdlu->name, cdlf->name)); + i++) + { switch (i % step) { case 0: - BLI_strncpy(cdlp->name, cdlu->name, sizeof(cdlp->name)); - CustomData_set_layer_unique_name(pdata, cdlp - pdata->layers); + if (cdlp) { + BLI_strncpy(cdlp->name, cdlu->name, sizeof(cdlp->name)); + CustomData_set_layer_unique_name(pdata, poly_index); + } break; case 1: BLI_strncpy(cdlu->name, cdlp->name, sizeof(cdlu->name)); - CustomData_set_layer_unique_name(ldata, cdlu - ldata->layers); + CustomData_set_layer_unique_name(ldata, loop_index); break; case 2: if (cdlf) { - BLI_strncpy(cdlf->name, cdlp->name, sizeof(cdlf->name)); - CustomData_set_layer_unique_name(fdata, cdlf - fdata->layers); + BLI_strncpy(cdlf->name, cdlu->name, sizeof(cdlf->name)); + CustomData_set_layer_unique_name(fdata, face_index); } break; } @@ -623,66 +674,44 @@ bool BKE_mesh_uv_cdlayer_rename_index(Mesh *me, const int poly_index, const int bool BKE_mesh_uv_cdlayer_rename(Mesh *me, const char *old_name, const char *new_name, bool do_tessface) { - CustomData *pdata, *ldata, *fdata; + CustomData *ldata, *fdata; if (me->edit_btmesh) { - pdata = &me->edit_btmesh->bm->pdata; ldata = &me->edit_btmesh->bm->ldata; /* No tessellated data in BMesh! */ fdata = NULL; do_tessface = false; } else { - pdata = &me->pdata; ldata = &me->ldata; fdata = &me->fdata; do_tessface = (do_tessface && fdata->totlayer); } { - const int pidx_start = CustomData_get_layer_index(pdata, CD_MTEXPOLY); const int lidx_start = CustomData_get_layer_index(ldata, CD_MLOOPUV); const int fidx_start = do_tessface ? CustomData_get_layer_index(fdata, CD_MTFACE) : -1; - int pidx = CustomData_get_named_layer(pdata, CD_MTEXPOLY, old_name); int lidx = CustomData_get_named_layer(ldata, CD_MLOOPUV, old_name); int fidx = do_tessface ? CustomData_get_named_layer(fdata, CD_MTFACE, old_name) : -1; /* None of those cases should happen, in theory! * Note this assume we have the same number of mtexpoly, mloopuv and mtface layers! */ - if (pidx == -1) { - if (lidx == -1) { - if (fidx == -1) { - /* No layer found with this name! */ - return false; - } - else { - lidx = fidx; - } - } - pidx = lidx; - } - else { - if (lidx == -1) { - lidx = pidx; + if (lidx == -1) { + if (fidx == -1) { + /* No layer found with this name! */ + return false; } - if (fidx == -1 && do_tessface) { - fidx = pidx; + else { + lidx = fidx; } } -#if 0 - /* For now, we do not consider mismatch in indices (i.e. same name leading to (relative) different indices). */ - else if (pidx != lidx) { - lidx = pidx; - } -#endif /* Go back to absolute indices! */ - pidx += pidx_start; lidx += lidx_start; if (fidx != -1) fidx += fidx_start; - return BKE_mesh_uv_cdlayer_rename_index(me, pidx, lidx, fidx, new_name, do_tessface); + return BKE_mesh_uv_cdlayer_rename_index(me, -1, lidx, fidx, new_name, do_tessface); } } @@ -760,6 +789,18 @@ void BKE_mesh_texspace_get(Mesh *me, float r_loc[3], float r_rot[3], float r_siz if (r_size) copy_v3_v3(r_size, me->size); } +void BKE_mesh_texspace_get_reference(Mesh *me, short **r_texflag, float **r_loc, float **r_rot, float **r_size) +{ + if (me->bb == NULL || (me->bb->flag & BOUNDBOX_DIRTY)) { + BKE_mesh_texspace_calc(me); + } + + if (r_texflag != NULL) *r_texflag = &me->texflag; + if (r_loc != NULL) *r_loc = me->loc; + if (r_rot != NULL) *r_rot = me->rot; + if (r_size != NULL) *r_size = me->size; +} + void BKE_mesh_texspace_copy_from_object(Mesh *me, Object *ob) { float *texloc, *texrot, *texsize; @@ -1382,7 +1423,6 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use if (alluv) { const char *uvname = "Orco"; - me->mtpoly = CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, uvname); me->mloopuv = CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_ASSIGN, alluv, me->totloop, uvname); } @@ -1602,10 +1642,10 @@ void BKE_mesh_to_curve_nurblist(DerivedMesh *dm, ListBase *nurblist, const int e } } -void BKE_mesh_to_curve(Scene *scene, Object *ob) +void BKE_mesh_to_curve(const EvaluationContext *eval_ctx, Scene *scene, Object *ob) { /* make new mesh data from the original copy */ - DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_MESH); + DerivedMesh *dm = mesh_get_derived_final(eval_ctx, scene, ob, CD_MASK_MESH); ListBase nurblist = {NULL, NULL}; bool needsFree = false; @@ -2384,7 +2424,7 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals) /* settings: 1 - preview, 2 - render */ Mesh *BKE_mesh_new_from_object( - Main *bmain, Scene *sce, Object *ob, + const EvaluationContext *eval_ctx, Main *bmain, Scene *sce, Object *ob, int apply_modifiers, int settings, int calc_tessface, int calc_undeformed) { Mesh *tmpmesh; @@ -2443,7 +2483,7 @@ Mesh *BKE_mesh_new_from_object( copycu->editnurb = tmpcu->editnurb; /* get updated display list, and convert to a mesh */ - BKE_displist_make_curveTypes_forRender(sce, tmpobj, &dispbase, &derivedFinal, false, render); + BKE_displist_make_curveTypes_forRender(eval_ctx, sce, tmpobj, &dispbase, &derivedFinal, false, render); copycu->editfont = NULL; copycu->editnurb = NULL; @@ -2492,13 +2532,7 @@ Mesh *BKE_mesh_new_from_object( if (render) { ListBase disp = {NULL, NULL}; - /* TODO(sergey): This is gonna to work for until EvaluationContext - * only contains for_render flag. As soon as CoW is - * implemented, this is to be rethinked. - */ - EvaluationContext eval_ctx; - DEG_evaluation_context_init(&eval_ctx, DAG_EVAL_RENDER); - BKE_displist_make_mball_forRender(&eval_ctx, sce, ob, &disp); + BKE_displist_make_mball_forRender(eval_ctx, sce, ob, &disp); BKE_mesh_from_metaball(&disp, tmpmesh); BKE_displist_free(&disp); } @@ -2537,9 +2571,9 @@ Mesh *BKE_mesh_new_from_object( /* Write the display mesh into the dummy mesh */ if (render) - dm = mesh_create_derived_render(sce, ob, mask); + dm = mesh_create_derived_render(eval_ctx, sce, ob, mask); else - dm = mesh_create_derived_view(sce, ob, mask); + dm = mesh_create_derived_view(eval_ctx, sce, ob, mask); tmpmesh = BKE_mesh_add(bmain, ((ID *)ob->data)->name + 2); DM_to_mesh(dm, tmpmesh, ob, mask, true); @@ -2630,7 +2664,7 @@ Mesh *BKE_mesh_new_from_object( /* **** Depsgraph evaluation **** */ -void BKE_mesh_eval_geometry(EvaluationContext *UNUSED(eval_ctx), +void BKE_mesh_eval_geometry(const EvaluationContext *UNUSED(eval_ctx), Mesh *mesh) { if (G.debug & G_DEBUG_DEPSGRAPH) { @@ -2640,3 +2674,20 @@ void BKE_mesh_eval_geometry(EvaluationContext *UNUSED(eval_ctx), BKE_mesh_texspace_calc(mesh); } } + +/* Draw Engine */ +void (*BKE_mesh_batch_cache_dirty_cb)(Mesh *me, int mode) = NULL; +void (*BKE_mesh_batch_cache_free_cb)(Mesh *me) = NULL; + +void BKE_mesh_batch_cache_dirty(Mesh *me, int mode) +{ + if (me->batch_cache) { + BKE_mesh_batch_cache_dirty_cb(me, mode); + } +} +void BKE_mesh_batch_cache_free(Mesh *me) +{ + if (me->batch_cache) { + BKE_mesh_batch_cache_free_cb(me); + } +} diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index b0c09979de9..531291c30bb 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -1707,152 +1707,6 @@ void BKE_mesh_normals_loop_to_vertex( /* -------------------------------------------------------------------- */ -/** \name Mesh Tangent Calculations - * \{ */ - -/* Tangent space utils. */ - -/* User data. */ -typedef struct { - const MPoly *mpolys; /* faces */ - const MLoop *mloops; /* faces's vertices */ - const MVert *mverts; /* vertices */ - const MLoopUV *luvs; /* texture coordinates */ - float (*lnors)[3]; /* loops' normals */ - float (*tangents)[4]; /* output tangents */ - int num_polys; /* number of polygons */ -} BKEMeshToTangent; - -/* Mikktspace's API */ -static int get_num_faces(const SMikkTSpaceContext *pContext) -{ - BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData; - return p_mesh->num_polys; -} - -static int get_num_verts_of_face(const SMikkTSpaceContext *pContext, const int face_idx) -{ - BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData; - return p_mesh->mpolys[face_idx].totloop; -} - -static void get_position(const SMikkTSpaceContext *pContext, float r_co[3], const int face_idx, const int vert_idx) -{ - BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData; - const int loop_idx = p_mesh->mpolys[face_idx].loopstart + vert_idx; - copy_v3_v3(r_co, p_mesh->mverts[p_mesh->mloops[loop_idx].v].co); -} - -static void get_texture_coordinate(const SMikkTSpaceContext *pContext, float r_uv[2], const int face_idx, - const int vert_idx) -{ - BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData; - copy_v2_v2(r_uv, p_mesh->luvs[p_mesh->mpolys[face_idx].loopstart + vert_idx].uv); -} - -static void get_normal(const SMikkTSpaceContext *pContext, float r_no[3], const int face_idx, const int vert_idx) -{ - BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData; - copy_v3_v3(r_no, p_mesh->lnors[p_mesh->mpolys[face_idx].loopstart + vert_idx]); -} - -static void set_tspace(const SMikkTSpaceContext *pContext, const float fv_tangent[3], const float face_sign, - const int face_idx, const int vert_idx) -{ - BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData; - float *p_res = p_mesh->tangents[p_mesh->mpolys[face_idx].loopstart + vert_idx]; - copy_v3_v3(p_res, fv_tangent); - p_res[3] = face_sign; -} - -/** - * Compute simplified tangent space normals, i.e. tangent vector + sign of bi-tangent one, which combined with - * split normals can be used to recreate the full tangent space. - * Note: * The mesh should be made of only tris and quads! - */ -void BKE_mesh_loop_tangents_ex( - const MVert *mverts, const int UNUSED(numVerts), const MLoop *mloops, - float (*r_looptangent)[4], float (*loopnors)[3], const MLoopUV *loopuvs, - const int UNUSED(numLoops), const MPoly *mpolys, const int numPolys, - ReportList *reports) -{ - BKEMeshToTangent mesh_to_tangent = {NULL}; - SMikkTSpaceContext s_context = {NULL}; - SMikkTSpaceInterface s_interface = {NULL}; - - const MPoly *mp; - int mp_index; - - /* First check we do have a tris/quads only mesh. */ - for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) { - if (mp->totloop > 4) { - BKE_report(reports, RPT_ERROR, "Tangent space can only be computed for tris/quads, aborting"); - return; - } - } - - /* Compute Mikktspace's tangent normals. */ - mesh_to_tangent.mpolys = mpolys; - mesh_to_tangent.mloops = mloops; - mesh_to_tangent.mverts = mverts; - mesh_to_tangent.luvs = loopuvs; - mesh_to_tangent.lnors = loopnors; - mesh_to_tangent.tangents = r_looptangent; - mesh_to_tangent.num_polys = numPolys; - - s_context.m_pUserData = &mesh_to_tangent; - s_context.m_pInterface = &s_interface; - s_interface.m_getNumFaces = get_num_faces; - s_interface.m_getNumVerticesOfFace = get_num_verts_of_face; - s_interface.m_getPosition = get_position; - s_interface.m_getTexCoord = get_texture_coordinate; - s_interface.m_getNormal = get_normal; - s_interface.m_setTSpaceBasic = set_tspace; - - /* 0 if failed */ - if (genTangSpaceDefault(&s_context) == false) { - BKE_report(reports, RPT_ERROR, "Mikktspace failed to generate tangents for this mesh!"); - } -} - -/** - * Wrapper around BKE_mesh_loop_tangents_ex, which takes care of most boiling code. - * \note - * - There must be a valid loop's CD_NORMALS available. - * - The mesh should be made of only tris and quads! - */ -void BKE_mesh_loop_tangents(Mesh *mesh, const char *uvmap, float (*r_looptangents)[4], ReportList *reports) -{ - MLoopUV *loopuvs; - float (*loopnors)[3]; - - /* Check we have valid texture coordinates first! */ - if (uvmap) { - loopuvs = CustomData_get_layer_named(&mesh->ldata, CD_MLOOPUV, uvmap); - } - else { - loopuvs = CustomData_get_layer(&mesh->ldata, CD_MLOOPUV); - } - if (!loopuvs) { - BKE_reportf(reports, RPT_ERROR, "Tangent space computation needs an UVMap, \"%s\" not found, aborting", uvmap); - return; - } - - loopnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL); - if (!loopnors) { - BKE_report(reports, RPT_ERROR, "Tangent space computation needs loop normals, none found, aborting"); - return; - } - - BKE_mesh_loop_tangents_ex(mesh->mvert, mesh->totvert, mesh->mloop, r_looptangents, - loopnors, loopuvs, mesh->totloop, mesh->mpoly, mesh->totpoly, reports); -} - -/** \} */ - - -/* -------------------------------------------------------------------- */ - /** \name Polygon Calculations * \{ */ @@ -2423,12 +2277,12 @@ void BKE_mesh_calc_volume( */ void BKE_mesh_loops_to_mface_corners( CustomData *fdata, CustomData *ldata, - CustomData *pdata, unsigned int lindex[4], int findex, - const int polyindex, + CustomData *UNUSED(pdata), unsigned int lindex[4], int findex, + const int UNUSED(polyindex), const int mf_len, /* 3 or 4 */ /* cache values to avoid lookups every time */ - const int numTex, /* CustomData_number_of_layers(pdata, CD_MTEXPOLY) */ + const int numUV, /* CustomData_number_of_layers(ldata, CD_MLOOPUV) */ const int numCol, /* CustomData_number_of_layers(ldata, CD_MLOOPCOL) */ const bool hasPCol, /* CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL) */ const bool hasOrigSpace, /* CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP) */ @@ -2436,17 +2290,13 @@ void BKE_mesh_loops_to_mface_corners( ) { MTFace *texface; - MTexPoly *texpoly; MCol *mcol; MLoopCol *mloopcol; MLoopUV *mloopuv; int i, j; - for (i = 0; i < numTex; i++) { + for (i = 0; i < numUV; i++) { texface = CustomData_get_n(fdata, CD_MTFACE, findex, i); - texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, polyindex, i); - - ME_MTEXFACE_CPY(texface, texpoly); for (j = 0; j < mf_len; j++) { mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, (int)lindex[j], i); @@ -2498,14 +2348,14 @@ void BKE_mesh_loops_to_mface_corners( * * \note when mface is not NULL, mface[face_index].v4 is used to test quads, else, loopindices[face_index][3] is used. */ -void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData *pdata, MFace *mface, +void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, MFace *mface, int *polyindices, unsigned int (*loopindices)[4], const int num_faces) { /* Note: performances are sub-optimal when we get a NULL mface, we could be ~25% quicker with dedicated code... * Issue is, unless having two different functions with nearly the same code, there's not much ways to solve * this. Better imho to live with it for now. :/ --mont29 */ - const int numTex = CustomData_number_of_layers(pdata, CD_MTEXPOLY); + const int numUV = CustomData_number_of_layers(ldata, CD_MLOOPUV); const int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL); const bool hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL); const bool hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP); @@ -2515,17 +2365,14 @@ void BKE_mesh_loops_to_tessdata(CustomData *fdata, CustomData *ldata, CustomData const int *pidx; unsigned int (*lidx)[4]; - for (i = 0; i < numTex; i++) { + for (i = 0; i < numUV; i++) { MTFace *texface = CustomData_get_layer_n(fdata, CD_MTFACE, i); - MTexPoly *texpoly = CustomData_get_layer_n(pdata, CD_MTEXPOLY, i); MLoopUV *mloopuv = CustomData_get_layer_n(ldata, CD_MLOOPUV, i); for (findex = 0, pidx = polyindices, lidx = loopindices; findex < num_faces; pidx++, lidx++, findex++, texface++) { - ME_MTEXFACE_CPY(texface, &texpoly[*pidx]); - for (j = (mface ? mface[findex].v4 : (*lidx)[3]) ? 4 : 3; j--;) { copy_v2_v2(texface->uv[j], mloopuv[(*lidx)[j]].uv); } @@ -2848,7 +2695,7 @@ int BKE_mesh_recalc_tessellation( /* CD_ORIGINDEX will contain an array of indices from tessfaces to the polygons * they are directly tessellated from */ CustomData_add_layer(fdata, CD_ORIGINDEX, CD_ASSIGN, mface_to_poly_map, totface); - CustomData_from_bmeshpoly(fdata, pdata, ldata, totface); + CustomData_from_bmeshpoly(fdata, ldata, totface); if (do_face_nor_copy) { /* If polys have a normals layer, copying that to faces can help @@ -2869,7 +2716,7 @@ int BKE_mesh_recalc_tessellation( * So we pass NULL as MFace pointer, and BKE_mesh_loops_to_tessdata will use the fourth loop index as quad test. * ... */ - BKE_mesh_loops_to_tessdata(fdata, ldata, pdata, NULL, mface_to_poly_map, lindices, totface); + BKE_mesh_loops_to_tessdata(fdata, ldata, NULL, mface_to_poly_map, lindices, totface); /* NOTE: quad detection issue - fourth vertidx vs fourth loopidx: * ...However, most TFace code uses 'MFace->v4 == 0' test to check whether it is a tri or quad. @@ -3061,7 +2908,7 @@ int BKE_mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata, MPoly *mp, *mpoly; MFace *mface, *mf; - const int numTex = CustomData_number_of_layers(pdata, CD_MTEXPOLY); + const int numUV = CustomData_number_of_layers(ldata, CD_MLOOPUV); const int numCol = CustomData_number_of_layers(ldata, CD_MLOOPCOL); const bool hasPCol = CustomData_has_layer(ldata, CD_PREVIEW_MLOOPCOL); const bool hasOrigSpace = CustomData_has_layer(ldata, CD_ORIGSPACE_MLOOP); @@ -3101,7 +2948,7 @@ int BKE_mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata, CustomData_add_layer(fdata, CD_MFACE, CD_ASSIGN, mface, totface); - CustomData_from_bmeshpoly(fdata, pdata, ldata, totface); + CustomData_from_bmeshpoly(fdata, ldata, totface); mp = mpoly; k = 0; @@ -3123,9 +2970,10 @@ int BKE_mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata, mf->v2 = mloop[mf->v2].v; mf->v3 = mloop[mf->v3].v; - BKE_mesh_loops_to_mface_corners(fdata, ldata, pdata, - lindex, k, i, 3, - numTex, numCol, hasPCol, hasOrigSpace, hasLNor); + BKE_mesh_loops_to_mface_corners( + fdata, ldata, pdata, + lindex, k, i, 3, + numUV, numCol, hasPCol, hasOrigSpace, hasLNor); test_index_face(mf, fdata, k, 3); } else { @@ -3143,9 +2991,10 @@ int BKE_mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata, mf->v3 = mloop[mf->v3].v; mf->v4 = mloop[mf->v4].v; - BKE_mesh_loops_to_mface_corners(fdata, ldata, pdata, - lindex, k, i, 4, - numTex, numCol, hasPCol, hasOrigSpace, hasLNor); + BKE_mesh_loops_to_mface_corners( + fdata, ldata, pdata, + lindex, k, i, 4, + numUV, numCol, hasPCol, hasOrigSpace, hasLNor); test_index_face(mf, fdata, k, 4); } @@ -3160,11 +3009,11 @@ int BKE_mesh_mpoly_to_mface(struct CustomData *fdata, struct CustomData *ldata, #endif /* USE_BMESH_SAVE_AS_COMPAT */ -static void bm_corners_to_loops_ex(ID *id, CustomData *fdata, CustomData *ldata, CustomData *pdata, - MFace *mface, int totloop, int findex, int loopstart, int numTex, int numCol) +static void bm_corners_to_loops_ex( + ID *id, CustomData *fdata, CustomData *ldata, + MFace *mface, int totloop, int findex, int loopstart, int numTex, int numCol) { MTFace *texface; - MTexPoly *texpoly; MCol *mcol; MLoopCol *mloopcol; MLoopUV *mloopuv; @@ -3175,9 +3024,6 @@ static void bm_corners_to_loops_ex(ID *id, CustomData *fdata, CustomData *ldata, for (i = 0; i < numTex; i++) { texface = CustomData_get_n(fdata, CD_MTFACE, findex, i); - texpoly = CustomData_get_n(pdata, CD_MTEXPOLY, findex, i); - - ME_MTEXFACE_CPY(texpoly, texface); mloopuv = CustomData_get_n(ldata, CD_MLOOPUV, loopstart, i); copy_v2_v2(mloopuv->uv, texface->uv[0]); mloopuv++; @@ -3284,7 +3130,7 @@ void BKE_mesh_do_versions_convert_mfaces_to_mpolys(Mesh *mesh) mesh->medge, mesh->mface, &mesh->totloop, &mesh->totpoly, &mesh->mloop, &mesh->mpoly); - CustomData_bmesh_do_versions_update_active_layers(&mesh->fdata, &mesh->pdata, &mesh->ldata); + CustomData_bmesh_do_versions_update_active_layers(&mesh->fdata, &mesh->ldata); BKE_mesh_update_customdata_pointers(mesh, true); } @@ -3327,7 +3173,7 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id, CustomData *fdata, CustomData CustomData_add_layer(ldata, CD_MLOOP, CD_ASSIGN, mloop, totloop); - CustomData_to_bmeshpoly(fdata, pdata, ldata, totloop, totpoly); + CustomData_to_bmeshpoly(fdata, ldata, totloop); if (id) { /* ensure external data is transferred */ @@ -3377,7 +3223,7 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id, CustomData *fdata, CustomData # undef ML - bm_corners_to_loops_ex(id, fdata, ldata, pdata, mface, totloop, i, mp->loopstart, numTex, numCol); + bm_corners_to_loops_ex(id, fdata, ldata, mface, totloop, i, mp->loopstart, numTex, numCol); if (polyindex) { *polyindex = i; diff --git a/source/blender/blenkernel/intern/mesh_tangent.c b/source/blender/blenkernel/intern/mesh_tangent.c new file mode 100644 index 00000000000..77288bd672e --- /dev/null +++ b/source/blender/blenkernel/intern/mesh_tangent.c @@ -0,0 +1,690 @@ +/* + * ***** 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) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/mesh_tangent.c + * \ingroup bke + * + * Functions to evaluate mesh tangents. + */ + +#include <limits.h> + +#include "MEM_guardedalloc.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "BLI_utildefines.h" +#include "BLI_math.h" +#include "BLI_stack.h" +#include "BLI_task.h" + +#include "BKE_customdata.h" +#include "BKE_global.h" +#include "BKE_mesh.h" +#include "BKE_mesh_tangent.h" +#include "BKE_report.h" + +#include "BLI_strict_flags.h" + +#include "atomic_ops.h" +#include "mikktspace.h" + + +/* -------------------------------------------------------------------- */ + +/** \name Mesh Tangent Calculations (Single Layer) + * \{ */ + +/* Tangent space utils. */ + +/* User data. */ +typedef struct { + const MPoly *mpolys; /* faces */ + const MLoop *mloops; /* faces's vertices */ + const MVert *mverts; /* vertices */ + const MLoopUV *luvs; /* texture coordinates */ + float (*lnors)[3]; /* loops' normals */ + float (*tangents)[4]; /* output tangents */ + int num_polys; /* number of polygons */ +} BKEMeshToTangent; + +/* Mikktspace's API */ +static int get_num_faces(const SMikkTSpaceContext *pContext) +{ + BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData; + return p_mesh->num_polys; +} + +static int get_num_verts_of_face(const SMikkTSpaceContext *pContext, const int face_idx) +{ + BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData; + return p_mesh->mpolys[face_idx].totloop; +} + +static void get_position(const SMikkTSpaceContext *pContext, float r_co[3], const int face_idx, const int vert_idx) +{ + BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData; + const int loop_idx = p_mesh->mpolys[face_idx].loopstart + vert_idx; + copy_v3_v3(r_co, p_mesh->mverts[p_mesh->mloops[loop_idx].v].co); +} + +static void get_texture_coordinate(const SMikkTSpaceContext *pContext, float r_uv[2], const int face_idx, + const int vert_idx) +{ + BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData; + copy_v2_v2(r_uv, p_mesh->luvs[p_mesh->mpolys[face_idx].loopstart + vert_idx].uv); +} + +static void get_normal(const SMikkTSpaceContext *pContext, float r_no[3], const int face_idx, const int vert_idx) +{ + BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData; + copy_v3_v3(r_no, p_mesh->lnors[p_mesh->mpolys[face_idx].loopstart + vert_idx]); +} + +static void set_tspace(const SMikkTSpaceContext *pContext, const float fv_tangent[3], const float face_sign, + const int face_idx, const int vert_idx) +{ + BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData; + float *p_res = p_mesh->tangents[p_mesh->mpolys[face_idx].loopstart + vert_idx]; + copy_v3_v3(p_res, fv_tangent); + p_res[3] = face_sign; +} + +/** + * Compute simplified tangent space normals, i.e. tangent vector + sign of bi-tangent one, which combined with + * split normals can be used to recreate the full tangent space. + * Note: * The mesh should be made of only tris and quads! + */ +void BKE_mesh_calc_loop_tangent_single_ex( + const MVert *mverts, const int UNUSED(numVerts), const MLoop *mloops, + float (*r_looptangent)[4], float (*loopnors)[3], const MLoopUV *loopuvs, + const int UNUSED(numLoops), const MPoly *mpolys, const int numPolys, + ReportList *reports) +{ + BKEMeshToTangent mesh_to_tangent = {NULL}; + SMikkTSpaceContext s_context = {NULL}; + SMikkTSpaceInterface s_interface = {NULL}; + + const MPoly *mp; + int mp_index; + + /* First check we do have a tris/quads only mesh. */ + for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) { + if (mp->totloop > 4) { + BKE_report(reports, RPT_ERROR, "Tangent space can only be computed for tris/quads, aborting"); + return; + } + } + + /* Compute Mikktspace's tangent normals. */ + mesh_to_tangent.mpolys = mpolys; + mesh_to_tangent.mloops = mloops; + mesh_to_tangent.mverts = mverts; + mesh_to_tangent.luvs = loopuvs; + mesh_to_tangent.lnors = loopnors; + mesh_to_tangent.tangents = r_looptangent; + mesh_to_tangent.num_polys = numPolys; + + s_context.m_pUserData = &mesh_to_tangent; + s_context.m_pInterface = &s_interface; + s_interface.m_getNumFaces = get_num_faces; + s_interface.m_getNumVerticesOfFace = get_num_verts_of_face; + s_interface.m_getPosition = get_position; + s_interface.m_getTexCoord = get_texture_coordinate; + s_interface.m_getNormal = get_normal; + s_interface.m_setTSpaceBasic = set_tspace; + + /* 0 if failed */ + if (genTangSpaceDefault(&s_context) == false) { + BKE_report(reports, RPT_ERROR, "Mikktspace failed to generate tangents for this mesh!"); + } +} + +/** + * Wrapper around BKE_mesh_calc_loop_tangent_single_ex, which takes care of most boiling code. + * \note + * - There must be a valid loop's CD_NORMALS available. + * - The mesh should be made of only tris and quads! + */ +void BKE_mesh_calc_loop_tangent_single(Mesh *mesh, const char *uvmap, float (*r_looptangents)[4], ReportList *reports) +{ + MLoopUV *loopuvs; + float (*loopnors)[3]; + + /* Check we have valid texture coordinates first! */ + if (uvmap) { + loopuvs = CustomData_get_layer_named(&mesh->ldata, CD_MLOOPUV, uvmap); + } + else { + loopuvs = CustomData_get_layer(&mesh->ldata, CD_MLOOPUV); + } + if (!loopuvs) { + BKE_reportf(reports, RPT_ERROR, "Tangent space computation needs an UVMap, \"%s\" not found, aborting", uvmap); + return; + } + + loopnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL); + if (!loopnors) { + BKE_report(reports, RPT_ERROR, "Tangent space computation needs loop normals, none found, aborting"); + return; + } + + BKE_mesh_calc_loop_tangent_single_ex(mesh->mvert, mesh->totvert, mesh->mloop, r_looptangents, + loopnors, loopuvs, mesh->totloop, mesh->mpoly, mesh->totpoly, reports); +} + +/** \} */ + + +/* -------------------------------------------------------------------- */ + +/** \name Mesh Tangent Calculations (All Layers) + * \{ */ + + +/* Necessary complexity to handle looptri's as quads for correct tangents */ +#define USE_LOOPTRI_DETECT_QUADS + +typedef struct { + const float (*precomputedFaceNormals)[3]; + const float (*precomputedLoopNormals)[3]; + const MLoopTri *looptri; + MLoopUV *mloopuv; /* texture coordinates */ + const MPoly *mpoly; /* indices */ + const MLoop *mloop; /* indices */ + const MVert *mvert; /* vertices & normals */ + const float (*orco)[3]; + float (*tangent)[4]; /* destination */ + int numTessFaces; + +#ifdef USE_LOOPTRI_DETECT_QUADS + /* map from 'fake' face index to looptri, + * quads will point to the first looptri of the quad */ + const int *face_as_quad_map; + int num_face_as_quad_map; +#endif + +} SGLSLMeshToTangent; + +/* interface */ +static int dm_ts_GetNumFaces(const SMikkTSpaceContext *pContext) +{ + SGLSLMeshToTangent *pMesh = pContext->m_pUserData; + +#ifdef USE_LOOPTRI_DETECT_QUADS + return pMesh->num_face_as_quad_map; +#else + return pMesh->numTessFaces; +#endif +} + +static int dm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num) +{ +#ifdef USE_LOOPTRI_DETECT_QUADS + SGLSLMeshToTangent *pMesh = pContext->m_pUserData; + if (pMesh->face_as_quad_map) { + const MLoopTri *lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]]; + const MPoly *mp = &pMesh->mpoly[lt->poly]; + if (mp->totloop == 4) { + return 4; + } + } + return 3; +#else + UNUSED_VARS(pContext, face_num); + return 3; +#endif +} + +static void dm_ts_GetPosition( + const SMikkTSpaceContext *pContext, float r_co[3], + const int face_num, const int vert_index) +{ + //assert(vert_index >= 0 && vert_index < 4); + SGLSLMeshToTangent *pMesh = pContext->m_pUserData; + const MLoopTri *lt; + uint loop_index; + const float *co; + +#ifdef USE_LOOPTRI_DETECT_QUADS + if (pMesh->face_as_quad_map) { + lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]]; + const MPoly *mp = &pMesh->mpoly[lt->poly]; + if (mp->totloop == 4) { + loop_index = (uint)(mp->loopstart + vert_index); + goto finally; + } + /* fall through to regular triangle */ + } + else { + lt = &pMesh->looptri[face_num]; + } +#else + lt = &pMesh->looptri[face_num]; +#endif + loop_index = lt->tri[vert_index]; + +finally: + co = pMesh->mvert[pMesh->mloop[loop_index].v].co; + copy_v3_v3(r_co, co); +} + +static void dm_ts_GetTextureCoordinate( + const SMikkTSpaceContext *pContext, float r_uv[2], + const int face_num, const int vert_index) +{ + //assert(vert_index >= 0 && vert_index < 4); + SGLSLMeshToTangent *pMesh = pContext->m_pUserData; + const MLoopTri *lt; + uint loop_index; + +#ifdef USE_LOOPTRI_DETECT_QUADS + if (pMesh->face_as_quad_map) { + lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]]; + const MPoly *mp = &pMesh->mpoly[lt->poly]; + if (mp->totloop == 4) { + loop_index = (uint)(mp->loopstart + vert_index); + goto finally; + } + /* fall through to regular triangle */ + } + else { + lt = &pMesh->looptri[face_num]; + } +#else + lt = &pMesh->looptri[face_num]; +#endif + loop_index = lt->tri[vert_index]; + +finally: + if (pMesh->mloopuv != NULL) { + const float *uv = pMesh->mloopuv[loop_index].uv; + copy_v2_v2(r_uv, uv); + } + else { + const float *orco = pMesh->orco[pMesh->mloop[loop_index].v]; + map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]); + } +} + +static void dm_ts_GetNormal( + const SMikkTSpaceContext *pContext, float r_no[3], + const int face_num, const int vert_index) +{ + //assert(vert_index >= 0 && vert_index < 4); + SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; + const MLoopTri *lt; + uint loop_index; + +#ifdef USE_LOOPTRI_DETECT_QUADS + if (pMesh->face_as_quad_map) { + lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]]; + const MPoly *mp = &pMesh->mpoly[lt->poly]; + if (mp->totloop == 4) { + loop_index = (uint)(mp->loopstart + vert_index); + goto finally; + } + /* fall through to regular triangle */ + } + else { + lt = &pMesh->looptri[face_num]; + } +#else + lt = &pMesh->looptri[face_num]; +#endif + loop_index = lt->tri[vert_index]; + +finally: + if (pMesh->precomputedLoopNormals) { + copy_v3_v3(r_no, pMesh->precomputedLoopNormals[loop_index]); + } + else if ((pMesh->mpoly[lt->poly].flag & ME_SMOOTH) == 0) { /* flat */ + if (pMesh->precomputedFaceNormals) { + copy_v3_v3(r_no, pMesh->precomputedFaceNormals[lt->poly]); + } + else { +#ifdef USE_LOOPTRI_DETECT_QUADS + const MPoly *mp = &pMesh->mpoly[lt->poly]; + if (mp->totloop == 4) { + normal_quad_v3( + r_no, + pMesh->mvert[pMesh->mloop[mp->loopstart + 0].v].co, + pMesh->mvert[pMesh->mloop[mp->loopstart + 1].v].co, + pMesh->mvert[pMesh->mloop[mp->loopstart + 2].v].co, + pMesh->mvert[pMesh->mloop[mp->loopstart + 3].v].co); + } + else +#endif + { + normal_tri_v3( + r_no, + pMesh->mvert[pMesh->mloop[lt->tri[0]].v].co, + pMesh->mvert[pMesh->mloop[lt->tri[1]].v].co, + pMesh->mvert[pMesh->mloop[lt->tri[2]].v].co); + } + } + } + else { + const short *no = pMesh->mvert[pMesh->mloop[loop_index].v].no; + normal_short_to_float_v3(r_no, no); + } +} + +static void dm_ts_SetTSpace( + const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign, + const int face_num, const int vert_index) +{ + //assert(vert_index >= 0 && vert_index < 4); + SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData; + const MLoopTri *lt; + uint loop_index; + +#ifdef USE_LOOPTRI_DETECT_QUADS + if (pMesh->face_as_quad_map) { + lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]]; + const MPoly *mp = &pMesh->mpoly[lt->poly]; + if (mp->totloop == 4) { + loop_index = (uint)(mp->loopstart + vert_index); + goto finally; + } + /* fall through to regular triangle */ + } + else { + lt = &pMesh->looptri[face_num]; + } +#else + lt = &pMesh->looptri[face_num]; +#endif + loop_index = lt->tri[vert_index]; + + float *pRes; + +finally: + pRes = pMesh->tangent[loop_index]; + copy_v3_v3(pRes, fvTangent); + pRes[3] = fSign; +} + +static void DM_calc_loop_tangents_thread(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid)) +{ + struct SGLSLMeshToTangent *mesh2tangent = taskdata; + /* new computation method */ + { + SMikkTSpaceContext sContext = {NULL}; + SMikkTSpaceInterface sInterface = {NULL}; + + sContext.m_pUserData = mesh2tangent; + sContext.m_pInterface = &sInterface; + sInterface.m_getNumFaces = dm_ts_GetNumFaces; + sInterface.m_getNumVerticesOfFace = dm_ts_GetNumVertsOfFace; + sInterface.m_getPosition = dm_ts_GetPosition; + sInterface.m_getTexCoord = dm_ts_GetTextureCoordinate; + sInterface.m_getNormal = dm_ts_GetNormal; + sInterface.m_setTSpaceBasic = dm_ts_SetTSpace; + + /* 0 if failed */ + genTangSpaceDefault(&sContext); + } +} + +void BKE_mesh_add_loop_tangent_named_layer_for_uv( + CustomData *uv_data, CustomData *tan_data, int numLoopData, + const char *layer_name) +{ + if (CustomData_get_named_layer_index(tan_data, CD_TANGENT, layer_name) == -1 && + CustomData_get_named_layer_index(uv_data, CD_MLOOPUV, layer_name) != -1) + { + CustomData_add_layer_named( + tan_data, CD_TANGENT, CD_CALLOC, NULL, + numLoopData, layer_name); + } +} + +/** + * Here we get some useful information such as active uv layer name and search if it is already in tangent_names. + * Also, we calculate tangent_mask that works as a descriptor of tangents state. + * If tangent_mask has changed, then recalculate tangents. + */ +void BKE_mesh_calc_loop_tangent_step_0( + const CustomData *loopData, bool calc_active_tangent, + const char (*tangent_names)[MAX_NAME], int tangent_names_count, + bool *rcalc_act, bool *rcalc_ren, int *ract_uv_n, int *rren_uv_n, + char *ract_uv_name, char *rren_uv_name, short *rtangent_mask) { + /* Active uv in viewport */ + int layer_index = CustomData_get_layer_index(loopData, CD_MLOOPUV); + *ract_uv_n = CustomData_get_active_layer(loopData, CD_MLOOPUV); + ract_uv_name[0] = 0; + if (*ract_uv_n != -1) { + strcpy(ract_uv_name, loopData->layers[*ract_uv_n + layer_index].name); + } + + /* Active tangent in render */ + *rren_uv_n = CustomData_get_render_layer(loopData, CD_MLOOPUV); + rren_uv_name[0] = 0; + if (*rren_uv_n != -1) { + strcpy(rren_uv_name, loopData->layers[*rren_uv_n + layer_index].name); + } + + /* If active tangent not in tangent_names we take it into account */ + *rcalc_act = false; + *rcalc_ren = false; + for (int i = 0; i < tangent_names_count; i++) { + if (tangent_names[i][0] == 0) { + calc_active_tangent = true; + } + } + if (calc_active_tangent) { + *rcalc_act = true; + *rcalc_ren = true; + for (int i = 0; i < tangent_names_count; i++) { + if (STREQ(ract_uv_name, tangent_names[i])) + *rcalc_act = false; + if (STREQ(rren_uv_name, tangent_names[i])) + *rcalc_ren = false; + } + } + *rtangent_mask = 0; + + const int uv_layer_num = CustomData_number_of_layers(loopData, CD_MLOOPUV); + for (int n = 0; n < uv_layer_num; n++) { + const char *name = CustomData_get_layer_name(loopData, CD_MLOOPUV, n); + bool add = false; + for (int i = 0; i < tangent_names_count; i++) { + if (tangent_names[i][0] && STREQ(tangent_names[i], name)) { + add = true; + break; + } + } + if (!add && ((*rcalc_act && ract_uv_name[0] && STREQ(ract_uv_name, name)) || + (*rcalc_ren && rren_uv_name[0] && STREQ(rren_uv_name, name)))) + { + add = true; + } + if (add) + *rtangent_mask |= (short)(1 << n); + } + + if (uv_layer_num == 0) + *rtangent_mask |= DM_TANGENT_MASK_ORCO; +} + +/** + * See: #BKE_editmesh_loop_tangent_calc (matching logic). + */ +void BKE_mesh_calc_loop_tangent_ex( + const MVert *mvert, + const MPoly *mpoly, const uint mpoly_len, + const MLoop *mloop, + const MLoopTri *looptri, + const uint looptri_len, + + CustomData *loopdata, + bool calc_active_tangent, + const char (*tangent_names)[MAX_NAME], int tangent_names_len, + const float (*poly_normals)[3], + const float (*loop_normals)[3], + const float (*vert_orco)[3], + /* result */ + CustomData *loopdata_out, + const uint loopdata_out_len, + short *tangent_mask_curr_p) +{ + int act_uv_n = -1; + int ren_uv_n = -1; + bool calc_act = false; + bool calc_ren = false; + char act_uv_name[MAX_NAME]; + char ren_uv_name[MAX_NAME]; + short tangent_mask = 0; + short tangent_mask_curr = *tangent_mask_curr_p; + + BKE_mesh_calc_loop_tangent_step_0( + loopdata, calc_active_tangent, tangent_names, tangent_names_len, + &calc_act, &calc_ren, &act_uv_n, &ren_uv_n, act_uv_name, ren_uv_name, &tangent_mask); + if ((tangent_mask_curr | tangent_mask) != tangent_mask_curr) { + /* Check we have all the needed layers */ + /* Allocate needed tangent layers */ + for (int i = 0; i < tangent_names_len; i++) + if (tangent_names[i][0]) + BKE_mesh_add_loop_tangent_named_layer_for_uv(loopdata, loopdata_out, (int)loopdata_out_len, tangent_names[i]); + if ((tangent_mask & DM_TANGENT_MASK_ORCO) && CustomData_get_named_layer_index(loopdata, CD_TANGENT, "") == -1) + CustomData_add_layer_named(loopdata_out, CD_TANGENT, CD_CALLOC, NULL, (int)loopdata_out_len, ""); + if (calc_act && act_uv_name[0]) + BKE_mesh_add_loop_tangent_named_layer_for_uv(loopdata, loopdata_out, (int)loopdata_out_len, act_uv_name); + if (calc_ren && ren_uv_name[0]) + BKE_mesh_add_loop_tangent_named_layer_for_uv(loopdata, loopdata_out, (int)loopdata_out_len, ren_uv_name); + +#ifdef USE_LOOPTRI_DETECT_QUADS + int num_face_as_quad_map; + int *face_as_quad_map = NULL; + + /* map faces to quads */ + if (looptri_len != mpoly_len) { + /* over alloc, since we dont know how many ngon or quads we have */ + + /* map fake face index to looptri */ + face_as_quad_map = MEM_mallocN(sizeof(int) * looptri_len, __func__); + int k, j; + for (k = 0, j = 0; j < (int)looptri_len; k++, j++) { + face_as_quad_map[k] = j; + /* step over all quads */ + if (mpoly[looptri[j].poly].totloop == 4) { + j++; /* skips the nest looptri */ + } + } + num_face_as_quad_map = k; + } + else { + num_face_as_quad_map = (int)looptri_len; + } +#endif + + /* Calculation */ + if (looptri_len != 0) { + TaskScheduler *scheduler = BLI_task_scheduler_get(); + TaskPool *task_pool; + task_pool = BLI_task_pool_create(scheduler, NULL); + + tangent_mask_curr = 0; + /* Calculate tangent layers */ + SGLSLMeshToTangent data_array[MAX_MTFACE]; + const int tangent_layer_num = CustomData_number_of_layers(loopdata_out, CD_TANGENT); + for (int n = 0; n < tangent_layer_num; n++) { + int index = CustomData_get_layer_index_n(loopdata_out, CD_TANGENT, n); + BLI_assert(n < MAX_MTFACE); + SGLSLMeshToTangent *mesh2tangent = &data_array[n]; + mesh2tangent->numTessFaces = (int)looptri_len; +#ifdef USE_LOOPTRI_DETECT_QUADS + mesh2tangent->face_as_quad_map = face_as_quad_map; + mesh2tangent->num_face_as_quad_map = num_face_as_quad_map; +#endif + mesh2tangent->mvert = mvert; + mesh2tangent->mpoly = mpoly; + mesh2tangent->mloop = mloop; + mesh2tangent->looptri = looptri; + /* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled), + * have to check this is valid... + */ + mesh2tangent->precomputedLoopNormals = loop_normals; + mesh2tangent->precomputedFaceNormals = poly_normals; + + mesh2tangent->orco = NULL; + mesh2tangent->mloopuv = CustomData_get_layer_named(loopdata, CD_MLOOPUV, loopdata_out->layers[index].name); + + /* Fill the resulting tangent_mask */ + if (!mesh2tangent->mloopuv) { + mesh2tangent->orco = vert_orco; + if (!mesh2tangent->orco) + continue; + + tangent_mask_curr |= DM_TANGENT_MASK_ORCO; + } + else { + int uv_ind = CustomData_get_named_layer_index(loopdata, CD_MLOOPUV, loopdata_out->layers[index].name); + int uv_start = CustomData_get_layer_index(loopdata, CD_MLOOPUV); + BLI_assert(uv_ind != -1 && uv_start != -1); + BLI_assert(uv_ind - uv_start < MAX_MTFACE); + tangent_mask_curr |= (short)(1 << (uv_ind - uv_start)); + } + + mesh2tangent->tangent = loopdata_out->layers[index].data; + BLI_task_pool_push(task_pool, DM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW); + } + + BLI_assert(tangent_mask_curr == tangent_mask); + BLI_task_pool_work_and_wait(task_pool); + BLI_task_pool_free(task_pool); + } + else { + tangent_mask_curr = tangent_mask; + } +#ifdef USE_LOOPTRI_DETECT_QUADS + if (face_as_quad_map) { + MEM_freeN(face_as_quad_map); + } +#undef USE_LOOPTRI_DETECT_QUADS + +#endif + + *tangent_mask_curr_p = tangent_mask_curr; + + /* Update active layer index */ + int act_uv_index = CustomData_get_layer_index_n(loopdata, CD_MLOOPUV, act_uv_n); + if (act_uv_index != -1) { + int tan_index = CustomData_get_named_layer_index(loopdata, CD_TANGENT, loopdata->layers[act_uv_index].name); + CustomData_set_layer_active_index(loopdata, CD_TANGENT, tan_index); + }/* else tangent has been built from orco */ + + /* Update render layer index */ + int ren_uv_index = CustomData_get_layer_index_n(loopdata, CD_MLOOPUV, ren_uv_n); + if (ren_uv_index != -1) { + int tan_index = CustomData_get_named_layer_index(loopdata, CD_TANGENT, loopdata->layers[ren_uv_index].name); + CustomData_set_layer_render_index(loopdata, CD_TANGENT, tan_index); + }/* else tangent has been built from orco */ + } +} + +/** \} */ diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c index 4aeddbb4c45..54de843bc64 100644 --- a/source/blender/blenkernel/intern/mesh_validate.c +++ b/source/blender/blenkernel/intern/mesh_validate.c @@ -43,10 +43,11 @@ #include "BLI_math_vector.h" #include "BKE_deform.h" -#include "BKE_depsgraph.h" #include "BKE_DerivedMesh.h" #include "BKE_mesh.h" +#include "DEG_depsgraph.h" + #include "MEM_guardedalloc.h" /* loop v/e are unsigned, so using max uint_32 value as invalid marker... */ @@ -936,7 +937,7 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata, { bool is_valid = true; bool is_change_v, is_change_e, is_change_l, is_change_p; - int tot_texpoly, tot_uvloop, tot_vcolloop; + int tot_uvloop, tot_vcolloop; CustomDataMask mask = check_meshmask ? CD_MASK_MESH : 0; is_valid &= mesh_validate_customdata(vdata, mask, do_verbose, do_fixes, &is_change_v); @@ -944,17 +945,8 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata, is_valid &= mesh_validate_customdata(ldata, mask, do_verbose, do_fixes, &is_change_l); is_valid &= mesh_validate_customdata(pdata, mask, do_verbose, do_fixes, &is_change_p); - tot_texpoly = CustomData_number_of_layers(pdata, CD_MTEXPOLY); tot_uvloop = CustomData_number_of_layers(ldata, CD_MLOOPUV); tot_vcolloop = CustomData_number_of_layers(ldata, CD_MLOOPCOL); - if (tot_texpoly != tot_uvloop) { - PRINT_ERR("\tCustomDataLayer mismatch, tot_texpoly(%d), tot_uvloop(%d)\n", - tot_texpoly, tot_uvloop); - } - if (tot_texpoly > MAX_MTFACE) { - PRINT_ERR("\tMore UV layers than %d allowed, %d last ones won't be available for render, shaders, etc.\n", - MAX_MTFACE, tot_texpoly - MAX_MTFACE); - } if (tot_uvloop > MAX_MTFACE) { PRINT_ERR("\tMore UV layers than %d allowed, %d last ones won't be available for render, shaders, etc.\n", MAX_MTFACE, tot_uvloop - MAX_MTFACE); @@ -965,18 +957,10 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata, } /* check indices of clone/stencil */ - if (do_fixes && CustomData_get_clone_layer(pdata, CD_MTEXPOLY) >= tot_texpoly) { - CustomData_set_layer_clone(pdata, CD_MTEXPOLY, 0); - is_change_p = true; - } if (do_fixes && CustomData_get_clone_layer(ldata, CD_MLOOPUV) >= tot_uvloop) { CustomData_set_layer_clone(ldata, CD_MLOOPUV, 0); is_change_l = true; } - if (do_fixes && CustomData_get_stencil_layer(pdata, CD_MTEXPOLY) >= tot_texpoly) { - CustomData_set_layer_stencil(pdata, CD_MTEXPOLY, 0); - is_change_p = true; - } if (do_fixes && CustomData_get_stencil_layer(ldata, CD_MLOOPUV) >= tot_uvloop) { CustomData_set_layer_stencil(ldata, CD_MLOOPUV, 0); is_change_l = true; @@ -1019,7 +1003,7 @@ int BKE_mesh_validate(Mesh *me, const int do_verbose, const int cddata_check_mas &changed); if (changed) { - DAG_id_tag_update(&me->id, OB_RECALC_DATA); + DEG_id_tag_update(&me->id, OB_RECALC_DATA); return true; } else { @@ -1028,64 +1012,6 @@ int BKE_mesh_validate(Mesh *me, const int do_verbose, const int cddata_check_mas } /** - * Duplicate of BM_mesh_cd_validate() for Mesh data. - */ -void BKE_mesh_cd_validate(Mesh *me) -{ - int totlayer_mtex = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY); - int totlayer_uv = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV); - int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL); - int mtex_index = CustomData_get_layer_index(&me->pdata, CD_MTEXPOLY); - int uv_index = CustomData_get_layer_index(&me->ldata, CD_MLOOPUV); - int i; - - /* XXX For now, do not delete those, just warn they are not really usable. */ - if (UNLIKELY(totlayer_mtex > MAX_MTFACE)) { - printf("WARNING! More UV layers than %d allowed, %d last ones won't be available for render, shaders, etc.\n", - MAX_MTFACE, totlayer_mtex - MAX_MTFACE); - } - if (UNLIKELY(totlayer_uv > MAX_MTFACE)) { - printf("WARNING! More UV layers than %d allowed, %d last ones won't be available for render, shaders, etc.\n", - MAX_MTFACE, totlayer_uv - MAX_MTFACE); - } - if (UNLIKELY(totlayer_mcol > MAX_MCOL)) { - printf("WARNING! More VCol layers than %d allowed, %d last ones won't be available for render, shaders, etc.\n", - MAX_MCOL, totlayer_mcol - MAX_MCOL); - } - - if (LIKELY(totlayer_mtex == totlayer_uv)) { - /* pass */ - } - else if (totlayer_mtex < totlayer_uv) { - do { - const char *from_name = me->ldata.layers[uv_index + totlayer_mtex].name; - CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, from_name); - CustomData_set_layer_unique_name(&me->pdata, totlayer_mtex); - } while (totlayer_uv != ++totlayer_mtex); - mtex_index = CustomData_get_layer_index(&me->pdata, CD_MTEXPOLY); - } - else if (totlayer_uv < totlayer_mtex) { - do { - const char *from_name = me->pdata.layers[mtex_index + totlayer_uv].name; - CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, from_name); - CustomData_set_layer_unique_name(&me->ldata, totlayer_uv); - } while (totlayer_mtex != ++totlayer_uv); - uv_index = CustomData_get_layer_index(&me->ldata, CD_MLOOPUV); - } - - BLI_assert(totlayer_mtex == totlayer_uv); - - /* Check uv/tex names match as well!!! */ - for (i = 0; i < totlayer_mtex; i++, mtex_index++, uv_index++) { - const char *name_src = me->pdata.layers[mtex_index].name; - const char *name_dst = me->ldata.layers[uv_index].name; - if (!STREQ(name_src, name_dst)) { - BKE_mesh_uv_cdlayer_rename_index(me, mtex_index, uv_index, -1, name_src, false); - } - } -} - -/** * Check all material indices of polygons are valid, invalid ones are set to 0. * \returns is_valid. */ @@ -1105,7 +1031,7 @@ int BKE_mesh_validate_material_indices(Mesh *me) } if (!is_valid) { - DAG_id_tag_update(&me->id, OB_RECALC_DATA); + DEG_id_tag_update(&me->id, OB_RECALC_DATA); return true; } else { diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c index d7a24f90dbe..1604a017054 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -69,6 +69,8 @@ #include "BKE_main.h" /* end */ +#include "DEG_depsgraph.h" + #include "MOD_modifiertypes.h" static ModifierTypeInfo *modifier_types[NUM_MODIFIER_TYPES] = {NULL}; @@ -660,15 +662,15 @@ bool modifier_isCorrectableDeformed(ModifierData *md) return (mti->deformMatricesEM != NULL); } -bool modifiers_isCorrectableDeformed(struct Scene *scene, Object *ob) +bool modifiers_isCorrectableDeformed(const EvaluationContext *eval_ctx, struct Scene *scene, Object *ob) { VirtualModifierData virtualModifierData; ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); int required_mode = eModifierMode_Realtime; - if (ob->mode == OB_MODE_EDIT) + if (eval_ctx->object_mode == OB_MODE_EDIT) { required_mode |= eModifierMode_Editmode; - + } for (; md; md = md->next) { if (!modifier_isEnabled(scene, md, required_mode)) { /* pass */ @@ -762,8 +764,8 @@ void modifier_path_init(char *path, int path_maxlen, const char *name) /* wrapper around ModifierTypeInfo.applyModifier that ensures valid normals */ struct DerivedMesh *modwrap_applyModifier( - ModifierData *md, Object *ob, - struct DerivedMesh *dm, + ModifierData *md, const struct EvaluationContext *eval_ctx, + Object *ob, struct DerivedMesh *dm, ModifierApplyFlag flag) { const ModifierTypeInfo *mti = modifierType_getInfo(md->type); @@ -772,12 +774,12 @@ struct DerivedMesh *modwrap_applyModifier( if (mti->dependsOnNormals && mti->dependsOnNormals(md)) { DM_ensure_normals(dm); } - return mti->applyModifier(md, ob, dm, flag); + return mti->applyModifier(md, eval_ctx, ob, dm, flag); } struct DerivedMesh *modwrap_applyModifierEM( - ModifierData *md, Object *ob, - struct BMEditMesh *em, + ModifierData *md, const struct EvaluationContext *eval_ctx, + Object *ob, struct BMEditMesh *em, DerivedMesh *dm, ModifierApplyFlag flag) { @@ -787,12 +789,12 @@ struct DerivedMesh *modwrap_applyModifierEM( if (mti->dependsOnNormals && mti->dependsOnNormals(md)) { DM_ensure_normals(dm); } - return mti->applyModifierEM(md, ob, em, dm, flag); + return mti->applyModifierEM(md, eval_ctx, ob, em, dm, flag); } void modwrap_deformVerts( - ModifierData *md, Object *ob, - DerivedMesh *dm, + ModifierData *md, const struct EvaluationContext *eval_ctx, + Object *ob, DerivedMesh *dm, float (*vertexCos)[3], int numVerts, ModifierApplyFlag flag) { @@ -802,11 +804,11 @@ void modwrap_deformVerts( if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) { DM_ensure_normals(dm); } - mti->deformVerts(md, ob, dm, vertexCos, numVerts, flag); + mti->deformVerts(md, eval_ctx, ob, dm, vertexCos, numVerts, flag); } void modwrap_deformVertsEM( - ModifierData *md, Object *ob, + ModifierData *md, const struct EvaluationContext *eval_ctx, Object *ob, struct BMEditMesh *em, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { @@ -816,6 +818,6 @@ void modwrap_deformVertsEM( if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) { DM_ensure_normals(dm); } - mti->deformVertsEM(md, ob, em, dm, vertexCos, numVerts); + mti->deformVertsEM(md, eval_ctx, ob, em, dm, vertexCos, numVerts); } /* end modifier callback wrappers */ diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 9c8fc9bfd0c..e7c36685c42 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -60,6 +60,8 @@ #include "BKE_object.h" +#include "DEG_depsgraph.h" + #include "CCGSubSurf.h" #include <math.h> @@ -277,14 +279,14 @@ static MDisps *multires_mdisps_initialize_hidden(Mesh *me, int level) return mdisps; } -DerivedMesh *get_multires_dm(Scene *scene, MultiresModifierData *mmd, Object *ob) +DerivedMesh *get_multires_dm(const struct EvaluationContext *eval_ctx, Scene *scene, MultiresModifierData *mmd, Object *ob) { ModifierData *md = (ModifierData *)mmd; const ModifierTypeInfo *mti = modifierType_getInfo(md->type); - DerivedMesh *tdm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); + DerivedMesh *tdm = mesh_get_derived_deform(eval_ctx, scene, ob, CD_MASK_BAREMESH); DerivedMesh *dm; - dm = mti->applyModifier(md, ob, tdm, MOD_APPLY_USECACHE | MOD_APPLY_IGNORE_SIMPLIFY); + dm = mti->applyModifier(md, eval_ctx, ob, tdm, MOD_APPLY_USECACHE | MOD_APPLY_IGNORE_SIMPLIFY); if (dm == tdm) { dm = CDDM_copy(tdm); } @@ -336,12 +338,13 @@ MultiresModifierData *get_multires_modifier(Scene *scene, Object *ob, bool use_f return mmd; } -static int multires_get_level(Object *ob, MultiresModifierData *mmd, - bool render, bool ignore_simplify) +static int multires_get_level( + MultiresModifierData *mmd, + bool render, bool ignore_simplify, eObjectMode object_mode) { if (render) return (mmd->modifier.scene) ? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->renderlvl, true) : mmd->renderlvl; - else if (ob->mode == OB_MODE_SCULPT) + else if (object_mode == OB_MODE_SCULPT) return mmd->sculptlvl; else if (ignore_simplify) return mmd->lvl; @@ -349,12 +352,13 @@ static int multires_get_level(Object *ob, MultiresModifierData *mmd, return (mmd->modifier.scene) ? get_render_subsurf_level(&mmd->modifier.scene->r, mmd->lvl, false) : mmd->lvl; } -void multires_set_tot_level(Object *ob, MultiresModifierData *mmd, int lvl) +void multires_set_tot_level(MultiresModifierData *mmd, int lvl, eObjectMode object_mode) { mmd->totlvl = lvl; - if (ob->mode != OB_MODE_SCULPT) + if (object_mode != OB_MODE_SCULPT) { mmd->lvl = CLAMPIS(MAX2(mmd->lvl, lvl), 0, mmd->totlvl); + } mmd->sculptlvl = CLAMPIS(MAX2(mmd->sculptlvl, lvl), 0, mmd->totlvl); mmd->renderlvl = CLAMPIS(MAX2(mmd->renderlvl, lvl), 0, mmd->totlvl); @@ -392,16 +396,16 @@ void multires_force_external_reload(Object *ob) multires_force_update(ob); } -void multires_force_render_update(Object *ob) +void multires_force_render_update(Object *ob, eObjectMode object_mode) { - if (ob && (ob->mode & OB_MODE_SCULPT) && modifiers_findByType(ob, eModifierType_Multires)) + if (ob && (object_mode & OB_MODE_SCULPT) && modifiers_findByType(ob, eModifierType_Multires)) multires_force_update(ob); } -int multiresModifier_reshapeFromDM(Scene *scene, MultiresModifierData *mmd, +int multiresModifier_reshapeFromDM(const struct EvaluationContext *eval_ctx, Scene *scene, MultiresModifierData *mmd, Object *ob, DerivedMesh *srcdm) { - DerivedMesh *mrdm = get_multires_dm(scene, mmd, ob); + DerivedMesh *mrdm = get_multires_dm(eval_ctx, scene, mmd, ob); if (mrdm && srcdm && mrdm->getNumVerts(mrdm) == srcdm->getNumVerts(srcdm)) { multires_mvert_to_ss(mrdm, srcdm->getVertArray(srcdm)); @@ -420,13 +424,13 @@ int multiresModifier_reshapeFromDM(Scene *scene, MultiresModifierData *mmd, } /* Returns 1 on success, 0 if the src's totvert doesn't match */ -int multiresModifier_reshape(Scene *scene, MultiresModifierData *mmd, Object *dst, Object *src) +int multiresModifier_reshape(const struct EvaluationContext *eval_ctx, Scene *scene, MultiresModifierData *mmd, Object *dst, Object *src) { - DerivedMesh *srcdm = mesh_get_derived_final(scene, src, CD_MASK_BAREMESH); - return multiresModifier_reshapeFromDM(scene, mmd, dst, srcdm); + DerivedMesh *srcdm = mesh_get_derived_final(eval_ctx, scene, src, CD_MASK_BAREMESH); + return multiresModifier_reshapeFromDM(eval_ctx, scene, mmd, dst, srcdm); } -int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mmd, +int multiresModifier_reshapeFromDeformMod(const struct EvaluationContext *eval_ctx, Scene *scene, MultiresModifierData *mmd, Object *ob, ModifierData *md) { const ModifierTypeInfo *mti = modifierType_getInfo(md->type); @@ -434,16 +438,16 @@ int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mm int numVerts, result; float (*deformedVerts)[3]; - if (multires_get_level(ob, mmd, false, true) == 0) + if (multires_get_level(mmd, false, true, eval_ctx->object_mode) == 0) return 0; /* Create DerivedMesh for deformation modifier */ - dm = get_multires_dm(scene, mmd, ob); + dm = get_multires_dm(eval_ctx, scene, mmd, ob); numVerts = dm->getNumVerts(dm); deformedVerts = MEM_malloc_arrayN(numVerts, sizeof(float[3]), "multiresReshape_deformVerts"); dm->getVertCos(dm, deformedVerts); - mti->deformVerts(md, ob, dm, deformedVerts, numVerts, 0); + mti->deformVerts(md, eval_ctx, ob, dm, deformedVerts, numVerts, 0); ndm = CDDM_copy(dm); CDDM_apply_vert_coords(ndm, deformedVerts); @@ -452,7 +456,7 @@ int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mm dm->release(dm); /* Reshaping */ - result = multiresModifier_reshapeFromDM(scene, mmd, ob, ndm); + result = multiresModifier_reshapeFromDM(eval_ctx, scene, mmd, ob, ndm); /* Cleanup */ ndm->release(ndm); @@ -614,7 +618,7 @@ static void multires_grid_paint_mask_downsample(GridPaintMask *gpm, int level) } } -static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl) +static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl, eObjectMode object_mode) { Mesh *me = (Mesh *)ob->data; int levels = mmd->totlvl - lvl; @@ -676,14 +680,14 @@ static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl) } } - multires_set_tot_level(ob, mmd, lvl); + multires_set_tot_level(mmd, lvl, object_mode); } /* (direction = 1) for delete higher, (direction = 0) for lower (not implemented yet) */ -void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int direction) +void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int direction, eObjectMode object_mode) { Mesh *me = BKE_mesh_from_object(ob); - int lvl = multires_get_level(ob, mmd, false, true); + int lvl = multires_get_level(mmd, false, true, object_mode); int levels = mmd->totlvl - lvl; MDisps *mdisps; @@ -694,13 +698,14 @@ void multiresModifier_del_levels(MultiresModifierData *mmd, Object *ob, int dire multires_force_update(ob); if (mdisps && levels > 0 && direction == 1) { - multires_del_higher(mmd, ob, lvl); + multires_del_higher(mmd, ob, lvl, object_mode); } - multires_set_tot_level(ob, mmd, lvl); + multires_set_tot_level(mmd, lvl, object_mode); } -static DerivedMesh *multires_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int totlvl, int simple, bool alloc_paint_mask) +static DerivedMesh *multires_dm_create_local( + Object *ob, DerivedMesh *dm, int lvl, int totlvl, int simple, bool alloc_paint_mask, eObjectMode object_mode) { MultiresModifierData mmd = {{NULL}}; MultiresFlags flags = MULTIRES_USE_LOCAL_MMD; @@ -714,10 +719,12 @@ static DerivedMesh *multires_dm_create_local(Object *ob, DerivedMesh *dm, int lv if (alloc_paint_mask) flags |= MULTIRES_ALLOC_PAINT_MASK; - return multires_make_derived_from_derived(dm, &mmd, ob, flags); + return multires_make_derived_from_derived(dm, &mmd, ob, flags, object_mode); } -static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl, int simple, int optimal, int plain_uv, int alloc_paint_mask) +static DerivedMesh *subsurf_dm_create_local( + DerivedMesh *dm, int lvl, int simple, + int optimal, int plain_uv, int alloc_paint_mask, eObjectMode object_mode) { SubsurfModifierData smd = {{NULL}}; SubsurfFlags flags = 0; @@ -730,7 +737,7 @@ static DerivedMesh *subsurf_dm_create_local(Object *ob, DerivedMesh *dm, int lvl if (optimal) smd.flags |= eSubsurfModifierFlag_ControlEdges; - if (ob->mode & OB_MODE_EDIT) + if (object_mode & OB_MODE_EDIT) flags |= SUBSURF_IN_EDIT_MODE; if (alloc_paint_mask) @@ -750,7 +757,7 @@ static float v3_dist_from_plane(float v[3], float center[3], float no[3]) return dot_v3v3(s, no); } -void multiresModifier_base_apply(MultiresModifierData *mmd, Object *ob) +void multiresModifier_base_apply(MultiresModifierData *mmd, Object *ob, eObjectMode object_mode) { DerivedMesh *cddm, *dispdm, *origdm; Mesh *me; @@ -772,7 +779,7 @@ void multiresModifier_base_apply(MultiresModifierData *mmd, Object *ob) /* generate highest level with displacements */ cddm = CDDM_from_mesh(me); DM_set_only_copy(cddm, CD_MASK_BAREMESH); - dispdm = multires_dm_create_local(ob, cddm, totlvl, totlvl, 0, 0); + dispdm = multires_dm_create_local(ob, cddm, totlvl, totlvl, 0, 0, object_mode); cddm->release(cddm); /* copy the new locations of the base verts into the mesh */ @@ -868,7 +875,9 @@ void multiresModifier_base_apply(MultiresModifierData *mmd, Object *ob) /* subdivide the mesh to highest level without displacements */ cddm = CDDM_from_mesh(me); DM_set_only_copy(cddm, CD_MASK_BAREMESH); - origdm = subsurf_dm_create_local(ob, cddm, totlvl, 0, 0, mmd->flags & eMultiresModifierFlag_PlainUv, 0); + origdm = subsurf_dm_create_local( + cddm, totlvl, 0, + 0, mmd->flags & eMultiresModifierFlag_PlainUv, 0, object_mode); cddm->release(cddm); /* calc disps */ @@ -878,7 +887,8 @@ void multiresModifier_base_apply(MultiresModifierData *mmd, Object *ob) dispdm->release(dispdm); } -static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl, int updateblock, int simple) +static void multires_subdivide( + MultiresModifierData *mmd, Object *ob, int totlvl, int updateblock, int simple, eObjectMode object_mode) { Mesh *me = ob->data; MDisps *mdisps; @@ -907,11 +917,13 @@ static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl /* create subsurf DM from original mesh at high level */ cddm = CDDM_from_mesh(me); DM_set_only_copy(cddm, CD_MASK_BAREMESH); - highdm = subsurf_dm_create_local(ob, cddm, totlvl, simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv, has_mask); + highdm = subsurf_dm_create_local( + cddm, totlvl, simple, + 0, mmd->flags & eMultiresModifierFlag_PlainUv, has_mask, object_mode); ss = ((CCGDerivedMesh *)highdm)->ss; /* create multires DM from original mesh at low level */ - lowdm = multires_dm_create_local(ob, cddm, lvl, lvl, simple, has_mask); + lowdm = multires_dm_create_local(ob, cddm, lvl, lvl, simple, has_mask, object_mode); BLI_assert(lowdm != cddm); cddm->release(cddm); @@ -958,12 +970,13 @@ static void multires_subdivide(MultiresModifierData *mmd, Object *ob, int totlvl multires_reallocate_mdisps(me->totloop, mdisps, totlvl); } - multires_set_tot_level(ob, mmd, totlvl); + multires_set_tot_level(mmd, totlvl, object_mode); } -void multiresModifier_subdivide(MultiresModifierData *mmd, Object *ob, int updateblock, int simple) +void multiresModifier_subdivide( + MultiresModifierData *mmd, Object *ob, int updateblock, int simple, eObjectMode object_mode) { - multires_subdivide(mmd, ob, mmd->totlvl + 1, updateblock, simple); + multires_subdivide(mmd, ob, mmd->totlvl + 1, updateblock, simple, object_mode); } static void grid_tangent(const CCGKey *key, int x, int y, int axis, CCGElem *grid, float t[3]) @@ -1196,7 +1209,7 @@ static void multiresModifier_disp_run(DerivedMesh *dm, Mesh *me, DerivedMesh *dm } } -void multires_modifier_update_mdisps(struct DerivedMesh *dm) +void multires_modifier_update_mdisps(struct DerivedMesh *dm, eObjectMode object_mode) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; Object *ob; @@ -1228,11 +1241,13 @@ void multires_modifier_update_mdisps(struct DerivedMesh *dm) else cddm = CDDM_from_mesh(me); DM_set_only_copy(cddm, CD_MASK_BAREMESH); - highdm = subsurf_dm_create_local(ob, cddm, totlvl, mmd->simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv, has_mask); + highdm = subsurf_dm_create_local( + cddm, totlvl, mmd->simple, + 0, mmd->flags & eMultiresModifierFlag_PlainUv, has_mask, object_mode); ss = ((CCGDerivedMesh *)highdm)->ss; /* create multires DM from original mesh and displacements */ - lowdm = multires_dm_create_local(ob, cddm, lvl, totlvl, mmd->simple, has_mask); + lowdm = multires_dm_create_local(ob, cddm, lvl, totlvl, mmd->simple, has_mask, object_mode); cddm->release(cddm); /* gather grid data */ @@ -1290,7 +1305,9 @@ void multires_modifier_update_mdisps(struct DerivedMesh *dm) else cddm = CDDM_from_mesh(me); DM_set_only_copy(cddm, CD_MASK_BAREMESH); - subdm = subsurf_dm_create_local(ob, cddm, mmd->totlvl, mmd->simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv, has_mask); + subdm = subsurf_dm_create_local( + cddm, mmd->totlvl, mmd->simple, + 0, mmd->flags & eMultiresModifierFlag_PlainUv, has_mask, object_mode); cddm->release(cddm); multiresModifier_disp_run(dm, me, NULL, CALC_DISPLACEMENTS, subdm->getGridData(subdm), mmd->totlvl); @@ -1332,7 +1349,7 @@ void multires_modifier_update_hidden(DerivedMesh *dm) } } -void multires_set_space(DerivedMesh *dm, Object *ob, int from, int to) +void multires_set_space(DerivedMesh *dm, Object *ob, int from, int to, eObjectMode object_mode) { DerivedMesh *ccgdm = NULL, *subsurf = NULL; CCGElem **gridData, **subGridData = NULL; @@ -1353,10 +1370,11 @@ void multires_set_space(DerivedMesh *dm, Object *ob, int from, int to) } totlvl = mmd->totlvl; - ccgdm = multires_dm_create_local(ob, dm, totlvl, totlvl, mmd->simple, false); + ccgdm = multires_dm_create_local(ob, dm, totlvl, totlvl, mmd->simple, false, object_mode); - subsurf = subsurf_dm_create_local(ob, dm, totlvl, - mmd->simple, mmd->flags & eMultiresModifierFlag_ControlEdges, mmd->flags & eMultiresModifierFlag_PlainUv, 0); + subsurf = subsurf_dm_create_local( + dm, totlvl, mmd->simple, + mmd->flags & eMultiresModifierFlag_ControlEdges, mmd->flags & eMultiresModifierFlag_PlainUv, 0, object_mode); numGrids = subsurf->getNumGrids(subsurf); gridSize = subsurf->getGridSize(subsurf); @@ -1471,10 +1489,12 @@ void multires_stitch_grids(Object *ob) } } -DerivedMesh *multires_make_derived_from_derived(DerivedMesh *dm, - MultiresModifierData *mmd, - Object *ob, - MultiresFlags flags) +DerivedMesh *multires_make_derived_from_derived( + DerivedMesh *dm, + MultiresModifierData *mmd, + Object *ob, + MultiresFlags flags, + eObjectMode object_mode) { Mesh *me = ob->data; DerivedMesh *result; @@ -1483,16 +1503,18 @@ DerivedMesh *multires_make_derived_from_derived(DerivedMesh *dm, CCGKey key; const bool render = (flags & MULTIRES_USE_RENDER_PARAMS) != 0; const bool ignore_simplify = (flags & MULTIRES_IGNORE_SIMPLIFY) != 0; - int lvl = multires_get_level(ob, mmd, render, ignore_simplify); + int lvl = multires_get_level(mmd, render, ignore_simplify, object_mode); int i, gridSize, numGrids; if (lvl == 0) return dm; - result = subsurf_dm_create_local(ob, dm, lvl, - mmd->simple, mmd->flags & eMultiresModifierFlag_ControlEdges, - mmd->flags & eMultiresModifierFlag_PlainUv, - flags & MULTIRES_ALLOC_PAINT_MASK); + result = subsurf_dm_create_local( + dm, lvl, mmd->simple, + mmd->flags & eMultiresModifierFlag_ControlEdges, + mmd->flags & eMultiresModifierFlag_PlainUv, + flags & MULTIRES_ALLOC_PAINT_MASK, + object_mode); if (!(flags & MULTIRES_USE_LOCAL_MMD)) { ccgdm = (CCGDerivedMesh *)result; @@ -2120,6 +2142,7 @@ void multires_load_old(Object *ob, Mesh *me) DerivedMesh *dm, *orig; CustomDataLayer *l; int i; + const eObjectMode object_mode = OB_MODE_OBJECT; /* Load original level into the mesh */ lvl = me->mr->levels.first; @@ -2168,7 +2191,7 @@ void multires_load_old(Object *ob, Mesh *me) BLI_insertlinkbefore(&ob->modifiers, md, mmd); for (i = 0; i < me->mr->level_count - 1; ++i) - multiresModifier_subdivide(mmd, ob, 1, 0); + multiresModifier_subdivide(mmd, ob, 1, 0, object_mode); mmd->lvl = mmd->totlvl; orig = CDDM_from_mesh(me); @@ -2177,7 +2200,7 @@ void multires_load_old(Object *ob, Mesh *me) * reference subsurfed dm with this option, before calling multiresModifier_disp_run(), * which implicitly expects both subsurfs from its first dm and oldGridData parameters to * be of the same "format"! */ - dm = multires_make_derived_from_derived(orig, mmd, ob, 0); + dm = multires_make_derived_from_derived(orig, mmd, ob, 0, object_mode); multires_load_old_dm(dm, me, mmd->totlvl + 1); @@ -2192,21 +2215,22 @@ void multires_load_old(Object *ob, Mesh *me) /* If 'ob_src' and 'ob_dst' both have multires modifiers, synchronize them * such that 'ob_dst' has the same total number of levels as 'ob_src'. */ -void multiresModifier_sync_levels_ex(Object *ob_dst, MultiresModifierData *mmd_src, MultiresModifierData *mmd_dst) +void multiresModifier_sync_levels_ex( + Object *ob_dst, MultiresModifierData *mmd_src, MultiresModifierData *mmd_dst, eObjectMode object_mode) { if (mmd_src->totlvl == mmd_dst->totlvl) { return; } if (mmd_src->totlvl > mmd_dst->totlvl) { - multires_subdivide(mmd_dst, ob_dst, mmd_src->totlvl, false, mmd_dst->simple); + multires_subdivide(mmd_dst, ob_dst, mmd_src->totlvl, false, mmd_dst->simple, object_mode); } else { - multires_del_higher(mmd_dst, ob_dst, mmd_src->totlvl); + multires_del_higher(mmd_dst, ob_dst, mmd_src->totlvl, object_mode); } } -static void multires_sync_levels(Scene *scene, Object *ob_src, Object *ob_dst) +static void multires_sync_levels(Scene *scene, Object *ob_src, Object *ob_dst, eObjectMode object_mode) { MultiresModifierData *mmd_src = get_multires_modifier(scene, ob_src, true); MultiresModifierData *mmd_dst = get_multires_modifier(scene, ob_dst, true); @@ -2221,7 +2245,7 @@ static void multires_sync_levels(Scene *scene, Object *ob_src, Object *ob_dst) } if (mmd_src && mmd_dst) { - multiresModifier_sync_levels_ex(ob_dst, mmd_src, mmd_dst); + multiresModifier_sync_levels_ex(ob_dst, mmd_src, mmd_dst, object_mode); } } @@ -2275,7 +2299,7 @@ static void multires_apply_smat_cb( } } -static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3]) +static void multires_apply_smat(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float smat[3][3]) { DerivedMesh *dm = NULL, *cddm = NULL, *subdm = NULL; CCGElem **gridData, **subGridData; @@ -2300,10 +2324,10 @@ static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3]) high_mmd.lvl = high_mmd.totlvl; /* unscaled multires with applied displacement */ - subdm = get_multires_dm(scene, &high_mmd, ob); + subdm = get_multires_dm(eval_ctx, scene, &high_mmd, ob); /* prepare scaled CDDM to create ccgDN */ - cddm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH); + cddm = mesh_get_derived_deform(eval_ctx, scene, ob, CD_MASK_BAREMESH); totvert = cddm->getNumVerts(cddm); vertCos = MEM_malloc_arrayN(totvert, sizeof(*vertCos), "multiresScale vertCos"); @@ -2314,7 +2338,9 @@ static void multires_apply_smat(Scene *scene, Object *ob, float smat[3][3]) MEM_freeN(vertCos); /* scaled ccgDM for tangent space of object with applied scale */ - dm = subsurf_dm_create_local(ob, cddm, high_mmd.totlvl, high_mmd.simple, 0, mmd->flags & eMultiresModifierFlag_PlainUv, 0); + dm = subsurf_dm_create_local( + cddm, high_mmd.totlvl, high_mmd.simple, + 0, mmd->flags & eMultiresModifierFlag_PlainUv, 0, eval_ctx->object_mode); cddm->release(cddm); gridSize = dm->getGridSize(dm); @@ -2364,20 +2390,20 @@ int multires_mdisp_corners(MDisps *s) return 0; } -void multiresModifier_scale_disp(Scene *scene, Object *ob) +void multiresModifier_scale_disp(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob) { float smat[3][3]; /* object's scale matrix */ BKE_object_scale_to_mat3(ob, smat); - multires_apply_smat(scene, ob, smat); + multires_apply_smat(eval_ctx, scene, ob, smat); } -void multiresModifier_prepare_join(Scene *scene, Object *ob, Object *to_ob) +void multiresModifier_prepare_join(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, Object *to_ob) { float smat[3][3], tmat[3][3], mat[3][3]; - multires_sync_levels(scene, to_ob, ob); + multires_sync_levels(scene, to_ob, ob, eval_ctx->object_mode); /* construct scale matrix for displacement */ BKE_object_scale_to_mat3(to_ob, tmat); @@ -2385,7 +2411,7 @@ void multiresModifier_prepare_join(Scene *scene, Object *ob, Object *to_ob) BKE_object_scale_to_mat3(ob, smat); mul_m3_m3m3(mat, smat, tmat); - multires_apply_smat(scene, ob, mat); + multires_apply_smat(eval_ctx, scene, ob, mat); } /* update multires data after topology changing */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 2363eb525d5..cbb7a766dfe 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -59,7 +59,7 @@ #include "BKE_library.h" #ifdef WITH_AUDASPACE -# include AUD_SPECIAL_H +# include <AUD_Special.h> #endif #include "RNA_access.h" diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 74766bec9a8..7ed76d18958 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -2043,7 +2043,7 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree) for (node = ntree->nodes.first; node; node = node->next) { /* store new_node pointer to original */ - node->new_node->new_node = node; + node->new_node->original = node; } if (ntree->typeinfo->localize) @@ -3621,6 +3621,7 @@ static void registerShaderNodes(void) register_node_type_sh_add_shader(); register_node_type_sh_uvmap(); register_node_type_sh_uvalongstroke(); + register_node_type_sh_eevee_specular(); register_node_type_sh_output_lamp(); register_node_type_sh_output_material(); @@ -3813,3 +3814,64 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter, return true; } + +/* -------------------------------------------------------------------- */ +/* NodeTree kernel functions */ + +void BKE_nodetree_remove_layer_n(bNodeTree *ntree, Scene *scene, const int layer_index) +{ + BLI_assert(layer_index != -1); + for (bNode *node = ntree->nodes.first; node; node = node->next) { + if (node->type == CMP_NODE_R_LAYERS && (Scene *)node->id == scene) { + if (node->custom1 == layer_index) { + node->custom1 = 0; + } + else if (node->custom1 > layer_index) { + node->custom1--; + } + } + } +} + +static void node_copy_default_values_list(ListBase *sockets_dst, + const ListBase *sockets_src) +{ + bNodeSocket *sock_dst = sockets_dst->first; + const bNodeSocket *sock_src = sockets_src->first; + while (sock_dst != NULL) { + node_socket_copy_default_value(sock_dst, sock_src); + sock_dst = sock_dst->next; + sock_src = sock_src->next; + } +} + +static void node_copy_default_values(bNode *node_dst, const bNode *node_src) +{ + node_copy_default_values_list(&node_dst->inputs, &node_src->inputs); + node_copy_default_values_list(&node_dst->outputs, &node_src->outputs); +} + +void BKE_nodetree_copy_default_values(bNodeTree *ntree_dst, + const bNodeTree *ntree_src) +{ + if (ntree_dst == ntree_src) { + return; + } + bNode *node_dst = ntree_dst->nodes.first; + const bNode *node_src = ntree_src->nodes.first; + while (node_dst != NULL) { + node_copy_default_values(node_dst, node_src); + node_dst = node_dst->next; + node_src = node_src->next; + } +} + +void BKE_nodetree_shading_params_eval(const struct EvaluationContext *UNUSED(eval_ctx), + bNodeTree *ntree_dst, + const bNodeTree *ntree_src) +{ + if (G.debug & G_DEBUG_DEPSGRAPH) { + printf("%s on %s (%p)\n", __func__, ntree_src->id.name, ntree_dst); + } + BKE_nodetree_copy_default_values(ntree_dst, ntree_src); +} diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index c6b4e3fb0c7..a0d2e7d76c8 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -58,6 +58,7 @@ #include "DNA_view3d_types.h" #include "DNA_world_types.h" #include "DNA_object_types.h" +#include "DNA_lightprobe_types.h" #include "DNA_property_types.h" #include "DNA_rigidbody_types.h" @@ -78,7 +79,6 @@ #include "BKE_action.h" #include "BKE_bullet.h" #include "BKE_deform.h" -#include "BKE_depsgraph.h" #include "BKE_DerivedMesh.h" #include "BKE_animsys.h" #include "BKE_anim.h" @@ -91,6 +91,7 @@ #include "BKE_icons.h" #include "BKE_key.h" #include "BKE_lamp.h" +#include "BKE_layer.h" #include "BKE_lattice.h" #include "BKE_library.h" #include "BKE_library_query.h" @@ -103,9 +104,11 @@ #include "BKE_multires.h" #include "BKE_node.h" #include "BKE_object.h" +#include "BKE_object_facemap.h" #include "BKE_paint.h" #include "BKE_particle.h" #include "BKE_pointcache.h" +#include "BKE_lightprobe.h" #include "BKE_property.h" #include "BKE_rigidbody.h" #include "BKE_sca.h" @@ -118,6 +121,10 @@ #include "BKE_camera.h" #include "BKE_image.h" +#include "DEG_depsgraph.h" + +#include "DRW_engine.h" + #ifdef WITH_MOD_FLUID #include "LBM_fluidsim.h" #endif @@ -129,7 +136,7 @@ #include "CCGSubSurf.h" #include "atomic_ops.h" -#include "GPU_material.h" +#include "GPU_lamp.h" /* Vertex parent modifies original BMesh which is not safe for threading. * Ideally such a modification should be handled as a separate DAG update @@ -152,16 +159,6 @@ void BKE_object_workob_clear(Object *workob) workob->rotmode = ROT_MODE_EUL; } -void BKE_object_update_base_layer(struct Scene *scene, Object *ob) -{ - Base *base = scene->base.first; - - while (base) { - if (base->object == ob) base->lay = ob->lay; - base = base->next; - } -} - void BKE_object_free_particlesystems(Object *ob) { ParticleSystem *psys; @@ -265,7 +262,9 @@ bool BKE_object_support_modifier_type_check(Object *ob, int modifier_type) return true; } -void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_src) +void BKE_object_link_modifiers( + struct Object *ob_dst, const struct Object *ob_src, + eObjectMode object_mode) { ModifierData *md; BKE_object_free_modifiers(ob_dst); @@ -304,7 +303,8 @@ void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_sr if (md->type == eModifierType_Multires) { /* Has to be done after mod creation, but *before* we actually copy its settings! */ - multiresModifier_sync_levels_ex(ob_dst, (MultiresModifierData *)md, (MultiresModifierData *)nmd); + multiresModifier_sync_levels_ex( + ob_dst, (MultiresModifierData *)md, (MultiresModifierData *)nmd, object_mode); } modifier_copyData(md, nmd); @@ -356,7 +356,18 @@ void BKE_object_free_derived_caches(Object *ob) ob->derivedDeform->release(ob->derivedDeform); ob->derivedDeform = NULL; } - + + if (ob->mesh_evaluated != NULL) { + /* Restore initial pointer. */ + ob->data = ob->mesh_evaluated->id.orig_id; + /* Evaluated mesh points to edit mesh, but does not own it. */ + ob->mesh_evaluated->edit_btmesh = NULL; + BKE_mesh_free(ob->mesh_evaluated); + BKE_libblock_free_data(&ob->mesh_evaluated->id, false); + MEM_freeN(ob->mesh_evaluated); + ob->mesh_evaluated = NULL; + } + BKE_object_free_curve_cache(ob); } @@ -401,7 +412,7 @@ void BKE_object_free_caches(Object *object) * guaranteed to be in a known state. */ if (update_flag != 0) { - DAG_id_tag_update(&object->id, update_flag); + DEG_id_tag_update(&object->id, update_flag); } } @@ -418,6 +429,7 @@ void BKE_object_free(Object *ob) MEM_SAFE_FREE(ob->bb); BLI_freelistN(&ob->defbase); + BLI_freelistN(&ob->fmaps); if (ob->pose) { BKE_pose_free_ex(ob->pose, false); ob->pose = NULL; @@ -448,6 +460,13 @@ void BKE_object_free(Object *ob) } GPU_lamp_free(ob); + for (ObjectEngineData *oed = ob->drawdata.first; oed; oed = oed->next) { + if (oed->free != NULL) { + oed->free(oed); + } + } + BLI_freelistN(&ob->drawdata); + BKE_sculptsession_free(ob); BLI_freelistN(&ob->pc_ids); @@ -464,10 +483,13 @@ void BKE_object_free(Object *ob) } BKE_previewimg_free(&ob->preview); + + /* don't free, let the base free it */ + ob->base_collection_properties = NULL; } /* actual check for internal data, not context or flags */ -bool BKE_object_is_in_editmode(Object *ob) +bool BKE_object_is_in_editmode(const Object *ob) { if (ob->data == NULL) return false; @@ -516,11 +538,11 @@ bool BKE_object_is_in_editmode_vgroup(Object *ob) BKE_object_is_in_editmode(ob)); } -bool BKE_object_is_in_wpaint_select_vert(Object *ob) +bool BKE_object_is_in_wpaint_select_vert(const Object *ob, eObjectMode object_mode) { if (ob->type == OB_MESH) { - Mesh *me = ob->data; - return ((ob->mode & OB_MODE_WEIGHT_PAINT) && + const Mesh *me = ob->data; + return ((object_mode & OB_MODE_WEIGHT_PAINT) && (me->edit_btmesh == NULL) && (ME_EDIT_PAINT_SEL_MODE(me) == SCE_SELECT_VERTEX)); } @@ -528,6 +550,36 @@ bool BKE_object_is_in_wpaint_select_vert(Object *ob) return false; } +/** + * Return if the object is visible, as evaluated by depsgraph + */ +bool BKE_object_is_visible(Object *ob, const eObjectVisibilityCheck mode) +{ + if ((ob->base_flag & BASE_VISIBLED) == 0) { + return false; + } + + if (mode == OB_VISIBILITY_CHECK_UNKNOWN_RENDER_MODE) { + return true; + } + + if (((ob->transflag & OB_DUPLI) == 0) && + (ob->particlesystem.first == NULL)) + { + return true; + } + + switch (mode) { + case OB_VISIBILITY_CHECK_FOR_VIEWPORT: + return ((ob->duplicator_visibility_flag & OB_DUPLI_FLAG_VIEWPORT) != 0); + case OB_VISIBILITY_CHECK_FOR_RENDER: + return ((ob->duplicator_visibility_flag & OB_DUPLI_FLAG_RENDER) != 0); + default: + BLI_assert(!"Object visible test mode not supported."); + return false; + } +} + bool BKE_object_exists_check(Object *obtest) { Object *ob; @@ -581,6 +633,7 @@ void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name) case OB_LATTICE: return BKE_lattice_add(bmain, name); case OB_ARMATURE: return BKE_armature_add(bmain, name); case OB_SPEAKER: return BKE_speaker_add(bmain, name); + case OB_LIGHTPROBE:return BKE_lightprobe_add(bmain, name); case OB_EMPTY: return NULL; default: printf("%s: Internal error, bad type: %d\n", __func__, type); @@ -652,6 +705,7 @@ void BKE_object_init(Object *ob) ob->col_group = 0x01; ob->col_mask = 0xffff; ob->preview = NULL; + ob->duplicator_visibility_flag = OB_DUPLI_FLAG_VIEWPORT | OB_DUPLI_FLAG_RENDER; /* NT fluid sim defaults */ ob->fluidsimSettings = NULL; @@ -672,6 +726,9 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name) ob = BKE_libblock_alloc(bmain, ID_OB, name, 0); + /* We increase object user count when linking to SceneCollections. */ + id_us_min(&ob->id); + /* default object vars */ ob->type = type; @@ -680,29 +737,65 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name) return ob; } -/* general add: to scene, with layer from area and default name */ + +static Object *object_add_common(Main *bmain, ViewLayer *view_layer, int type, const char *name) +{ + Object *ob; + + ob = BKE_object_add_only_object(bmain, type, name); + ob->data = BKE_object_obdata_add_from_type(bmain, type, name); + BKE_view_layer_base_deselect_all(view_layer); + + DEG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + return ob; +} + +/** + * General add: to scene, with layer from area and default name + * + * Object is added to the active SceneCollection. + * If there is no linked collection to the active ViewLayer we create a new one. + */ /* creates minimum required data, but without vertices etc. */ Object *BKE_object_add( - Main *bmain, Scene *scene, + Main *bmain, Scene *scene, ViewLayer *view_layer, int type, const char *name) { Object *ob; Base *base; + LayerCollection *layer_collection; - ob = BKE_object_add_only_object(bmain, type, name); + ob = object_add_common(bmain, view_layer, type, name); - ob->data = BKE_object_obdata_add_from_type(bmain, type, name); + layer_collection = BKE_layer_collection_get_active_ensure(scene, view_layer); + BKE_collection_object_add(&scene->id, layer_collection->scene_collection, ob); - ob->lay = scene->lay; - - base = BKE_scene_base_add(scene, ob); - BKE_scene_base_deselect_all(scene); - BKE_scene_base_select(scene, base); - DAG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + base = BKE_view_layer_base_find(view_layer, ob); + BKE_view_layer_base_select(view_layer, base); return ob; } +/** + * Add a new object, using another one as a reference + * + * /param ob_src object to use to determine the collections of the new object. + */ +Object *BKE_object_add_from( + Main *bmain, Scene *scene, ViewLayer *view_layer, + int type, const char *name, Object *ob_src) +{ + Object *ob; + Base *base; + + ob = object_add_common(bmain, view_layer, type, name); + BKE_collection_object_add_from(scene, ob_src, ob); + + base = BKE_view_layer_base_find(view_layer, ob); + BKE_view_layer_base_select(view_layer, base); + + return ob; +} #ifdef WITH_GAMEENGINE @@ -794,10 +887,10 @@ static LodLevel *lod_level_select(Object *ob, const float camera_position[3]) return current; } -bool BKE_object_lod_is_usable(Object *ob, Scene *scene) +bool BKE_object_lod_is_usable(Object *ob, ViewLayer *view_layer, const eObjectMode object_mode) { - bool active = (scene) ? ob == OBACT : false; - return (ob->mode == OB_MODE_OBJECT || !active); + bool active = (view_layer) ? ob == OBACT(view_layer) : false; + return (object_mode == OB_MODE_OBJECT || !active); } void BKE_object_lod_update(Object *ob, const float camera_position[3]) @@ -810,11 +903,11 @@ void BKE_object_lod_update(Object *ob, const float camera_position[3]) } } -static Object *lod_ob_get(Object *ob, Scene *scene, int flag) +static Object *lod_ob_get(Object *ob, ViewLayer *view_layer, int flag, const eObjectMode object_mode) { LodLevel *current = ob->currentlod; - if (!current || !BKE_object_lod_is_usable(ob, scene)) + if (!current || !BKE_object_lod_is_usable(ob, view_layer, object_mode)) return ob; while (current->prev && (!(current->flags & flag) || !current->source || current->source->type != OB_MESH)) { @@ -824,14 +917,14 @@ static Object *lod_ob_get(Object *ob, Scene *scene, int flag) return current->source; } -struct Object *BKE_object_lod_meshob_get(Object *ob, Scene *scene) +struct Object *BKE_object_lod_meshob_get(Object *ob, ViewLayer *view_layer, const eObjectMode object_mode) { - return lod_ob_get(ob, scene, OB_LOD_USE_MESH); + return lod_ob_get(ob, view_layer, OB_LOD_USE_MESH, object_mode); } -struct Object *BKE_object_lod_matob_get(Object *ob, Scene *scene) +struct Object *BKE_object_lod_matob_get(Object *ob, ViewLayer *view_layer, const eObjectMode object_mode) { - return lod_ob_get(ob, scene, OB_LOD_USE_MAT); + return lod_ob_get(ob, view_layer, OB_LOD_USE_MAT, object_mode); } #endif /* WITH_GAMEENGINE */ @@ -943,6 +1036,7 @@ ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys, const int f psysn->effectors = NULL; psysn->tree = NULL; psysn->bvhtree = NULL; + psysn->batch_cache = NULL; BLI_listbase_clear(&psysn->pathcachebufs); BLI_listbase_clear(&psysn->childcachebufs); @@ -1059,12 +1153,13 @@ static void copy_object_lod(Object *obn, const Object *ob, const int UNUSED(flag obn->currentlod = (LodLevel *)obn->lodlevels.first; } -bool BKE_object_pose_context_check(Object *ob) +bool BKE_object_pose_context_check_ex(Object *ob, bool selected) { if ((ob) && (ob->type == OB_ARMATURE) && (ob->pose) && - (ob->mode & OB_MODE_POSE)) + /* Currently using selection when the object isn't active. */ + ((selected == false) || (ob->flag & SELECT))) { return true; } @@ -1073,22 +1168,41 @@ bool BKE_object_pose_context_check(Object *ob) } } +bool BKE_object_pose_context_check(Object *ob) +{ + return BKE_object_pose_context_check_ex(ob, false); +} + Object *BKE_object_pose_armature_get(Object *ob) { if (ob == NULL) return NULL; - if (BKE_object_pose_context_check(ob)) + if (BKE_object_pose_context_check_ex(ob, false)) return ob; ob = modifiers_isDeformedByArmature(ob); - if (BKE_object_pose_context_check(ob)) + /* Only use selected check when non-active. */ + if (BKE_object_pose_context_check_ex(ob, true)) return ob; return NULL; } +Object *BKE_object_pose_armature_get_visible(Object *ob, ViewLayer *view_layer) +{ + Object *ob_armature = BKE_object_pose_armature_get(ob); + if (ob_armature) { + Base *base = BKE_view_layer_base_find(view_layer, ob_armature); + if (base) { + if (BASE_VISIBLE(base)) { + return ob_armature; + } + } + } + return NULL; +} void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src) { copy_v3_v3(ob_tar->loc, ob_src->loc); @@ -1147,9 +1261,9 @@ void BKE_object_copy_data(Main *UNUSED(bmain), Object *ob_dst, const Object *ob_ BKE_pose_rebuild(ob_dst, ob_dst->data); } defgroup_copy_list(&ob_dst->defbase, &ob_src->defbase); + BKE_object_facemap_copy_list(&ob_dst->fmaps, &ob_src->fmaps); BKE_constraints_copy_ex(&ob_dst->constraints, &ob_src->constraints, flag_subdata, true); - ob_dst->mode = OB_MODE_OBJECT; ob_dst->sculpt = NULL; if (ob_src->pd) { @@ -1169,6 +1283,7 @@ void BKE_object_copy_data(Main *UNUSED(bmain), Object *ob_dst, const Object *ob_ ob_dst->derivedFinal = NULL; BLI_listbase_clear(&ob_dst->gpulamp); + BLI_listbase_clear(&ob_dst->drawdata); BLI_listbase_clear(&ob_dst->pc_ids); ob_dst->mpath = NULL; @@ -1329,8 +1444,8 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *gob) ob->proxy_group = gob; id_lib_extern(&target->id); - DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); - DAG_id_tag_update(&target->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); + DEG_id_tag_update(&target->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); /* copy transform * - gob means this proxy comes from a group, just apply the matrix @@ -1673,13 +1788,16 @@ static bool ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4]) Curve *cu = par->data; float vec[4], dir[3], quat[4], radius, ctime; + /* TODO: Make sure this doesn't crash. */ +#if 0 /* only happens on reload file, but violates depsgraph still... fix! */ if (par->curve_cache == NULL) { if (scene == NULL) { return false; } - BKE_displist_make_curveTypes(scene, par, 0); + BKE_displist_make_curveTypes(eval_ctx, scene, par, 0); } +#endif if (par->curve_cache->path == NULL) { return false; @@ -2060,8 +2178,9 @@ static bool where_is_object_parslow(Object *ob, float obmat[4][4], float slowmat } /* note, scene is the active scene while actual_scene is the scene the object resides in */ -void BKE_object_where_is_calc_time_ex(Scene *scene, Object *ob, float ctime, - RigidBodyWorld *rbw, float r_originmat[3][3]) +void BKE_object_where_is_calc_time_ex( + const EvaluationContext *eval_ctx, Scene *scene, Object *ob, float ctime, + RigidBodyWorld *rbw, float r_originmat[3][3]) { if (ob == NULL) return; @@ -2096,7 +2215,7 @@ void BKE_object_where_is_calc_time_ex(Scene *scene, Object *ob, float ctime, if (ob->constraints.first && !(ob->transflag & OB_NO_CONSTRAINTS)) { bConstraintOb *cob; cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); - BKE_constraints_solve(&ob->constraints, cob, ctime); + BKE_constraints_solve(eval_ctx, &ob->constraints, cob, ctime); BKE_constraints_clear_evalob(cob); } @@ -2105,9 +2224,9 @@ void BKE_object_where_is_calc_time_ex(Scene *scene, Object *ob, float ctime, else ob->transflag &= ~OB_NEG_SCALE; } -void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime) +void BKE_object_where_is_calc_time(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, float ctime) { - BKE_object_where_is_calc_time_ex(scene, ob, ctime, NULL, NULL); + BKE_object_where_is_calc_time_ex(eval_ctx, scene, ob, ctime, NULL, NULL); } /* get object transformation matrix without recalculating dependencies and @@ -2132,17 +2251,17 @@ void BKE_object_where_is_calc_mat4(Scene *scene, Object *ob, float obmat[4][4]) } } -void BKE_object_where_is_calc_ex(Scene *scene, RigidBodyWorld *rbw, Object *ob, float r_originmat[3][3]) +void BKE_object_where_is_calc_ex(const EvaluationContext *eval_ctx, Scene *scene, RigidBodyWorld *rbw, Object *ob, float r_originmat[3][3]) { - BKE_object_where_is_calc_time_ex(scene, ob, BKE_scene_frame_get(scene), rbw, r_originmat); + BKE_object_where_is_calc_time_ex(eval_ctx, scene, ob, BKE_scene_frame_get(scene), rbw, r_originmat); } -void BKE_object_where_is_calc(Scene *scene, Object *ob) +void BKE_object_where_is_calc(const EvaluationContext *eval_ctx, Scene *scene, Object *ob) { - BKE_object_where_is_calc_time_ex(scene, ob, BKE_scene_frame_get(scene), NULL, NULL); + BKE_object_where_is_calc_time_ex(eval_ctx, scene, ob, BKE_scene_frame_get(scene), NULL, NULL); } /* for calculation of the inverse parent transform, only used for editor */ -void BKE_object_workob_calc_parent(Scene *scene, Object *ob, Object *workob) +void BKE_object_workob_calc_parent(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, Object *workob) { BKE_object_workob_clear(workob); @@ -2164,7 +2283,7 @@ void BKE_object_workob_calc_parent(Scene *scene, Object *ob, Object *workob) BLI_strncpy(workob->parsubstr, ob->parsubstr, sizeof(workob->parsubstr)); - BKE_object_where_is_calc(scene, workob); + BKE_object_where_is_calc(eval_ctx, scene, workob); } /* see BKE_pchan_apply_mat4() for the equivalent 'pchan' function */ @@ -2489,14 +2608,14 @@ void BKE_object_foreach_display_point( } void BKE_scene_foreach_display_point( - Scene *scene, View3D *v3d, const short flag, + Scene *scene, ViewLayer *view_layer, void (*func_cb)(const float[3], void *), void *user_data) { Base *base; Object *ob; - for (base = FIRSTBASE; base; base = base->next) { - if (BASE_VISIBLE_BGMODE(v3d, scene, base) && (base->flag & flag) == flag) { + for (base = FIRSTBASE(view_layer); base; base = base->next) { + if (((base->flag & BASE_VISIBLED) != 0) && ((base->flag & BASE_SELECTED) != 0)) { ob = base->object; if ((ob->transflag & OB_DUPLI) == 0) { @@ -2586,7 +2705,7 @@ bool BKE_object_parent_loop_check(const Object *par, const Object *ob) return BKE_object_parent_loop_check(par->parent, ob); } -static void object_handle_update_proxy(EvaluationContext *eval_ctx, +static void object_handle_update_proxy(const EvaluationContext *eval_ctx, Scene *scene, Object *object, const bool do_proxy_update) @@ -2616,12 +2735,17 @@ static void object_handle_update_proxy(EvaluationContext *eval_ctx, /* the main object update call, for object matrix, constraints, keys and displist (modifiers) */ /* requires flags to be set! */ /* Ideally we shouldn't have to pass the rigid body world, but need bigger restructuring to avoid id */ -void BKE_object_handle_update_ex(EvaluationContext *eval_ctx, +void BKE_object_handle_update_ex(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, RigidBodyWorld *rbw, const bool do_proxy_update) { - if ((ob->recalc & OB_RECALC_ALL) == 0) { + const ID *object_data = ob->data; + const bool recalc_object = (ob->id.recalc & ID_RECALC) != 0; + const bool recalc_data = + (object_data != NULL) ? ((object_data->recalc & ID_RECALC_ALL) != 0) + : 0; + if (!recalc_object && ! recalc_data) { object_handle_update_proxy(eval_ctx, scene, ob, do_proxy_update); return; } @@ -2632,7 +2756,7 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx, BKE_pose_update_constraint_flags(ob->pose); } } - if (ob->recalc & OB_RECALC_DATA) { + if (recalc_data) { if (ob->type == OB_ARMATURE) { /* this happens for reading old files and to match library armatures * with poses we do it ahead of BKE_object_where_is_calc to ensure animation @@ -2645,21 +2769,21 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx, /* XXX new animsys warning: depsgraph tag OB_RECALC_DATA should not skip drivers, * which is only in BKE_object_where_is_calc now */ /* XXX: should this case be OB_RECALC_OB instead? */ - if (ob->recalc & OB_RECALC_ALL) { + if (recalc_object || recalc_data) { if (G.debug & G_DEBUG_DEPSGRAPH) { printf("recalcob %s\n", ob->id.name + 2); } /* Handle proxy copy for target. */ if (!BKE_object_eval_proxy_copy(eval_ctx, ob)) { - BKE_object_where_is_calc_ex(scene, rbw, ob, NULL); + BKE_object_where_is_calc_ex(eval_ctx, scene, rbw, ob, NULL); } } - if (ob->recalc & OB_RECALC_DATA) { + if (recalc_data) { BKE_object_handle_data_update(eval_ctx, scene, ob); } - ob->recalc &= ~OB_RECALC_ALL; + ob->id.recalc &= ID_RECALC_ALL; object_handle_update_proxy(eval_ctx, scene, ob, do_proxy_update); } @@ -2669,7 +2793,7 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx, * e.g. "scene" <-- set 1 <-- set 2 ("ob" lives here) <-- set 3 <-- ... <-- set n * rigid bodies depend on their world so use BKE_object_handle_update_ex() to also pass along the corrent rigid body world */ -void BKE_object_handle_update(EvaluationContext *eval_ctx, Scene *scene, Object *ob) +void BKE_object_handle_update(const EvaluationContext *eval_ctx, Scene *scene, Object *ob) { BKE_object_handle_update_ex(eval_ctx, scene, ob, NULL, true); } @@ -2716,14 +2840,7 @@ int BKE_object_obdata_texspace_get(Object *ob, short **r_texflag, float **r_loc, switch (GS(((ID *)ob->data)->name)) { case ID_ME: { - Mesh *me = ob->data; - if (me->bb == NULL || (me->bb->flag & BOUNDBOX_DIRTY)) { - BKE_mesh_texspace_calc(me); - } - if (r_texflag) *r_texflag = &me->texflag; - if (r_loc) *r_loc = me->loc; - if (r_size) *r_size = me->size; - if (r_rot) *r_rot = me->rot; + BKE_mesh_texspace_get_reference((Mesh *)ob->data, r_texflag, r_loc, r_rot, r_size); break; } case ID_CU: @@ -3290,33 +3407,33 @@ static void obrel_list_add(LinkNode **links, Object *ob) } /* - * Iterates over all objects of the given scene. + * Iterates over all objects of the given scene layer. * Depending on the eObjectSet flag: * collect either OB_SET_ALL, OB_SET_VISIBLE or OB_SET_SELECTED objects. * If OB_SET_VISIBLE or OB_SET_SELECTED are collected, * then also add related objects according to the given includeFilters. */ -LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter) +LinkNode *BKE_object_relational_superset(struct ViewLayer *view_layer, eObjectSet objectSet, eObRelationTypes includeFilter) { LinkNode *links = NULL; Base *base; /* Remove markers from all objects */ - for (base = scene->base.first; base; base = base->next) { + for (base = view_layer->object_bases.first; base; base = base->next) { base->object->id.tag &= ~LIB_TAG_DOIT; } /* iterate over all selected and visible objects */ - for (base = scene->base.first; base; base = base->next) { + for (base = view_layer->object_bases.first; base; base = base->next) { if (objectSet == OB_SET_ALL) { /* as we get all anyways just add it */ Object *ob = base->object; obrel_list_add(&links, ob); } else { - if ((objectSet == OB_SET_SELECTED && TESTBASELIB_BGMODE(((View3D *)NULL), scene, base)) || - (objectSet == OB_SET_VISIBLE && BASE_EDITABLE_BGMODE(((View3D *)NULL), scene, base))) + if ((objectSet == OB_SET_SELECTED && TESTBASELIB_BGMODE(base)) || + (objectSet == OB_SET_VISIBLE && BASE_EDITABLE_BGMODE(base))) { Object *ob = base->object; @@ -3345,8 +3462,8 @@ LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectS /* child relationship */ if (includeFilter & (OB_REL_CHILDREN | OB_REL_CHILDREN_RECURSIVE)) { Base *local_base; - for (local_base = scene->base.first; local_base; local_base = local_base->next) { - if (BASE_EDITABLE_BGMODE(((View3D *)NULL), scene, local_base)) { + for (local_base = view_layer->object_bases.first; local_base; local_base = local_base->next) { + if (BASE_EDITABLE_BGMODE(local_base)) { Object *child = local_base->object; if (obrel_list_test(child)) { @@ -3390,18 +3507,11 @@ struct LinkNode *BKE_object_groups(Object *ob) return group_linknode; } -void BKE_object_groups_clear(Scene *scene, Base *base, Object *object) +void BKE_object_groups_clear(Object *ob) { Group *group = NULL; - - BLI_assert((base == NULL) || (base->object == object)); - - if (scene && base == NULL) { - base = BKE_scene_base_find(scene, object); - } - - while ((group = BKE_group_object_find(group, base->object))) { - BKE_group_object_unlink(group, object, scene, base); + while ((group = BKE_group_object_find(group, ob))) { + BKE_group_object_unlink(group, ob); } } @@ -3602,9 +3712,9 @@ static void object_cacheIgnoreClear(Object *ob, int state) /* Note: this function should eventually be replaced by depsgraph functionality. * Avoid calling this in new code unless there is a very good reason for it! */ -bool BKE_object_modifier_update_subframe(Scene *scene, Object *ob, bool update_mesh, - int parent_recursion, float frame, - int type) +bool BKE_object_modifier_update_subframe( + const EvaluationContext *eval_ctx, Scene *scene, Object *ob, bool update_mesh, + int parent_recursion, float frame, int type) { ModifierData *md = modifiers_findByType(ob, (ModifierType)type); bConstraint *con; @@ -3627,8 +3737,8 @@ bool BKE_object_modifier_update_subframe(Scene *scene, Object *ob, bool update_m if (parent_recursion) { int recursion = parent_recursion - 1; bool no_update = false; - if (ob->parent) no_update |= BKE_object_modifier_update_subframe(scene, ob->parent, 0, recursion, frame, type); - if (ob->track) no_update |= BKE_object_modifier_update_subframe(scene, ob->track, 0, recursion, frame, type); + if (ob->parent) no_update |= BKE_object_modifier_update_subframe(eval_ctx, scene, ob->parent, 0, recursion, frame, type); + if (ob->track) no_update |= BKE_object_modifier_update_subframe(eval_ctx, scene, ob->track, 0, recursion, frame, type); /* skip subframe if object is parented * to vertex of a dynamic paint canvas */ @@ -3645,7 +3755,7 @@ bool BKE_object_modifier_update_subframe(Scene *scene, Object *ob, bool update_m cti->get_constraint_targets(con, &targets); for (ct = targets.first; ct; ct = ct->next) { if (ct->tar) - BKE_object_modifier_update_subframe(scene, ct->tar, 0, recursion, frame, type); + BKE_object_modifier_update_subframe(eval_ctx, scene, ct->tar, 0, recursion, frame, type); } /* free temp targets */ if (cti->flush_constraint_targets) @@ -3655,7 +3765,8 @@ bool BKE_object_modifier_update_subframe(Scene *scene, Object *ob, bool update_m } /* was originally OB_RECALC_ALL - TODO - which flags are really needed??? */ - ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME; + /* TODO(sergey): What about animation? */ + ob->id.recalc |= ID_RECALC_ALL; BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, frame, ADT_RECALC_ANIM); if (update_mesh) { /* ignore cache clear during subframe updates @@ -3665,7 +3776,7 @@ bool BKE_object_modifier_update_subframe(Scene *scene, Object *ob, bool update_m object_cacheIgnoreClear(ob, 0); } else - BKE_object_where_is_calc_time(scene, ob, frame); + BKE_object_where_is_calc_time(eval_ctx, scene, ob, frame); /* for curve following objects, parented curve has to be updated too */ if (ob->type == OB_CURVE) { @@ -3676,7 +3787,7 @@ bool BKE_object_modifier_update_subframe(Scene *scene, Object *ob, bool update_m if (ob->type == OB_ARMATURE) { bArmature *arm = ob->data; BKE_animsys_evaluate_animdata(scene, &arm->id, arm->adt, frame, ADT_RECALC_ANIM); - BKE_pose_where_is(scene, ob); + BKE_pose_where_is(eval_ctx, scene, ob); } return false; diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c index 4f92509827f..c298427b38d 100644 --- a/source/blender/blenkernel/intern/object_deform.c +++ b/source/blender/blenkernel/intern/object_deform.c @@ -51,6 +51,7 @@ #include "BKE_editmesh.h" #include "BKE_object_deform.h" /* own include */ #include "BKE_object.h" +#include "BKE_mesh.h" #include "BKE_modifier.h" /** \name Misc helpers @@ -405,6 +406,8 @@ void BKE_object_defgroup_remove(Object *ob, bDeformGroup *defgroup) object_defgroup_remove_edit_mode(ob, defgroup); else object_defgroup_remove_object_mode(ob, defgroup); + + BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL); } /** diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index 56d5cb609fc..f9f6b0aab40 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -49,10 +49,10 @@ #include "BKE_animsys.h" #include "BKE_DerivedMesh.h" -#include "BKE_depsgraph.h" #include "BKE_font.h" -#include "BKE_group.h" #include "BKE_global.h" +#include "BKE_group.h" +#include "BKE_idprop.h" #include "BKE_lattice.h" #include "BKE_main.h" #include "BKE_mesh.h" @@ -62,6 +62,7 @@ #include "BKE_editmesh.h" #include "BKE_anim.h" +#include "DEG_depsgraph.h" #include "BLI_strict_flags.h" #include "BLI_hash.h" @@ -69,15 +70,15 @@ /* Dupli-Geometry */ typedef struct DupliContext { - EvaluationContext *eval_ctx; + const EvaluationContext *eval_ctx; bool do_update; bool animated; Group *group; /* XXX child objects are selected from this group if set, could be nicer */ Scene *scene; + ViewLayer *view_layer; Object *object; float space_mat[4][4]; - unsigned int lay; int persistent_id[MAX_DUPLI_RECUR]; int level; @@ -96,10 +97,11 @@ typedef struct DupliGenerator { static const DupliGenerator *get_dupli_generator(const DupliContext *ctx); /* create initial context for root object */ -static void init_context(DupliContext *r_ctx, EvaluationContext *eval_ctx, Scene *scene, Object *ob, float space_mat[4][4], bool update) +static void init_context(DupliContext *r_ctx, const EvaluationContext *eval_ctx, Scene *scene, Object *ob, float space_mat[4][4], bool update) { r_ctx->eval_ctx = eval_ctx; r_ctx->scene = scene; + r_ctx->view_layer = eval_ctx->view_layer; /* don't allow BKE_object_handle_update for viewport during render, can crash */ r_ctx->do_update = update && !(G.is_rendering && eval_ctx->mode != DAG_EVAL_RENDER); r_ctx->animated = false; @@ -110,7 +112,6 @@ static void init_context(DupliContext *r_ctx, EvaluationContext *eval_ctx, Scene copy_m4_m4(r_ctx->space_mat, space_mat); else unit_m4(r_ctx->space_mat); - r_ctx->lay = ob->lay; r_ctx->level = 0; r_ctx->gen = get_dupli_generator(r_ctx); @@ -143,7 +144,8 @@ static void copy_dupli_context(DupliContext *r_ctx, const DupliContext *ctx, Obj */ static DupliObject *make_dupli(const DupliContext *ctx, Object *ob, float mat[4][4], int index, - bool animated, bool hide) + bool animated, bool hide, + IDProperty *collection_properties) { DupliObject *dob; int i; @@ -198,6 +200,10 @@ static DupliObject *make_dupli(const DupliContext *ctx, dob->random_id ^= BLI_hash_int(BLI_hash_string(ctx->object->id.name + 2)); } + if (collection_properties) { + dob->collection_properties = IDP_CopyProperty(collection_properties); + } + return dob; } @@ -238,32 +244,30 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild Object *obedit = ctx->scene->obedit; if (ctx->group) { - unsigned int lay = ctx->group->layer; int groupid = 0; - GroupObject *go; - for (go = ctx->group->gobject.first; go; go = go->next, groupid++) { - Object *ob = go->ob; - - if ((ob->lay & lay) && ob != obedit && is_child(ob, parent)) { + FOREACH_GROUP_BASE(ctx->group, base) + { + Object *ob = base->object; + if ((base->flag & BASE_VISIBLED) && ob != obedit && is_child(ob, parent)) { DupliContext pctx; copy_dupli_context(&pctx, ctx, ctx->object, NULL, groupid, false); /* mballs have a different dupli handling */ - if (ob->type != OB_MBALL) + if (ob->type != OB_MBALL) { ob->flag |= OB_DONE; /* doesnt render */ - + } make_child_duplis_cb(&pctx, userdata, ob); } + groupid++; } + FOREACH_GROUP_BASE_END } else { - unsigned int lay = ctx->scene->lay; int baseid = 0; - Base *base; - for (base = ctx->scene->base.first; base; base = base->next, baseid++) { + ViewLayer *view_layer = ctx->view_layer; + for (Base *base = view_layer->object_bases.first; base; base = base->next, baseid++) { Object *ob = base->object; - - if ((base->lay & lay) && ob != obedit && is_child(ob, parent)) { + if (ob != obedit && is_child(ob, parent)) { DupliContext pctx; copy_dupli_context(&pctx, ctx, ctx->object, NULL, baseid, false); @@ -283,13 +287,12 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild /* OB_DUPLIGROUP */ static void make_duplis_group(const DupliContext *ctx) { - bool for_render = (ctx->eval_ctx->mode == DAG_EVAL_RENDER); Object *ob = ctx->object; Group *group; - GroupObject *go; + Base *base; float group_mat[4][4]; int id; - bool animated, hide; + bool animated; if (ob->dup_group == NULL) return; group = ob->dup_group; @@ -311,34 +314,18 @@ static void make_duplis_group(const DupliContext *ctx) animated = BKE_group_is_animated(group, ob); - for (go = group->gobject.first, id = 0; go; go = go->next, id++) { - /* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */ - if (go->ob != ob) { + for (base = group->view_layer->object_bases.first, id = 0; base; base = base->next, id++) { + if (base->object != ob && (base->flag & BASE_VISIBLED)) { float mat[4][4]; - /* Special case for instancing dupli-groups, see: T40051 - * this object may be instanced via dupli-verts/faces, in this case we don't want to render - * (blender convention), but _do_ show in the viewport. - * - * Regular objects work fine but not if we're instancing dupli-groups, - * because the rules for rendering aren't applied to objects they instance. - * We could recursively pass down the 'hide' flag instead, but that seems unnecessary. - */ - if (for_render && go->ob->parent && go->ob->parent->transflag & (OB_DUPLIVERTS | OB_DUPLIFACES)) { - continue; - } - /* group dupli offset, should apply after everything else */ - mul_m4_m4m4(mat, group_mat, go->ob->obmat); + mul_m4_m4m4(mat, group_mat, base->object->obmat); - /* check the group instance and object layers match, also that the object visible flags are ok. */ - hide = (go->ob->lay & group->layer) == 0 || - (for_render ? go->ob->restrictflag & OB_RESTRICT_RENDER : go->ob->restrictflag & OB_RESTRICT_VIEW); - - make_dupli(ctx, go->ob, mat, id, animated, hide); + BLI_assert(base->collection_properties != NULL); + make_dupli(ctx, base->object, mat, id, animated, false, base->collection_properties); /* recursion */ - make_recursive_duplis(ctx, go->ob, group_mat, id, animated); + make_recursive_duplis(ctx, base->object, group_mat, id, animated); } } } @@ -377,10 +364,6 @@ static void make_duplis_frames(const DupliContext *ctx) /* duplicate over the required range */ if (ob->transflag & OB_DUPLINOSPEED) enable_cu_speed = 0; - /* special flag to avoid setting recalc flags to notify the depsgraph of - * updates, as this is not a permanent change to the object */ - ob->id.recalc |= ID_RECALC_SKIP_ANIM_TAG; - for (scene->r.cfra = ob->dupsta; scene->r.cfra <= dupend; scene->r.cfra++) { int ok = 1; @@ -399,9 +382,9 @@ static void make_duplis_frames(const DupliContext *ctx) * However, this has always been the way that this worked (i.e. pre 2.5), so I guess that it'll be fine! */ BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */ - BKE_object_where_is_calc_time(scene, ob, (float)scene->r.cfra); + BKE_object_where_is_calc_time(ctx->eval_ctx, scene, ob, (float)scene->r.cfra); - make_dupli(ctx, ob, ob->obmat, scene->r.cfra, false, false); + make_dupli(ctx, ob, ob->obmat, scene->r.cfra, false, false, NULL); } } @@ -413,7 +396,7 @@ static void make_duplis_frames(const DupliContext *ctx) scene->r.cfra = cfrao; BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */ - BKE_object_where_is_calc_time(scene, ob, (float)scene->r.cfra); + BKE_object_where_is_calc_time(ctx->eval_ctx, scene, ob, (float)scene->r.cfra); /* but, to make sure unkeyed object transforms are still sane, * let's copy object's original data back over @@ -486,7 +469,7 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3], */ mul_m4_m4m4(space_mat, obmat, inst_ob->imat); - dob = make_dupli(vdd->ctx, vdd->inst_ob, obmat, index, false, false); + dob = make_dupli(vdd->ctx, vdd->inst_ob, obmat, index, false, false, NULL); if (vdd->orco) copy_v3_v3(dob->orco, vdd->orco[index]); @@ -548,13 +531,13 @@ static void make_duplis_verts(const DupliContext *ctx) CustomDataMask dm_mask = (use_texcoords ? CD_MASK_BAREMESH | CD_MASK_ORCO : CD_MASK_BAREMESH); if (ctx->eval_ctx->mode == DAG_EVAL_RENDER) { - vdd.dm = mesh_create_derived_render(scene, parent, dm_mask); + vdd.dm = mesh_create_derived_render(ctx->eval_ctx, scene, parent, dm_mask); } else if (em) { - vdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask); + vdd.dm = editbmesh_get_derived_cage(ctx->eval_ctx, scene, parent, em, dm_mask); } else { - vdd.dm = mesh_get_derived_final(scene, parent, dm_mask); + vdd.dm = mesh_get_derived_final(ctx->eval_ctx, scene, parent, dm_mask); } vdd.edit_btmesh = me->edit_btmesh; @@ -671,7 +654,7 @@ static void make_duplis_font(const DupliContext *ctx) copy_v3_v3(obmat[3], vec); - make_dupli(ctx, ob, obmat, a, false, false); + make_dupli(ctx, ob, obmat, a, false, false, NULL); } } @@ -777,7 +760,7 @@ static void make_child_duplis_faces(const DupliContext *ctx, void *userdata, Obj */ mul_m4_m4m4(space_mat, obmat, inst_ob->imat); - dob = make_dupli(ctx, inst_ob, obmat, a, false, false); + dob = make_dupli(ctx, inst_ob, obmat, a, false, false, NULL); if (use_texcoords) { float w = 1.0f / (float)mp->totloop; @@ -816,13 +799,13 @@ static void make_duplis_faces(const DupliContext *ctx) CustomDataMask dm_mask = (use_texcoords ? CD_MASK_BAREMESH | CD_MASK_ORCO | CD_MASK_MLOOPUV : CD_MASK_BAREMESH); if (ctx->eval_ctx->mode == DAG_EVAL_RENDER) { - fdd.dm = mesh_create_derived_render(scene, parent, dm_mask); + fdd.dm = mesh_create_derived_render(ctx->eval_ctx, scene, parent, dm_mask); } else if (em) { - fdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask); + fdd.dm = editbmesh_get_derived_cage(ctx->eval_ctx, scene, parent, em, dm_mask); } else { - fdd.dm = mesh_get_derived_final(scene, parent, dm_mask); + fdd.dm = mesh_get_derived_final(ctx->eval_ctx, scene, parent, dm_mask); } if (use_texcoords) { @@ -860,7 +843,6 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem bool for_render = ctx->eval_ctx->mode == DAG_EVAL_RENDER; bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); - GroupObject *go; Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL; DupliObject *dob; ParticleDupliWeight *dw; @@ -900,6 +882,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem if ((psys->renderdata || part->draw_as == PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) { ParticleSimulationData sim = {NULL}; + sim.eval_ctx = ctx->eval_ctx; sim.scene = scene; sim.ob = par; sim.psys = psys; @@ -913,10 +896,10 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem return; } else { /*PART_DRAW_GR */ - if (part->dup_group == NULL || BLI_listbase_is_empty(&part->dup_group->gobject)) + if (part->dup_group == NULL || BLI_listbase_is_empty(&part->dup_group->view_layer->object_bases)) return; - if (BLI_findptr(&part->dup_group->gobject, par, offsetof(GroupObject, ob))) { + if (BLI_findptr(&part->dup_group->view_layer->object_bases, par, offsetof(Base, object))) { return; } } @@ -948,8 +931,12 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem totgroup += dw->count; } else { - for (go = part->dup_group->gobject.first; go; go = go->next) + FOREACH_GROUP_OBJECT(part->dup_group, object) + { + (void) object; totgroup++; + } + FOREACH_GROUP_OBJECT_END } /* we also copy the actual objects to restore afterwards, since @@ -968,11 +955,18 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem } } else { - go = part->dup_group->gobject.first; - for (a = 0; a < totgroup; a++, go = go->next) { - oblist[a] = go->ob; - obcopylist[a] = *go->ob; + a = 0; + FOREACH_GROUP_OBJECT(part->dup_group, object) + { + oblist[a] = object; + obcopylist[a] = *object; + a++; + + if (a >= totgroup) { + continue; + } } + FOREACH_GROUP_OBJECT_END } } else { @@ -1061,27 +1055,37 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem } if (part->ren_as == PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) { - for (go = part->dup_group->gobject.first, b = 0; go; go = go->next, b++) { - + b = 0; + FOREACH_GROUP_OBJECT(part->dup_group, object) + { copy_m4_m4(tmat, oblist[b]->obmat); + /* apply particle scale */ mul_mat3_m4_fl(tmat, size * scale); mul_v3_fl(tmat[3], size * scale); + /* group dupli offset, should apply after everything else */ - if (!is_zero_v3(part->dup_group->dupli_ofs)) + if (!is_zero_v3(part->dup_group->dupli_ofs)) { sub_v3_v3(tmat[3], part->dup_group->dupli_ofs); + } + /* individual particle transform */ mul_m4_m4m4(mat, pamat, tmat); - dob = make_dupli(ctx, go->ob, mat, a, false, false); + dob = make_dupli(ctx, object, mat, a, false, false, NULL); dob->particle_system = psys; - if (use_texcoords) + + if (use_texcoords) { psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); + } + + b++; } + FOREACH_GROUP_OBJECT_END } else { /* to give ipos in object correct offset */ - BKE_object_where_is_calc_time(scene, ob, ctime - pa_time); + BKE_object_where_is_calc_time(ctx->eval_ctx, scene, ob, ctime - pa_time); copy_v3_v3(vec, obmat[3]); obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f; @@ -1122,7 +1126,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem if (part->draw & PART_DRAW_GLOBAL_OB) add_v3_v3v3(mat[3], mat[3], vec); - dob = make_dupli(ctx, ob, mat, a, false, false); + dob = make_dupli(ctx, ob, mat, a, false, false, NULL); dob->particle_system = psys; if (use_texcoords) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); @@ -1217,7 +1221,7 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx) /* ---- ListBase dupli container implementation ---- */ /* Returns a list of DupliObject */ -ListBase *object_duplilist_ex(EvaluationContext *eval_ctx, Scene *scene, Object *ob, bool update) +ListBase *object_duplilist_ex(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, bool update) { ListBase *duplilist = MEM_callocN(sizeof(ListBase), "duplilist"); DupliContext ctx; @@ -1232,13 +1236,21 @@ ListBase *object_duplilist_ex(EvaluationContext *eval_ctx, Scene *scene, Object /* note: previously updating was always done, this is why it defaults to be on * but there are likely places it can be called without updating */ -ListBase *object_duplilist(EvaluationContext *eval_ctx, Scene *sce, Object *ob) +ListBase *object_duplilist(const EvaluationContext *eval_ctx, Scene *sce, Object *ob) { return object_duplilist_ex(eval_ctx, sce, ob, true); } void free_object_duplilist(ListBase *lb) { + + for (DupliObject *dob = lb->first; dob; dob = dob->next) { + if (dob->collection_properties) { + IDP_FreeProperty(dob->collection_properties); + MEM_freeN(dob->collection_properties); + } + } + BLI_freelistN(lb); MEM_freeN(lb); } @@ -1273,7 +1285,7 @@ int count_duplilist(Object *ob) return 1; } -DupliApplyData *duplilist_apply(Object *ob, Scene *scene, ListBase *duplilist) +DupliApplyData *duplilist_apply(const EvaluationContext *eval_ctx, Object *ob, Scene *scene, ListBase *duplilist) { DupliApplyData *apply_data = NULL; int num_objects = BLI_listbase_count(duplilist); @@ -1289,7 +1301,7 @@ DupliApplyData *duplilist_apply(Object *ob, Scene *scene, ListBase *duplilist) for (dob = duplilist->first, i = 0; dob; dob = dob->next, ++i) { /* make sure derivedmesh is calculated once, before drawing */ if (scene && !(dob->ob->transflag & OB_DUPLICALCDERIVED) && dob->ob->type == OB_MESH) { - mesh_get_derived_final(scene, dob->ob, scene->customdata_mask); + mesh_get_derived_final(eval_ctx, scene, dob->ob, scene->customdata_mask); dob->ob->transflag |= OB_DUPLICALCDERIVED; } } diff --git a/source/blender/blenkernel/intern/object_facemap.c b/source/blender/blenkernel/intern/object_facemap.c new file mode 100644 index 00000000000..1218dd376cb --- /dev/null +++ b/source/blender/blenkernel/intern/object_facemap.c @@ -0,0 +1,257 @@ + +/* + * ***** 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) 2008 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file blender/blenkernel/intern/object_facemap.c + * \ingroup bke + */ + +#include <string.h> + +#include "DNA_object_types.h" +#include "DNA_mesh_types.h" + +#include "BLI_utildefines.h" +#include "BLI_path_util.h" +#include "BLI_string.h" +#include "BLI_string_utils.h" +#include "BLI_listbase.h" + +#include "BKE_context.h" +#include "BKE_customdata.h" +#include "BKE_editmesh.h" +#include "BKE_object.h" +#include "BKE_object_facemap.h" /* own include */ +#include "BKE_object_deform.h" + +#include "BLT_translation.h" + +#include "MEM_guardedalloc.h" + +#include "RNA_define.h" +#include "RNA_access.h" + +static bool fmap_unique_check(void *arg, const char *name) +{ + struct {Object *ob; void *fm; } *data = arg; + + bFaceMap *fmap; + + for (fmap = data->ob->fmaps.first; fmap; fmap = fmap->next) { + if (data->fm != fmap) { + if (!strcmp(fmap->name, name)) { + return true; + } + } + } + + return false; +} + +static bFaceMap *fmap_duplicate(bFaceMap *infmap) +{ + bFaceMap *outfmap; + + if (!infmap) + return NULL; + + outfmap = MEM_callocN(sizeof(bFaceMap), "copy facemap"); + + /* For now, just copy everything over. */ + memcpy(outfmap, infmap, sizeof(bFaceMap)); + + outfmap->next = outfmap->prev = NULL; + + return outfmap; +} + +void BKE_object_facemap_copy_list(ListBase *outbase, const ListBase *inbase) +{ + bFaceMap *fmap, *fmapn; + + BLI_listbase_clear(outbase); + + for (fmap = inbase->first; fmap; fmap = fmap->next) { + fmapn = fmap_duplicate(fmap); + BLI_addtail(outbase, fmapn); + } +} + +void BKE_object_facemap_unique_name(Object *ob, bFaceMap *fmap) +{ + struct {Object *ob; void *fmap; } data; + data.ob = ob; + data.fmap = fmap; + + BLI_uniquename_cb(fmap_unique_check, &data, DATA_("Group"), '.', fmap->name, sizeof(fmap->name)); +} + +bFaceMap *BKE_object_facemap_add_name(Object *ob, const char *name) +{ + bFaceMap *fmap; + + if (!ob || ob->type != OB_MESH) + return NULL; + + fmap = MEM_callocN(sizeof(bFaceMap), __func__); + + BLI_strncpy(fmap->name, name, sizeof(fmap->name)); + + BLI_addtail(&ob->fmaps, fmap); + + ob->actfmap = BLI_listbase_count(&ob->fmaps); + + BKE_object_facemap_unique_name(ob, fmap); + + return fmap; +} + +bFaceMap *BKE_object_facemap_add(Object *ob) +{ + return BKE_object_facemap_add_name(ob, DATA_("FaceMap")); +} + + +static void object_fmap_remove_edit_mode(Object *ob, bFaceMap *fmap, bool do_selected, bool purge) +{ + const int fmap_nr = BLI_findindex(&ob->fmaps, fmap); + + if (ob->type == OB_MESH) { + Mesh *me = ob->data; + + if (me->edit_btmesh) { + BMEditMesh *em = me->edit_btmesh; + const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP); + + if (cd_fmap_offset != -1) { + BMFace *efa; + BMIter iter; + int *map; + + if (purge) { + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset); + + if (map) { + if (*map == fmap_nr) + *map = -1; + else if (*map > fmap_nr) + *map -= 1; + } + } + } + else { + BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) { + map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset); + + if (map && *map == fmap_nr && (!do_selected || BM_elem_flag_test(efa, BM_ELEM_SELECT))) { + *map = -1; + } + } + } + } + + if (ob->actfmap == BLI_listbase_count(&ob->fmaps)) + ob->actfmap--; + + BLI_remlink(&ob->fmaps, fmap); + MEM_freeN(fmap); + } + } +} + +static void object_fmap_remove_object_mode(Object *ob, bFaceMap *fmap, bool purge) +{ + const int fmap_nr = BLI_findindex(&ob->fmaps, fmap); + + if (ob->type == OB_MESH) { + Mesh *me = ob->data; + + if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) { + int *map = CustomData_get_layer(&me->pdata, CD_FACEMAP); + int i; + + if (map) { + for (i = 0; i < me->totpoly; i++) { + if (map[i] == fmap_nr) + map[i] = -1; + else if (purge && map[i] > fmap_nr) + map[i]--; + } + } + } + + if (ob->actfmap == BLI_listbase_count(&ob->fmaps)) + ob->actfmap--; + + BLI_remlink(&ob->fmaps, fmap); + MEM_freeN(fmap); + } +} + +static void fmap_remove_exec(Object *ob, bFaceMap *fmap, const bool is_edit_mode, const bool purge) +{ + if (is_edit_mode) + object_fmap_remove_edit_mode(ob, fmap, false, purge); + else + object_fmap_remove_object_mode(ob, fmap, purge); +} + +void BKE_object_facemap_remove(Object *ob, bFaceMap *fmap) +{ + fmap_remove_exec(ob, fmap, BKE_object_is_in_editmode(ob), true); +} + +void BKE_object_facemap_clear(Object *ob) +{ + bFaceMap *fmap = (bFaceMap *)ob->fmaps.first; + + if (fmap) { + const bool edit_mode = BKE_object_is_in_editmode_vgroup(ob); + + while (fmap) { + bFaceMap *next_fmap = fmap->next; + fmap_remove_exec(ob, fmap, edit_mode, false); + fmap = next_fmap; + } + } + /* remove all face-maps */ + if (ob->type == OB_MESH) { + Mesh *me = ob->data; + CustomData_free_layer(&me->pdata, CD_FACEMAP, me->totpoly, 0); + } + ob->actfmap = 0; +} + +int BKE_object_facemap_name_index(Object *ob, const char *name) +{ + return (name) ? BLI_findstringindex(&ob->fmaps, name, offsetof(bFaceMap, name)) : -1; +} + +bFaceMap *BKE_object_facemap_find_name(Object *ob, const char *name) +{ + return BLI_findstring(&ob->fmaps, name, offsetof(bFaceMap, name)); +} diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c index 84d2f624577..bc183ba95a6 100644 --- a/source/blender/blenkernel/intern/object_update.c +++ b/source/blender/blenkernel/intern/object_update.c @@ -32,18 +32,18 @@ #include "DNA_group_types.h" #include "DNA_key_types.h" #include "DNA_material_types.h" +#include "DNA_mesh_types.h" #include "DNA_scene_types.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" #include "BLI_math.h" -#include "BLI_threads.h" #include "BKE_global.h" #include "BKE_armature.h" #include "BKE_action.h" #include "BKE_constraint.h" -#include "BKE_depsgraph.h" +#include "BKE_curve.h" #include "BKE_DerivedMesh.h" #include "BKE_animsys.h" #include "BKE_displist.h" @@ -51,28 +51,26 @@ #include "BKE_key.h" #include "BKE_lamp.h" #include "BKE_lattice.h" +#include "BKE_library.h" #include "BKE_editmesh.h" #include "BKE_object.h" #include "BKE_particle.h" #include "BKE_pointcache.h" #include "BKE_scene.h" #include "BKE_material.h" +#include "BKE_mball.h" +#include "BKE_mesh.h" #include "BKE_image.h" +#include "MEM_guardedalloc.h" #include "DEG_depsgraph.h" -#ifdef WITH_LEGACY_DEPSGRAPH -# define DEBUG_PRINT if (!DEG_depsgraph_use_legacy() && G.debug & G_DEBUG_DEPSGRAPH) printf -#else -# define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf -#endif - -static ThreadMutex material_lock = BLI_MUTEX_INITIALIZER; +#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf -void BKE_object_eval_local_transform(EvaluationContext *UNUSED(eval_ctx), +void BKE_object_eval_local_transform(const EvaluationContext *UNUSED(eval_ctx), Object *ob) { - DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob); /* calculate local matrix */ BKE_object_to_mat4(ob, ob->obmat); @@ -80,7 +78,7 @@ void BKE_object_eval_local_transform(EvaluationContext *UNUSED(eval_ctx), /* Evaluate parent */ /* NOTE: based on solve_parenting(), but with the cruft stripped out */ -void BKE_object_eval_parent(EvaluationContext *UNUSED(eval_ctx), +void BKE_object_eval_parent(const EvaluationContext *UNUSED(eval_ctx), Scene *scene, Object *ob) { @@ -90,7 +88,7 @@ void BKE_object_eval_parent(EvaluationContext *UNUSED(eval_ctx), float tmat[4][4]; float locmat[4][4]; - DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob); /* get local matrix (but don't calculate it, as that was done already!) */ // XXX: redundant? @@ -112,14 +110,14 @@ void BKE_object_eval_parent(EvaluationContext *UNUSED(eval_ctx), } } -void BKE_object_eval_constraints(EvaluationContext *UNUSED(eval_ctx), +void BKE_object_eval_constraints(const EvaluationContext *eval_ctx, Scene *scene, Object *ob) { bConstraintOb *cob; float ctime = BKE_scene_frame_get(scene); - DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob); /* evaluate constraints stack */ /* TODO: split this into: @@ -131,22 +129,23 @@ void BKE_object_eval_constraints(EvaluationContext *UNUSED(eval_ctx), * */ cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT); - BKE_constraints_solve(&ob->constraints, cob, ctime); + BKE_constraints_solve(eval_ctx, &ob->constraints, cob, ctime); BKE_constraints_clear_evalob(cob); } -void BKE_object_eval_done(EvaluationContext *UNUSED(eval_ctx), Object *ob) +void BKE_object_eval_done(const EvaluationContext *UNUSED(eval_ctx), Object *ob) { - DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob); /* Set negative scale flag in object. */ if (is_negative_m4(ob->obmat)) ob->transflag |= OB_NEG_SCALE; else ob->transflag &= ~OB_NEG_SCALE; } -void BKE_object_handle_data_update(EvaluationContext *eval_ctx, - Scene *scene, - Object *ob) +void BKE_object_handle_data_update( + const EvaluationContext *eval_ctx, + Scene *scene, + Object *ob) { ID *data_id = (ID *)ob->data; AnimData *adt = BKE_animdata_from_id(data_id); @@ -183,10 +182,10 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx, } #endif if (em) { - makeDerivedMesh(scene, ob, em, data_mask, false); /* was CD_MASK_BAREMESH */ + makeDerivedMesh(eval_ctx, scene, ob, em, data_mask, false); /* was CD_MASK_BAREMESH */ } else { - makeDerivedMesh(scene, ob, NULL, data_mask, false); + makeDerivedMesh(eval_ctx, scene, ob, NULL, data_mask, false); } break; } @@ -198,7 +197,7 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx, } } else { - BKE_pose_where_is(scene, ob); + BKE_pose_where_is(eval_ctx, scene, ob); } break; @@ -209,11 +208,11 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx, case OB_CURVE: case OB_SURF: case OB_FONT: - BKE_displist_make_curveTypes(scene, ob, 0); + BKE_displist_make_curveTypes(eval_ctx, scene, ob, 0); break; case OB_LATTICE: - BKE_lattice_modifiers_calc(scene, ob); + BKE_lattice_modifiers_calc(eval_ctx, scene, ob); break; case OB_EMPTY: @@ -223,28 +222,6 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx, break; } - /* related materials */ - /* XXX: without depsgraph tagging, this will always need to be run, which will be slow! - * However, not doing anything (or trying to hack around this lack) is not an option - * anymore, especially due to Cycles [#31834] - */ - if (ob->totcol) { - int a; - if (ob->totcol != 0) { - BLI_mutex_lock(&material_lock); - for (a = 1; a <= ob->totcol; a++) { - Material *ma = give_current_material(ob, a); - if (ma) { - /* recursively update drivers for this material */ - material_drivers_update(scene, ma, ctime); - } - } - BLI_mutex_unlock(&material_lock); - } - } - else if (ob->type == OB_LAMP) - lamp_drivers_update(scene, ob->data, ctime); - /* particles */ if (ob != scene->obedit && ob->particlesystem.first) { ParticleSystem *tpsys, *psys; @@ -266,7 +243,7 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx, ob->transflag |= OB_DUPLIPARTS; } - particle_system_update(scene, ob, psys, (eval_ctx->mode == DAG_EVAL_RENDER)); + particle_system_update(eval_ctx, scene, ob, psys, (eval_ctx->mode == DAG_EVAL_RENDER)); psys = psys->next; } else if (psys->flag & PSYS_DELETE) { @@ -284,7 +261,7 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx, * the derivedmesh must be created before init_render_mesh, * since object_duplilist does dupliparticles before that */ CustomDataMask data_mask = CD_MASK_BAREMESH | CD_MASK_MFACE | CD_MASK_MTFACE | CD_MASK_MCOL; - dm = mesh_create_derived_render(scene, ob, data_mask); + dm = mesh_create_derived_render(eval_ctx, scene, ob, data_mask); dm->release(dm); for (psys = ob->particlesystem.first; psys; psys = psys->next) @@ -295,7 +272,7 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx, /* quick cache removed */ } -bool BKE_object_eval_proxy_copy(EvaluationContext *UNUSED(eval_ctx), +bool BKE_object_eval_proxy_copy(const EvaluationContext *UNUSED(eval_ctx), Object *object) { /* Handle proxy copy for target, */ @@ -319,35 +296,98 @@ bool BKE_object_eval_proxy_copy(EvaluationContext *UNUSED(eval_ctx), return false; } -void BKE_object_eval_uber_transform(EvaluationContext *eval_ctx, Object *object) +void BKE_object_eval_uber_transform(const EvaluationContext *eval_ctx, Object *object) { BKE_object_eval_proxy_copy(eval_ctx, object); - object->recalc &= ~(OB_RECALC_OB | OB_RECALC_TIME); - if (object->data == NULL) { - object->recalc &= ~OB_RECALC_DATA; - } } -void BKE_object_eval_uber_data(EvaluationContext *eval_ctx, +void BKE_object_eval_uber_data(const EvaluationContext *eval_ctx, Scene *scene, Object *ob) { - DEBUG_PRINT("%s on %s\n", __func__, ob->id.name); + DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob); BLI_assert(ob->type != OB_ARMATURE); BKE_object_handle_data_update(eval_ctx, scene, ob); - ob->recalc &= ~(OB_RECALC_DATA | OB_RECALC_TIME); + switch (ob->type) { + case OB_MESH: + BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL); + break; + case OB_LATTICE: + BKE_lattice_batch_cache_dirty(ob->data, BKE_LATTICE_BATCH_DIRTY_ALL); + break; + case OB_CURVE: + case OB_FONT: + case OB_SURF: + BKE_curve_batch_cache_dirty(ob->data, BKE_CURVE_BATCH_DIRTY_ALL); + break; + case OB_MBALL: + BKE_mball_batch_cache_dirty(ob->data, BKE_MBALL_BATCH_DIRTY_ALL); + break; + } + + if (DEG_depsgraph_use_copy_on_write()) { + if (ob->type == OB_MESH) { + /* Quick hack to convert evaluated derivedMesh to Mesh. */ + DerivedMesh *dm = ob->derivedFinal; + if (dm != NULL) { + Mesh *mesh = (Mesh *)ob->data; + Mesh *new_mesh = BKE_libblock_alloc_notest(ID_ME); + BKE_mesh_init(new_mesh); + /* Copy ID name so GS(new_mesh->id) works correct later on. */ + BLI_strncpy(new_mesh->id.name, mesh->id.name, sizeof(new_mesh->id.name)); + /* Copy materials so render engines can access them. */ + new_mesh->mat = MEM_dupallocN(mesh->mat); + new_mesh->totcol = mesh->totcol; + DM_to_mesh(dm, new_mesh, ob, CD_MASK_MESH, true); + new_mesh->edit_btmesh = mesh->edit_btmesh; + /* Store result mesh as derived_mesh of object. This way we have + * explicit way to query final object evaluated data and know for sure + * who owns the newly created mesh datablock. + */ + ob->mesh_evaluated = new_mesh; + /* TODO(sergey): This is kind of compatibility thing, so all render + * engines can use object->data for mesh data for display. This is + * something what we might want to change in the future. + */ + ob->data = new_mesh; + /* Special flags to help debugging. */ + new_mesh->id.tag |= LIB_TAG_COPY_ON_WRITE_EVAL; + /* Save some memory by throwing DerivedMesh away. */ + /* NOTE: Watch out, some tools might need it! + * So keep around for now.. + */ + /* Store original ID as a pointer in evaluated ID. + * This way we can restore original object data when we are freeing + * evaluated mesh. + */ + new_mesh->id.orig_id = &mesh->id; + } +#if 0 + if (ob->derivedFinal != NULL) { + ob->derivedFinal->needsFree = 1; + ob->derivedFinal->release(ob->derivedFinal); + ob->derivedFinal = NULL; + } + if (ob->derivedDeform != NULL) { + ob->derivedDeform->needsFree = 1; + ob->derivedDeform->release(ob->derivedDeform); + ob->derivedDeform = NULL; + } +#endif + } + } } -void BKE_object_eval_cloth(EvaluationContext *UNUSED(eval_ctx), +void BKE_object_eval_cloth(const EvaluationContext *UNUSED(eval_ctx), Scene *scene, Object *object) { - DEBUG_PRINT("%s on %s\n", __func__, object->id.name); + DEBUG_PRINT("%s on %s (%p)\n", __func__, object->id.name, object); BKE_ptcache_object_reset(scene, object, PTCACHE_RESET_DEPSGRAPH); } -void BKE_object_eval_transform_all(EvaluationContext *eval_ctx, +void BKE_object_eval_transform_all(const EvaluationContext *eval_ctx, Scene *scene, Object *object) { @@ -362,3 +402,55 @@ void BKE_object_eval_transform_all(EvaluationContext *eval_ctx, BKE_object_eval_uber_transform(eval_ctx, object); BKE_object_eval_done(eval_ctx, object); } + +void BKE_object_eval_update_shading(const EvaluationContext *UNUSED(eval_ctx), + Object *object) +{ + DEBUG_PRINT("%s on %s (%p)\n", __func__, object->id.name, object); + if (object->type == OB_MESH) { + BKE_mesh_batch_cache_dirty(object->data, BKE_MESH_BATCH_DIRTY_SHADING); + } +} + +void BKE_object_data_select_update(const EvaluationContext *UNUSED(eval_ctx), + struct ID *object_data) +{ + DEBUG_PRINT("%s on %s (%p)\n", __func__, object_data->name, object_data); + switch (GS(object_data->name)) { + case ID_ME: + BKE_mesh_batch_cache_dirty((Mesh *)object_data, + BKE_CURVE_BATCH_DIRTY_SELECT); + break; + case ID_CU: + BKE_curve_batch_cache_dirty((Curve *)object_data, + BKE_CURVE_BATCH_DIRTY_SELECT); + break; + case ID_LT: + BKE_lattice_batch_cache_dirty((struct Lattice *)object_data, + BKE_CURVE_BATCH_DIRTY_SELECT); + break; + default: + break; + } +} + +void BKE_object_eval_flush_base_flags(const EvaluationContext *UNUSED(eval_ctx), + Object *object, Base *base, bool is_from_set) +{ + DEBUG_PRINT("%s on %s (%p)\n", __func__, object->id.name, object); + + /* Make sure we have the base collection settings is already populated. + * This will fail when BKE_layer_eval_layer_collection_pre hasn't run yet. + * + * Which usually means a missing call to DEG_id_tag_update(id, DEG_TAG_BASE_FLAGS_UPDATE). + * Either of the entire scene, or of the newly added objects.*/ + BLI_assert(!BLI_listbase_is_empty(&base->collection_properties->data.group)); + + /* Copy flags and settings from base. */ + object->base_flag = base->flag; + if (is_from_set) { + object->base_flag |= BASE_FROM_SET; + object->base_flag &= ~(BASE_SELECTED | BASE_SELECTABLED); + } + object->base_collection_properties = base->collection_properties; +} diff --git a/source/blender/blenkernel/intern/outliner_treehash.c b/source/blender/blenkernel/intern/outliner_treehash.c index 4d97121e2a3..d9a602aa41e 100644 --- a/source/blender/blenkernel/intern/outliner_treehash.c +++ b/source/blender/blenkernel/intern/outliner_treehash.c @@ -27,6 +27,7 @@ */ #include <stdlib.h> +#include <string.h> #include "BLI_utildefines.h" #include "BLI_ghash.h" @@ -56,7 +57,7 @@ static TseGroup *tse_group_create(void) return tse_group; } -static void tse_group_add(TseGroup *tse_group, TreeStoreElem *elem) +static void tse_group_add_element(TseGroup *tse_group, TreeStoreElem *elem) { if (UNLIKELY(tse_group->size == tse_group->allocated)) { tse_group->allocated *= 2; @@ -66,6 +67,26 @@ static void tse_group_add(TseGroup *tse_group, TreeStoreElem *elem) tse_group->size++; } +static void tse_group_remove_element(TseGroup *tse_group, TreeStoreElem *elem) +{ + int min_allocated = MAX2(1, tse_group->allocated / 2); + BLI_assert(tse_group->allocated == 1 || (tse_group->allocated % 2) == 0); + + tse_group->size--; + BLI_assert(tse_group->size >= 0); + for (int i = 0; i < tse_group->size; i++) { + if (tse_group->elems[i] == elem) { + memcpy(tse_group->elems[i], tse_group->elems[i + 1], (tse_group->size - (i + 1)) * sizeof(TreeStoreElem *)); + break; + } + } + + if (UNLIKELY(tse_group->size > 0 && tse_group->size <= min_allocated)) { + tse_group->allocated = min_allocated; + tse_group->elems = MEM_reallocN(tse_group->elems, sizeof(TreeStoreElem *) * tse_group->allocated); + } +} + static void tse_group_free(TseGroup *tse_group) { MEM_freeN(tse_group->elems); @@ -140,7 +161,21 @@ void BKE_outliner_treehash_add_element(void *treehash, TreeStoreElem *elem) *val_p = tse_group_create(); } group = *val_p; - tse_group_add(group, elem); + tse_group_add_element(group, elem); +} + +void BKE_outliner_treehash_remove_element(void *treehash, TreeStoreElem *elem) +{ + TseGroup *group = BLI_ghash_lookup(treehash, elem); + + BLI_assert(group != NULL); + if (group->size <= 1) { + /* one element -> remove group completely */ + BLI_ghash_remove(treehash, elem, NULL, free_treehash_group); + } + else { + tse_group_remove_element(group, elem); + } } static TseGroup *BKE_outliner_treehash_lookup_group(GHash *th, short type, short nr, struct ID *id) diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c index 593c769e8e9..81943d470dc 100644 --- a/source/blender/blenkernel/intern/paint.c +++ b/source/blender/blenkernel/intern/paint.c @@ -41,6 +41,7 @@ #include "DNA_scene_types.h" #include "DNA_brush_types.h" #include "DNA_space_types.h" +#include "DNA_workspace_types.h" #include "BLI_bitmap.h" #include "BLI_utildefines.h" @@ -53,7 +54,6 @@ #include "BKE_main.h" #include "BKE_context.h" #include "BKE_crazyspace.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_image.h" #include "BKE_key.h" @@ -65,6 +65,8 @@ #include "BKE_pbvh.h" #include "BKE_subsurf.h" +#include "DEG_depsgraph.h" + #include "bmesh.h" const char PAINT_CURSOR_SCULPT[3] = {255, 100, 100}; @@ -74,27 +76,67 @@ const char PAINT_CURSOR_TEXTURE_PAINT[3] = {255, 255, 255}; static eOverlayControlFlags overlay_flags = 0; -void BKE_paint_invalidate_overlay_tex(Scene *scene, const Tex *tex) +/* Keep in sync with 'BKE_paint_get_active' */ +#define OB_MODE_HAS_PAINT_STRUCT(SEP) \ + OB_MODE_SCULPT SEP \ + OB_MODE_VERTEX_PAINT SEP \ + OB_MODE_WEIGHT_PAINT SEP \ + OB_MODE_TEXTURE_PAINT SEP \ + OB_MODE_EDIT + +#define COMMA , +static const eObjectMode ob_mode_has_paint_struct = OB_MODE_HAS_PAINT_STRUCT(|); +static const eObjectMode ob_mode_has_paint_struct_array[] = {OB_MODE_HAS_PAINT_STRUCT(COMMA)}; +#undef COMMA + +#define FOREACH_OB_MODE_PAINT_ITER_BEGIN(scene, view_layer, object_mode, p) \ +{ \ + eObjectMode object_mode_test = object_mode & ob_mode_has_paint_struct; \ + for (uint _i = 0; _i < ARRAY_SIZE(ob_mode_has_paint_struct_array) && object_mode_test; _i++) { \ + eObjectMode object_mode_single = ob_mode_has_paint_struct_array[_i]; \ + if (object_mode_test & object_mode_single) { \ + object_mode_test &= ~object_mode_single; \ + Paint *p = BKE_paint_get_active(scene, view_layer, object_mode_single); \ + { + +#define FOREACH_OB_MODE_PAINT_ITER_END \ + } \ + } \ + } \ +} ((void)0) + +void BKE_paint_invalidate_overlay_tex( + Scene *scene, ViewLayer *view_layer, const Tex *tex, eObjectMode object_mode) { - Paint *p = BKE_paint_get_active(scene); - Brush *br = p->brush; - - if (!br) - return; - - if (br->mtex.tex == tex) - overlay_flags |= PAINT_INVALID_OVERLAY_TEXTURE_PRIMARY; - if (br->mask_mtex.tex == tex) - overlay_flags |= PAINT_INVALID_OVERLAY_TEXTURE_SECONDARY; + FOREACH_OB_MODE_PAINT_ITER_BEGIN(scene, view_layer, object_mode, p) + { + Brush *br = p->brush; + if (br) { + if (br->mtex.tex == tex) { + overlay_flags |= PAINT_INVALID_OVERLAY_TEXTURE_PRIMARY; + } + if (br->mask_mtex.tex == tex) { + overlay_flags |= PAINT_INVALID_OVERLAY_TEXTURE_SECONDARY; + } + } + } + FOREACH_OB_MODE_PAINT_ITER_END; } -void BKE_paint_invalidate_cursor_overlay(Scene *scene, CurveMapping *curve) +void BKE_paint_invalidate_cursor_overlay( + Scene *scene, ViewLayer *view_layer, CurveMapping *curve, eObjectMode object_mode) { - Paint *p = BKE_paint_get_active(scene); - Brush *br = p->brush; - - if (br && br->curve == curve) - overlay_flags |= PAINT_INVALID_OVERLAY_CURVE; + FOREACH_OB_MODE_PAINT_ITER_BEGIN(scene, view_layer, object_mode, p) + { + Brush *br = p->brush; + if (br) { + if (br->curve == curve) { + overlay_flags |= PAINT_INVALID_OVERLAY_CURVE; + break; + } + } + } + FOREACH_OB_MODE_PAINT_ITER_END; } void BKE_paint_invalidate_overlay_all(void) @@ -156,13 +198,13 @@ Paint *BKE_paint_get_active_from_paintmode(Scene *sce, ePaintMode mode) return NULL; } -Paint *BKE_paint_get_active(Scene *sce) +Paint *BKE_paint_get_active(Scene *sce, ViewLayer *view_layer, const eObjectMode object_mode) { - if (sce) { + if (sce && view_layer) { ToolSettings *ts = sce->toolsettings; - if (sce->basact && sce->basact->object) { - switch (sce->basact->object->mode) { + if (view_layer->basact && view_layer->basact->object) { + switch (object_mode) { case OB_MODE_SCULPT: return &ts->sculpt->paint; case OB_MODE_VERTEX_PAINT: @@ -175,6 +217,8 @@ Paint *BKE_paint_get_active(Scene *sce) if (ts->use_uv_sculpt) return &ts->uvsculpt->paint; return &ts->imapaint.paint; + default: + break; } } @@ -188,17 +232,19 @@ Paint *BKE_paint_get_active(Scene *sce) Paint *BKE_paint_get_active_from_context(const bContext *C) { Scene *sce = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); SpaceImage *sima; - if (sce) { + if (sce && view_layer) { + const WorkSpace *workspace = CTX_wm_workspace(C); ToolSettings *ts = sce->toolsettings; Object *obact = NULL; - if (sce->basact && sce->basact->object) - obact = sce->basact->object; + if (view_layer->basact && view_layer->basact->object) + obact = view_layer->basact->object; if ((sima = CTX_wm_space_image(C)) != NULL) { - if (obact && obact->mode == OB_MODE_EDIT) { + if (obact && workspace->object_mode == OB_MODE_EDIT) { if (sima->mode == SI_MODE_PAINT) return &ts->imapaint.paint; else if (ts->use_uv_sculpt) @@ -209,7 +255,7 @@ Paint *BKE_paint_get_active_from_context(const bContext *C) } } else if (obact) { - switch (obact->mode) { + switch (workspace->object_mode) { case OB_MODE_SCULPT: return &ts->sculpt->paint; case OB_MODE_VERTEX_PAINT: @@ -238,17 +284,19 @@ Paint *BKE_paint_get_active_from_context(const bContext *C) ePaintMode BKE_paintmode_get_active_from_context(const bContext *C) { Scene *sce = CTX_data_scene(C); + ViewLayer *view_layer = CTX_data_view_layer(C); SpaceImage *sima; - if (sce) { + if (sce && view_layer) { + const WorkSpace *workspace = CTX_wm_workspace(C); ToolSettings *ts = sce->toolsettings; Object *obact = NULL; - if (sce->basact && sce->basact->object) - obact = sce->basact->object; + if (view_layer->basact && view_layer->basact->object) + obact = view_layer->basact->object; if ((sima = CTX_wm_space_image(C)) != NULL) { - if (obact && obact->mode == OB_MODE_EDIT) { + if (obact && workspace->object_mode == OB_MODE_EDIT) { if (sima->mode == SI_MODE_PAINT) return ePaintTexture2D; else if (ts->use_uv_sculpt) @@ -259,7 +307,7 @@ ePaintMode BKE_paintmode_get_active_from_context(const bContext *C) } } else if (obact) { - switch (obact->mode) { + switch (workspace->object_mode) { case OB_MODE_SCULPT: return ePaintSculpt; case OB_MODE_VERTEX_PAINT: @@ -450,24 +498,24 @@ bool BKE_palette_is_empty(const struct Palette *palette) /* are we in vertex paint or weight pain face select mode? */ -bool BKE_paint_select_face_test(Object *ob) +bool BKE_paint_select_face_test(Object *ob, eObjectMode object_mode) { return ( (ob != NULL) && (ob->type == OB_MESH) && (ob->data != NULL) && (((Mesh *)ob->data)->editflag & ME_EDIT_PAINT_FACE_SEL) && - (ob->mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) + (object_mode & (OB_MODE_VERTEX_PAINT | OB_MODE_WEIGHT_PAINT | OB_MODE_TEXTURE_PAINT)) ); } /* are we in weight paint vertex select mode? */ -bool BKE_paint_select_vert_test(Object *ob) +bool BKE_paint_select_vert_test(Object *ob, eObjectMode object_mode) { return ( (ob != NULL) && (ob->type == OB_MESH) && (ob->data != NULL) && (((Mesh *)ob->data)->editflag & ME_EDIT_PAINT_VERT_SEL) && - (ob->mode & OB_MODE_WEIGHT_PAINT || ob->mode & OB_MODE_VERTEX_PAINT) + (object_mode & OB_MODE_WEIGHT_PAINT || object_mode & OB_MODE_VERTEX_PAINT) ); } @@ -475,10 +523,10 @@ bool BKE_paint_select_vert_test(Object *ob) * used to check if selection is possible * (when we don't care if its face or vert) */ -bool BKE_paint_select_elem_test(Object *ob) +bool BKE_paint_select_elem_test(Object *ob, eObjectMode object_mode) { - return (BKE_paint_select_vert_test(ob) || - BKE_paint_select_face_test(ob)); + return (BKE_paint_select_vert_test(ob, object_mode) || + BKE_paint_select_face_test(ob, object_mode)); } void BKE_paint_cavity_curve_preset(Paint *p, int preset) @@ -733,7 +781,7 @@ void BKE_sculptsession_bm_to_me(Object *ob, bool reorder) sculptsession_bm_to_me_update_data_only(ob, reorder); /* ensure the objects DerivedMesh mesh doesn't hold onto arrays now realloc'd in the mesh [#34473] */ - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } } @@ -743,7 +791,7 @@ void BKE_sculptsession_bm_to_me_for_render(Object *object) if (object->sculpt->bm) { /* Ensure no points to old arrays are stored in DM * - * Apparently, we could not use DAG_id_tag_update + * Apparently, we could not use DEG_id_tag_update * here because this will lead to the while object * surface to disappear, so we'll release DM in place. */ @@ -781,7 +829,7 @@ void BKE_sculptsession_free(Object *ob) BM_log_free(ss->bm_log); if (dm && dm->getPBVH) - dm->getPBVH(NULL, dm); /* signal to clear */ + dm->getPBVH(NULL, dm, OB_MODE_OBJECT); /* signal to clear */ if (ss->texcache) MEM_freeN(ss->texcache); @@ -874,8 +922,9 @@ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob) /** * \param need_mask So the DerivedMesh thats returned has mask data */ -void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, - bool need_pmap, bool need_mask) +void BKE_sculpt_update_mesh_elements( + const EvaluationContext *eval_ctx, Scene *scene, Sculpt *sd, Object *ob, + bool need_pmap, bool need_mask) { DerivedMesh *dm; SculptSession *ss = ob->sculpt; @@ -914,10 +963,10 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, ss->kb = (mmd == NULL) ? BKE_keyblock_from_object(ob) : NULL; - dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); + dm = mesh_get_derived_final(eval_ctx, scene, ob, CD_MASK_BAREMESH); /* VWPaint require mesh info for loop lookup, so require sculpt mode here */ - if (mmd && ob->mode & OB_MODE_SCULPT) { + if (mmd && eval_ctx->object_mode & OB_MODE_SCULPT) { ss->multires = mmd; ss->totvert = dm->getNumVerts(dm); ss->totpoly = dm->getNumPolys(dm); @@ -935,7 +984,7 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, ss->vmask = CustomData_get_layer(&me->vdata, CD_PAINT_MASK); } - ss->pbvh = dm->getPBVH(ob, dm); + ss->pbvh = dm->getPBVH(ob, dm, eval_ctx->object_mode); ss->pmap = (need_pmap && dm->getPolyMap) ? dm->getPolyMap(ob, dm) : NULL; pbvh_show_diffuse_color_set(ss->pbvh, ss->show_diffuse_color); @@ -949,7 +998,7 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, 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_crazyspace_build_sculpt(eval_ctx, scene, ob, &ss->deform_imats, &ss->deform_cos); BKE_pbvh_apply_vertCos(ss->pbvh, ss->deform_cos); for (a = 0; a < me->totvert; ++a) { @@ -985,6 +1034,9 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob, } } } + + /* 2.8x - avoid full mesh update! */ + BKE_mesh_batch_cache_dirty(me, BKE_MESH_BATCH_DIRTY_SCULPT_COORDS); } int BKE_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd) diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 26e7562590d..d227ea55816 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -78,7 +78,6 @@ #include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_library_remap.h" -#include "BKE_depsgraph.h" #include "BKE_modifier.h" #include "BKE_mesh.h" #include "BKE_cdderivedmesh.h" @@ -86,6 +85,9 @@ #include "BKE_scene.h" #include "BKE_deform.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "RE_render_ext.h" unsigned int PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT]; @@ -250,7 +252,7 @@ struct LatticeDeformData *psys_create_lattice_deform_data(ParticleSimulationData { struct LatticeDeformData *lattice_deform_data = NULL; - if (psys_in_edit_mode(sim->scene, sim->psys) == 0) { + if (psys_in_edit_mode(sim->eval_ctx, sim->eval_ctx->view_layer, sim->psys) == 0) { Object *lattice = NULL; ModifierData *md = (ModifierData *)psys_get_modifier(sim->ob, sim->psys); int mode = G.is_rendering ? eModifierMode_Render : eModifierMode_Realtime; @@ -286,10 +288,16 @@ void psys_enable_all(Object *ob) for (; psys; psys = psys->next) psys->flag &= ~PSYS_DISABLED; } -bool psys_in_edit_mode(Scene *scene, ParticleSystem *psys) + +bool psys_in_edit_mode(const EvaluationContext *eval_ctx, ViewLayer *view_layer, ParticleSystem *psys) { - return (scene->basact && (scene->basact->object->mode & OB_MODE_PARTICLE_EDIT) && psys == psys_get_current((scene->basact)->object) && (psys->edit || psys->pointcache->edit) && !psys->renderdata); + return (view_layer->basact && + (eval_ctx->object_mode & OB_MODE_PARTICLE_EDIT) && + psys == psys_get_current((view_layer->basact)->object) && + (psys->edit || psys->pointcache->edit) && + !psys->renderdata); } + bool psys_check_enabled(Object *ob, ParticleSystem *psys, const bool use_render_params) { ParticleSystemModifierData *psmd; @@ -319,18 +327,17 @@ bool psys_check_edited(ParticleSystem *psys) void psys_check_group_weights(ParticleSettings *part) { ParticleDupliWeight *dw, *tdw; - GroupObject *go; int current = 0; - if (part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first) { + if (part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->view_layer->object_bases.first) { /* First try to find NULL objects from their index, * and remove all weights that don't have an object in the group. */ dw = part->dupliweights.first; while (dw) { if (dw->ob == NULL || !BKE_group_object_exists(part->dup_group, dw->ob)) { - go = (GroupObject *)BLI_findlink(&part->dup_group->gobject, dw->index); - if (go) { - dw->ob = go->ob; + Base *base = BLI_findlink(&part->dup_group->view_layer->object_bases, dw->index); + if (base != NULL) { + dw->ob = base->object; } else { tdw = dw->next; @@ -344,21 +351,21 @@ void psys_check_group_weights(ParticleSettings *part) } /* then add objects in the group to new list */ - go = part->dup_group->gobject.first; - while (go) { + FOREACH_GROUP_OBJECT(part->dup_group, object) + { dw = part->dupliweights.first; - while (dw && dw->ob != go->ob) + while (dw && dw->ob != object) { dw = dw->next; - + } + if (!dw) { dw = MEM_callocN(sizeof(ParticleDupliWeight), "ParticleDupliWeight"); - dw->ob = go->ob; + dw->ob = object; dw->count = 1; BLI_addtail(&part->dupliweights, dw); } - - go = go->next; } + FOREACH_GROUP_OBJECT_END dw = part->dupliweights.first; for (; dw; dw = dw->next) { @@ -607,6 +614,8 @@ void psys_free(Object *ob, ParticleSystem *psys) MEM_freeN(psys->pdd); } + BKE_particle_batch_cache_free(psys); + MEM_freeN(psys); } } @@ -1843,7 +1852,7 @@ void precalc_guides(ParticleSimulationData *sim, ListBase *effectors) } } -int do_guides(ParticleSettings *part, ListBase *effectors, ParticleKey *state, int index, float time) +int do_guides(const EvaluationContext *eval_ctx, ParticleSettings *part, ListBase *effectors, ParticleKey *state, int index, float time) { CurveMapping *clumpcurve = (part->child_flag & PART_CHILD_USE_CLUMP_CURVE) ? part->clumpcurve : NULL; CurveMapping *roughcurve = (part->child_flag & PART_CHILD_USE_ROUGH_CURVE) ? part->roughcurve : NULL; @@ -1906,7 +1915,7 @@ int do_guides(ParticleSettings *part, ListBase *effectors, ParticleKey *state, i /* curve taper */ if (cu->taperobj) - mul_v3_fl(vec_to_point, BKE_displist_calc_taper(eff->scene, cu->taperobj, (int)(data->strength * guidetime * 100.0f), 100)); + mul_v3_fl(vec_to_point, BKE_displist_calc_taper(eval_ctx, eff->scene, cu->taperobj, (int)(data->strength * guidetime * 100.0f), 100)); else { /* curve size*/ if (cu->flag & CU_PATH_RADIUS) { @@ -2089,7 +2098,7 @@ static bool psys_thread_context_init_path( psys_thread_context_init(ctx, sim); /*---start figuring out what is actually wanted---*/ - if (psys_in_edit_mode(scene, psys)) { + if (psys_in_edit_mode(sim->eval_ctx, sim->eval_ctx->view_layer, psys)) { ParticleEditSettings *pset = &scene->toolsettings->particle; if ((psys->renderdata == 0 && use_render_params == 0) && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0) @@ -2178,7 +2187,7 @@ static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cp ParticleSystem *psys = ctx->sim.psys; ParticleSettings *part = psys->part; ParticleCacheKey **cache = psys->childcache; - ParticleCacheKey **pcache = psys_in_edit_mode(ctx->sim.scene, psys) && psys->edit ? psys->edit->pathcache : psys->pathcache; + ParticleCacheKey **pcache = psys_in_edit_mode(ctx->sim.eval_ctx, ctx->sim.eval_ctx->view_layer, psys) && psys->edit ? psys->edit->pathcache : psys->pathcache; ParticleCacheKey *child, *key[4]; ParticleTexture ptex; float *cpa_fuv = 0, *par_rot = 0, rot[4]; @@ -2587,7 +2596,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re if ((psys->flag & PSYS_HAIR_DONE || psys->flag & PSYS_KEYED || psys->pointcache) == 0) return; - if (psys_in_edit_mode(sim->scene, psys)) + if (psys_in_edit_mode(sim->eval_ctx, sim->eval_ctx->view_layer, psys)) if (psys->renderdata == 0 && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0) return; @@ -2707,7 +2716,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re if (sim->psys->effectors && (psys->part->flag & PART_CHILD_EFFECT) == 0) { for (k = 0, ca = cache[p]; k <= segments; k++, ca++) /* ca is safe to cast, since only co and vel are used */ - do_guides(sim->psys->part, sim->psys->effectors, (ParticleKey *)ca, p, (float)k / (float)segments); + do_guides(sim->eval_ctx, sim->psys->part, sim->psys->effectors, (ParticleKey *)ca, p, (float)k / (float)segments); } /* lattices have to be calculated separately to avoid mixups between effector calculations */ @@ -2755,7 +2764,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re if (vg_length) MEM_freeN(vg_length); } -void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cfra, const bool use_render_params) +void psys_cache_edit_paths(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, PTCacheEdit *edit, float cfra, const bool use_render_params) { ParticleCacheKey *ca, **cache = edit->pathcache; ParticleEditSettings *pset = &scene->toolsettings->particle; @@ -2956,6 +2965,7 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf if (psys) { ParticleSimulationData sim = {0}; + sim.eval_ctx = eval_ctx; sim.scene = scene; sim.ob = ob; sim.psys = psys; @@ -3170,8 +3180,8 @@ ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *n psys->flag = PSYS_CURRENT; psys->cfra = BKE_scene_frame_get_from_ctime(scene, CFRA + 1); - DAG_relations_tag_update(G.main); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_relations_tag_update(G.main); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); return md; } @@ -3213,11 +3223,9 @@ void object_remove_particle_system(Scene *UNUSED(scene), Object *ob) if (ob->particlesystem.first) ((ParticleSystem *) ob->particlesystem.first)->flag |= PSYS_CURRENT; - else - ob->mode &= ~OB_MODE_PARTICLE_EDIT; - DAG_relations_tag_update(G.main); - DAG_id_tag_update(&ob->id, OB_RECALC_DATA); + DEG_relations_tag_update(G.main); + DEG_id_tag_update(&ob->id, OB_RECALC_DATA); } static void default_particle_settings(ParticleSettings *part) @@ -3280,7 +3288,7 @@ static void default_particle_settings(ParticleSettings *part) part->clength = 1.0f; part->clength_thres = 0.0f; - part->draw = PART_DRAW_EMITTER; + part->draw = 0; part->draw_line[0] = 0.5; part->path_start = 0.0f; part->path_end = 1.0f; @@ -3302,6 +3310,7 @@ static void default_particle_settings(ParticleSettings *part) part->omat = 1; part->use_modifier_stack = false; + part->draw_size = 0.1f; } @@ -3778,7 +3787,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey * pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE); /* pind.dm disabled in editmode means we don't get effectors taken into * account when subdividing for instance */ - pind.dm = psys_in_edit_mode(sim->scene, psys) ? NULL : psys->hair_out_dm; + pind.dm = psys_in_edit_mode(sim->eval_ctx, sim->eval_ctx->view_layer, psys) ? NULL : psys->hair_out_dm; init_particle_interpolation(sim->ob, psys, pa, &pind); do_particle_interpolation(psys, p, pa, t, &pind, state); @@ -3793,7 +3802,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey * mul_mat3_m4_v3(hairmat, state->vel); if (sim->psys->effectors && (part->flag & PART_CHILD_GUIDE) == 0) { - do_guides(sim->psys->part, sim->psys->effectors, state, p, state->time); + do_guides(sim->eval_ctx, sim->psys->part, sim->psys->effectors, state, p, state->time); /* TODO: proper velocity handling */ } @@ -4320,9 +4329,10 @@ void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3] madd_v3_v3fl(center, yvec, bb->offset[1]); } -void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys) +void psys_apply_hair_lattice(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ParticleSystem *psys) { ParticleSimulationData sim = {0}; + sim.eval_ctx = eval_ctx; sim.scene = scene; sim.ob = ob; sim.psys = psys; @@ -4355,3 +4365,22 @@ void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys) psys->flag |= PSYS_EDITED; } } + + + +/* Draw Engine */ +void (*BKE_particle_batch_cache_dirty_cb)(ParticleSystem *psys, int mode) = NULL; +void (*BKE_particle_batch_cache_free_cb)(ParticleSystem *psys) = NULL; + +void BKE_particle_batch_cache_dirty(ParticleSystem *psys, int mode) +{ + if (psys->batch_cache) { + BKE_particle_batch_cache_dirty_cb(psys, mode); + } +} +void BKE_particle_batch_cache_free(ParticleSystem *psys) +{ + if (psys->batch_cache) { + BKE_particle_batch_cache_free_cb(psys); + } +} diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c index bfcda89a635..d2ad05c20b7 100644 --- a/source/blender/blenkernel/intern/particle_child.c +++ b/source/blender/blenkernel/intern/particle_child.c @@ -702,7 +702,7 @@ void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim, if (part->flag & PART_CHILD_EFFECT) /* state is safe to cast, since only co and vel are used */ - guided = do_guides(sim->psys->part, sim->psys->effectors, (ParticleKey *)state, cpa->parent, t); + guided = do_guides(sim->eval_ctx, sim->psys->part, sim->psys->effectors, (ParticleKey *)state, cpa->parent, t); if (guided == 0) { float orco_offset[3]; diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c index 9a7980827ad..ff8a638089f 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -312,19 +312,16 @@ static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys) static void hammersley_create(float *out, int n, int seed, float amount) { RNG *rng; - double p, t, offs[2]; - int k, kk; + + double offs[2], t; rng = BLI_rng_new(31415926 + n + seed); offs[0] = BLI_rng_get_double(rng) + (double)amount; offs[1] = BLI_rng_get_double(rng) + (double)amount; BLI_rng_free(rng); - for (k = 0; k < n; k++) { - t = 0; - for (p = 0.5, kk = k; kk; p *= 0.5, kk >>= 1) - if (kk & 1) /* kk mod 2 = 1 */ - t += p; + for (int k = 0; k < n; k++) { + BLI_hammersley_1D(k, &t); out[2*k + 0] = fmod((double)k/(double)n + offs[0], 1.0); out[2*k + 1] = fmod(t + offs[1], 1.0); diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index dfc732dcb74..d187a009a2d 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -78,6 +78,7 @@ #include "BKE_particle.h" #include "BKE_global.h" +#include "BKE_collection.h" #include "BKE_DerivedMesh.h" #include "BKE_object.h" #include "BKE_material.h" @@ -88,7 +89,8 @@ #include "BKE_modifier.h" #include "BKE_scene.h" #include "BKE_bvhutils.h" -#include "BKE_depsgraph.h" + +#include "DEG_depsgraph.h" #include "PIL_time.h" @@ -980,14 +982,14 @@ void psys_get_birth_coords(ParticleSimulationData *sim, ParticleData *pa, Partic } /* recursively evaluate emitter parent anim at cfra */ -static void evaluate_emitter_anim(Scene *scene, Object *ob, float cfra) +static void evaluate_emitter_anim(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float cfra) { if (ob->parent) - evaluate_emitter_anim(scene, ob->parent, cfra); + evaluate_emitter_anim(eval_ctx, scene, ob->parent, cfra); /* we have to force RECALC_ANIM here since where_is_objec_time only does drivers */ BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, cfra, ADT_RECALC_ANIM); - BKE_object_where_is_calc_time(scene, ob, cfra); + BKE_object_where_is_calc_time(eval_ctx, scene, ob, cfra); } /* sets particle to the emitter surface with initial velocity & rotation */ @@ -1001,7 +1003,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime, /* get precise emitter matrix if particle is born */ if (part->type != PART_HAIR && dtime > 0.f && pa->time < cfra && pa->time >= sim->psys->cfra) { - evaluate_emitter_anim(sim->scene, sim->ob, pa->time); + evaluate_emitter_anim(sim->eval_ctx, sim->scene, sim->ob, pa->time); psys->flag |= PSYS_OB_ANIM_RESTORE; } @@ -1133,7 +1135,8 @@ static void set_keyed_keys(ParticleSimulationData *sim) int totpart = psys->totpart, k, totkeys = psys->totkeyed; int keyed_flag = 0; - ksim.scene= sim->scene; + ksim.eval_ctx = sim->eval_ctx; + ksim.scene = sim->scene; /* no proper targets so let's clear and bail out */ if (psys->totkeyed==0) { @@ -1294,7 +1297,7 @@ void psys_update_particle_tree(ParticleSystem *psys, float cfra) static void psys_update_effectors(ParticleSimulationData *sim) { pdEndEffectors(&sim->psys->effectors); - sim->psys->effectors = pdInitEffectors(sim->scene, sim->ob, sim->psys, + sim->psys->effectors = pdInitEffectors(sim->eval_ctx, sim->scene, sim->ob, sim->psys, sim->psys->part->effector_weights, true); precalc_guides(sim, sim->psys->effectors); } @@ -2115,7 +2118,7 @@ static void basic_integrate(ParticleSimulationData *sim, int p, float dfra, floa tkey.time=pa->state.time; if (part->type != PART_HAIR) { - if (do_guides(sim->psys->part, sim->psys->effectors, &tkey, p, time)) { + if (do_guides(sim->eval_ctx, sim->psys->part, sim->psys->effectors, &tkey, p, time)) { copy_v3_v3(pa->state.co,tkey.co); /* guides don't produce valid velocity */ sub_v3_v3v3(pa->state.vel, tkey.co, pa->prev_state.co); @@ -2896,14 +2899,16 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons ParticleSystem *psys = sim->psys; ParticleSettings *part = psys->part; ParticleEditSettings *pset = &sim->scene->toolsettings->particle; - Base *base; int distr=0, alloc=0, skip=0; if ((psys->part->childtype && psys->totchild != psys_get_tot_child(sim->scene, psys)) || psys->recalc&PSYS_RECALC_RESET) alloc=1; - if (alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (sim->ob && sim->ob->mode & OB_MODE_WEIGHT_PAINT))) + if (alloc || psys->recalc&PSYS_RECALC_CHILD || + (psys->vgroup[PSYS_VG_DENSITY] && (sim->ob && sim->eval_ctx->object_mode & OB_MODE_WEIGHT_PAINT))) + { distr=1; + } if (distr) { if (alloc) @@ -2931,7 +2936,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons skip = 1; /* draw visualization */ else if (psys->pointcache->flag & PTCACHE_BAKING) skip = 1; /* no need to cache paths while baking dynamics */ - else if (psys_in_edit_mode(sim->scene, psys)) { + else if (psys_in_edit_mode(sim->eval_ctx, sim->eval_ctx->view_layer, psys)) { if ((pset->flag & PE_DRAW_PART)==0) skip = 1; else if (part->childtype==0 && (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED)==0) @@ -2941,8 +2946,9 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons /* particle instance modifier with "path" option need cached paths even if particle system doesn't */ - for (base = sim->scene->base.first; base; base= base->next) { - ModifierData *md = modifiers_findByType(base->object, eModifierType_ParticleInstance); + FOREACH_SCENE_OBJECT(sim->scene, ob) + { + ModifierData *md = modifiers_findByType(ob, eModifierType_ParticleInstance); if (md) { ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md; if (pimd->flag & eParticleInstanceFlag_Path && pimd->ob == sim->ob && pimd->psys == (psys - (ParticleSystem*)sim->ob->particlesystem.first)) { @@ -2951,6 +2957,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons } } } + FOREACH_SCENE_OBJECT_END if (!skip) { psys_cache_paths(sim, cfra, use_render_params); @@ -3196,7 +3203,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim) psys->hair_out_dm = CDDM_copy(psys->hair_in_dm); psys->hair_out_dm->getVertCos(psys->hair_out_dm, deformedVerts); - clothModifier_do(psys->clmd, sim->scene, sim->ob, psys->hair_in_dm, deformedVerts); + clothModifier_do(psys->clmd, sim->eval_ctx, sim->scene, sim->ob, psys->hair_in_dm, deformedVerts); CDDM_apply_vert_coords(psys->hair_out_dm, deformedVerts); @@ -4196,7 +4203,7 @@ static int hair_needs_recalc(ParticleSystem *psys) /* main particle update call, checks that things are ok on the large scale and * then advances in to actual particle calculations depending on particle type */ -void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys, const bool use_render_params) +void particle_system_update(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, ParticleSystem *psys, const bool use_render_params) { ParticleSimulationData sim= {0}; ParticleSettings *part = psys->part; @@ -4210,10 +4217,11 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys, cons cfra= BKE_scene_frame_get(scene); - sim.scene= scene; - sim.ob= ob; - sim.psys= psys; - sim.psmd= psys_get_modifier(ob, psys); + sim.eval_ctx = eval_ctx; + sim.scene = scene; + sim.ob = ob; + sim.psys = psys; + sim.psmd = psys_get_modifier(ob, psys); /* system was already updated from modifier stack */ if (sim.psmd->flag & eParticleSystemFlag_psys_updated) { @@ -4356,7 +4364,7 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys, cons /* make sure emitter is left at correct time (particle emission can change this) */ if (psys->flag & PSYS_OB_ANIM_RESTORE) { - evaluate_emitter_anim(scene, ob, cfra); + evaluate_emitter_anim(eval_ctx, scene, ob, cfra); psys->flag &= ~PSYS_OB_ANIM_RESTORE; } @@ -4366,6 +4374,8 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys, cons /* save matrix for duplicators, at rendertime the actual dupliobject's matrix is used so don't update! */ if (psys->renderdata==0) invert_m4_m4(psys->imat, ob->obmat); + + BKE_particle_batch_cache_dirty(psys, BKE_PARTICLE_BATCH_DIRTY_ALL); } /* ID looper */ @@ -4396,12 +4406,30 @@ void BKE_particlesystem_id_loop(ParticleSystem *psys, ParticleSystemIDFunc func, /* **** Depsgraph evaluation **** */ -void BKE_particle_system_eval_init(EvaluationContext *UNUSED(eval_ctx), +void BKE_particle_system_settings_eval(const struct EvaluationContext *UNUSED(eval_ctx), + ParticleSystem *psys) +{ + if (G.debug & G_DEBUG_DEPSGRAPH) { + printf("%s on %s (%p)\n", __func__, psys->name, psys); + } + psys->recalc |= psys->part->recalc; +} + +void BKE_particle_system_settings_recalc_clear(struct EvaluationContext *UNUSED(eval_ctx), + ParticleSettings *particle_settings) +{ + if (G.debug & G_DEBUG_DEPSGRAPH) { + printf("%s on %s (%p)\n", __func__, particle_settings->id.name, particle_settings); + } + particle_settings->recalc = 0; +} + +void BKE_particle_system_eval_init(const struct EvaluationContext *UNUSED(eval_ctx), Scene *scene, Object *ob) { if (G.debug & G_DEBUG_DEPSGRAPH) { - printf("%s on %s\n", __func__, ob->id.name); + printf("%s on %s (%p)\n", __func__, ob->id.name, ob); } BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH); } diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c index d926c96c0d8..63f2c7e5452 100644 --- a/source/blender/blenkernel/intern/pbvh.c +++ b/source/blender/blenkernel/intern/pbvh.c @@ -41,6 +41,7 @@ #include "BKE_paint.h" #include "GPU_buffers.h" +#include "GPU_immediate.h" #include "bmesh.h" @@ -1187,15 +1188,16 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode) void BKE_pbvh_draw_BB(PBVH *bvh) { - GPU_pbvh_BB_draw_init(); + unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT); + immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR); for (int a = 0; a < bvh->totnode; a++) { PBVHNode *node = &bvh->nodes[a]; - GPU_pbvh_BB_draw(node->vb.bmin, node->vb.bmax, ((node->flag & PBVH_Leaf) != 0)); + GPU_pbvh_BB_draw(node->vb.bmin, node->vb.bmax, ((node->flag & PBVH_Leaf) != 0), pos); } - GPU_pbvh_BB_draw_end(); + immUnbindProgram(); } static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag) @@ -2016,24 +2018,6 @@ void BKE_pbvh_node_draw(PBVHNode *node, void *data_v) { PBVHNodeDrawData *data = data_v; -#if 0 - /* XXX: Just some quick code to show leaf nodes in different colors */ - float col[3]; - float spec[3] = {0.0f, 0.0f, 0.0f}; - - if (0) { //is_partial) { - col[0] = (rand() / (float)RAND_MAX); col[1] = col[2] = 0.6; - } - else { - srand((long long)node); - for (int i = 0; i < 3; ++i) - col[i] = (rand() / (float)RAND_MAX) * 0.3 + 0.7; - } - - GPU_basic_shader_colors(col, spec, 0, 1.0f); - glColor3f(1, 0, 0); -#endif - if (!(node->flag & PBVH_FullyHidden)) { GPU_pbvh_buffers_draw(node->draw_buffers, data->setMaterial, @@ -2152,6 +2136,67 @@ void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*fnors)[3], BKE_pbvh_draw_BB(bvh); } +struct PBVHNodeDrawCallbackData { + + void (*draw_fn)(void *user_data, Gwn_Batch *batch); + void *user_data; + bool fast; +}; + +static void pbvh_node_draw_cb(PBVHNode *node, void *data_v) +{ + struct PBVHNodeDrawCallbackData *data = data_v; + + if (!(node->flag & PBVH_FullyHidden)) { + Gwn_Batch *triangles = GPU_pbvh_buffers_batch_get(node->draw_buffers, data->fast); + if (triangles != NULL) { + data->draw_fn(data->user_data, triangles); + } + } +} + +/** + * Version of #BKE_pbvh_draw that runs a callback. + */ +void BKE_pbvh_draw_cb( + PBVH *bvh, float (*planes)[4], float (*fnors)[3], bool fast, + void (*draw_fn)(void *user_data, Gwn_Batch *batch), void *user_data) +{ + struct PBVHNodeDrawCallbackData draw_data = { + .fast = fast, + .draw_fn = draw_fn, + .user_data = user_data, + }; + PBVHNode **nodes; + int totnode; + + for (int a = 0; a < bvh->totnode; a++) + pbvh_node_check_diffuse_changed(bvh, &bvh->nodes[a]); + + BKE_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(PBVH_UpdateNormals | PBVH_UpdateDrawBuffers), + &nodes, &totnode); + + pbvh_update_normals(bvh, nodes, totnode, fnors); + pbvh_update_draw_buffers(bvh, nodes, totnode); + + if (nodes) MEM_freeN(nodes); + + if (planes) { + BKE_pbvh_search_callback( + bvh, BKE_pbvh_node_planes_contain_AABB, + planes, pbvh_node_draw_cb, &draw_data); + } + else { + BKE_pbvh_search_callback( + bvh, NULL, + NULL, pbvh_node_draw_cb, &draw_data); + } +#if 0 + if (G.debug_value == 14) + pbvh_draw_BB(bvh); +#endif +} + void BKE_pbvh_grids_update(PBVH *bvh, CCGElem **grids, void **gridfaces, DMFlagMat *flagmats, BLI_bitmap **grid_hidden) { @@ -2361,24 +2406,24 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, vi->vmask = CustomData_get_layer(bvh->vdata, CD_PAINT_MASK); } -void pbvh_show_diffuse_color_set(PBVH *bvh, bool show_diffuse_color) +bool pbvh_has_mask(PBVH *bvh) { - bool has_mask = false; - switch (bvh->type) { case PBVH_GRIDS: - has_mask = (bvh->gridkey.has_mask != 0); - break; + return (bvh->gridkey.has_mask != 0); case PBVH_FACES: - has_mask = (bvh->vdata && CustomData_get_layer(bvh->vdata, - CD_PAINT_MASK)); - break; + return (bvh->vdata && CustomData_get_layer(bvh->vdata, + CD_PAINT_MASK)); case PBVH_BMESH: - has_mask = (bvh->bm && (CustomData_get_offset(&bvh->bm->vdata, CD_PAINT_MASK) != -1)); - break; + return (bvh->bm && (CustomData_get_offset(&bvh->bm->vdata, CD_PAINT_MASK) != -1)); } - bvh->show_diffuse_color = !has_mask || show_diffuse_color; + return false; +} + +void pbvh_show_diffuse_color_set(PBVH *bvh, bool show_diffuse_color) +{ + bvh->show_diffuse_color = !pbvh_has_mask(bvh) || show_diffuse_color; } void pbvh_show_mask_set(PBVH *bvh, bool show_mask) diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c index dc1c0da4401..169b1b10024 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -3509,13 +3509,14 @@ PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, const ListBase *ptcach * every user action changing stuff, and then it runs a complete bake??? (ton) */ /* Baking */ -void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene) +void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene, ViewLayer *view_layer) { PTCacheBaker baker; memset(&baker, 0, sizeof(baker)); baker.main = bmain; baker.scene = scene; + baker.view_layer = view_layer; baker.bake = 0; baker.render = 0; baker.anim_init = 0; @@ -3541,6 +3542,8 @@ void BKE_ptcache_bake(PTCacheBaker *baker) { Main *bmain = baker->main; Scene *scene = baker->scene; + ViewLayer *view_layer = baker->view_layer; + struct Depsgraph *depsgraph = baker->depsgraph; Scene *sce_iter; /* SETLOOPER macro only */ Base *base; ListBase pidlist; @@ -3603,7 +3606,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker) } } else { - for (SETLOOPER(scene, sce_iter, base)) { + for (SETLOOPER_VIEW_LAYER(scene, view_layer, sce_iter, base)) { /* cache/bake everything in the scene */ BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR); @@ -3659,7 +3662,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker) stime = ptime = PIL_check_seconds_timer(); for (int fr = CFRA; fr <= endframe; fr += baker->quick_step, CFRA = fr) { - BKE_scene_update_for_newframe(G.main->eval_ctx, bmain, scene, scene->lay); + BKE_scene_graph_update_for_newframe(G.main->eval_ctx, depsgraph, bmain, scene, view_layer); if (baker->update_progress) { float progress = ((float)(CFRA - startframe)/(float)(endframe - startframe)); @@ -3714,7 +3717,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker) } } else { - for (SETLOOPER(scene, sce_iter, base)) { + for (SETLOOPER_VIEW_LAYER(scene, view_layer, sce_iter, base)) { BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR); for (pid=pidlist.first; pid; pid=pid->next) { @@ -3745,7 +3748,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker) CFRA = cfrao; if (bake) { /* already on cfra unless baking */ - BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay); + BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer); } /* TODO: call redraw all windows somehow */ diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index 39b0668f0b9..4a52c4f7d14 100644 --- a/source/blender/blenkernel/intern/rigidbody.c +++ b/source/blender/blenkernel/intern/rigidbody.c @@ -55,9 +55,9 @@ #include "DNA_scene_types.h" #include "BKE_cdderivedmesh.h" -#include "BKE_depsgraph.h" #include "BKE_effect.h" #include "BKE_global.h" +#include "BKE_group.h" #include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_mesh.h" @@ -91,26 +91,30 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw) if (rbw->physics_world) { /* free physics references, we assume that all physics objects in will have been added to the world */ - GroupObject *go; if (rbw->constraints) { - for (go = rbw->constraints->gobject.first; go; go = go->next) { - if (go->ob && go->ob->rigidbody_constraint) { - RigidBodyCon *rbc = go->ob->rigidbody_constraint; - - if (rbc->physics_constraint) + FOREACH_GROUP_OBJECT(rbw->constraints, object) + { + if (object->rigidbody_constraint) { + RigidBodyCon *rbc = object->rigidbody_constraint; + if (rbc->physics_constraint) { RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint); + } } } + FOREACH_GROUP_OBJECT_END } - if (rbw->group) { - for (go = rbw->group->gobject.first; go; go = go->next) { - if (go->ob && go->ob->rigidbody_object) { - RigidBodyOb *rbo = go->ob->rigidbody_object; - if (rbo->physics_object) + if (rbw->group) { + FOREACH_GROUP_OBJECT(rbw->group, object) + { + if (object->rigidbody_object) { + RigidBodyOb *rbo = object->rigidbody_object; + if (rbo->physics_object) { RB_dworld_remove_body(rbw->physics_world, rbo->physics_object); + } } } + FOREACH_GROUP_OBJECT_END } /* free dynamics world */ RB_dworld_delete(rbw->physics_world); @@ -1125,7 +1129,6 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob) RigidBodyWorld *rbw = scene->rigidbody_world; RigidBodyOb *rbo = ob->rigidbody_object; RigidBodyCon *rbc; - GroupObject *go; int i; if (rbw) { @@ -1145,8 +1148,8 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob) /* remove object from rigid body constraints */ if (rbw->constraints) { - for (go = rbw->constraints->gobject.first; go; go = go->next) { - Object *obt = go->ob; + FOREACH_GROUP_OBJECT(rbw->constraints, obt) + { if (obt && obt->rigidbody_constraint) { rbc = obt->rigidbody_constraint; if (ELEM(ob, rbc->ob1, rbc->ob2)) { @@ -1154,6 +1157,7 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob) } } } + FOREACH_GROUP_OBJECT_END } } @@ -1187,20 +1191,22 @@ void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob) /* Update object array and rigid body count so they're in sync with the rigid body group */ static void rigidbody_update_ob_array(RigidBodyWorld *rbw) { - GroupObject *go; int i, n; - n = BLI_listbase_count(&rbw->group->gobject); + n = BLI_listbase_count(&rbw->group->view_layer->object_bases); if (rbw->numbodies != n) { rbw->numbodies = n; rbw->objects = realloc(rbw->objects, sizeof(Object *) * rbw->numbodies); } - for (go = rbw->group->gobject.first, i = 0; go; go = go->next, i++) { - Object *ob = go->ob; - rbw->objects[i] = ob; + i = 0; + FOREACH_GROUP_OBJECT(rbw->group, object) + { + rbw->objects[i] = object; + i++; } + FOREACH_GROUP_OBJECT_END } static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw) @@ -1223,7 +1229,7 @@ static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw) rigidbody_update_ob_array(rbw); } -static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *ob, RigidBodyOb *rbo) +static void rigidbody_update_sim_ob(const struct EvaluationContext *eval_ctx, Scene *scene, RigidBodyWorld *rbw, Object *ob, RigidBodyOb *rbo) { float loc[3]; float rot[4]; @@ -1271,7 +1277,7 @@ static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *o ListBase *effectors; /* get effectors present in the group specified by effector_weights */ - effectors = pdInitEffectors(scene, ob, NULL, effector_weights, true); + effectors = pdInitEffectors(eval_ctx, scene, ob, NULL, effector_weights, true); if (effectors) { float eff_force[3] = {0.0f, 0.0f, 0.0f}; float eff_loc[3], eff_vel[3]; @@ -1312,10 +1318,8 @@ static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *o * * \param rebuild Rebuild entire simulation */ -static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, bool rebuild) +static void rigidbody_update_simulation(const struct EvaluationContext *eval_ctx, Scene *scene, RigidBodyWorld *rbw, bool rebuild) { - GroupObject *go; - /* update world */ if (rebuild) BKE_rigidbody_validate_sim_world(scene, rbw, true); @@ -1328,28 +1332,26 @@ static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, bool * Memory management needs redesign here, this is just a dirty workaround. */ if (rebuild && rbw->constraints) { - for (go = rbw->constraints->gobject.first; go; go = go->next) { - Object *ob = go->ob; - if (ob) { - RigidBodyCon *rbc = ob->rigidbody_constraint; - if (rbc && rbc->physics_constraint) { - RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint); - RB_constraint_delete(rbc->physics_constraint); - rbc->physics_constraint = NULL; - } + FOREACH_GROUP_OBJECT(rbw->constraints, ob) + { + RigidBodyCon *rbc = ob->rigidbody_constraint; + if (rbc && rbc->physics_constraint) { + RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint); + RB_constraint_delete(rbc->physics_constraint); + rbc->physics_constraint = NULL; } } + FOREACH_GROUP_OBJECT_END } /* update objects */ - for (go = rbw->group->gobject.first; go; go = go->next) { - Object *ob = go->ob; - - if (ob && ob->type == OB_MESH) { + FOREACH_GROUP_OBJECT(rbw->group, ob) + { + if (ob->type == OB_MESH) { /* validate that we've got valid object set up here... */ RigidBodyOb *rbo = ob->rigidbody_object; /* update transformation matrix of the object so we don't get a frame of lag for simple animations */ - BKE_object_where_is_calc(scene, ob); + BKE_object_where_is_calc(eval_ctx, scene, ob); if (rbo == NULL) { /* Since this object is included in the sim group but doesn't have @@ -1383,65 +1385,62 @@ static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, bool } /* update simulation object... */ - rigidbody_update_sim_ob(scene, rbw, ob, rbo); + rigidbody_update_sim_ob(eval_ctx, scene, rbw, ob, rbo); } } + FOREACH_GROUP_OBJECT_END /* update constraints */ if (rbw->constraints == NULL) /* no constraints, move on */ return; - for (go = rbw->constraints->gobject.first; go; go = go->next) { - Object *ob = go->ob; - if (ob) { - /* validate that we've got valid object set up here... */ - RigidBodyCon *rbc = ob->rigidbody_constraint; - /* update transformation matrix of the object so we don't get a frame of lag for simple animations */ - BKE_object_where_is_calc(scene, ob); + FOREACH_GROUP_OBJECT(rbw->constraints, ob) + { + /* validate that we've got valid object set up here... */ + RigidBodyCon *rbc = ob->rigidbody_constraint; + /* update transformation matrix of the object so we don't get a frame of lag for simple animations */ + BKE_object_where_is_calc(eval_ctx, scene, ob); - if (rbc == NULL) { - /* Since this object is included in the group but doesn't have - * constraint settings (perhaps it was added manually), add! - */ - ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, RBC_TYPE_FIXED); - rigidbody_validate_sim_constraint(rbw, ob, true); + if (rbc == NULL) { + /* Since this object is included in the group but doesn't have + * constraint settings (perhaps it was added manually), add! + */ + ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, RBC_TYPE_FIXED); + rigidbody_validate_sim_constraint(rbw, ob, true); - rbc = ob->rigidbody_constraint; + rbc = ob->rigidbody_constraint; + } + else { + /* perform simulation data updates as tagged */ + if (rebuild) { + /* World has been rebuilt so rebuild constraint */ + rigidbody_validate_sim_constraint(rbw, ob, true); } - else { - /* perform simulation data updates as tagged */ - if (rebuild) { - /* World has been rebuilt so rebuild constraint */ - rigidbody_validate_sim_constraint(rbw, ob, true); - } - else if (rbc->flag & RBC_FLAG_NEEDS_VALIDATE) { - rigidbody_validate_sim_constraint(rbw, ob, false); - } - rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE; + else if (rbc->flag & RBC_FLAG_NEEDS_VALIDATE) { + rigidbody_validate_sim_constraint(rbw, ob, false); } + rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE; } } + FOREACH_GROUP_OBJECT_END } static void rigidbody_update_simulation_post_step(RigidBodyWorld *rbw) { - GroupObject *go; - - for (go = rbw->group->gobject.first; go; go = go->next) { - Object *ob = go->ob; - - if (ob) { - RigidBodyOb *rbo = ob->rigidbody_object; - /* reset kinematic state for transformed objects */ - if (rbo && (ob->flag & SELECT) && (G.moving & G_TRANSFORM_OBJ)) { - RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED); - RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo)); - /* deactivate passive objects so they don't interfere with deactivation of active objects */ - if (rbo->type == RBO_TYPE_PASSIVE) - RB_body_deactivate(rbo->physics_object); - } + FOREACH_GROUP_BASE(rbw->group, base) + { + Object *ob = base->object; + RigidBodyOb *rbo = ob->rigidbody_object; + /* Reset kinematic state for transformed objects. */ + if (rbo && (base->flag & BASE_SELECTED) && (G.moving & G_TRANSFORM_OBJ)) { + RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED); + RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo)); + /* Deactivate passive objects so they don't interfere with deactivation of active objects. */ + if (rbo->type == RBO_TYPE_PASSIVE) + RB_body_deactivate(rbo->physics_object); } } + FOREACH_GROUP_BASE_END } bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float ctime) @@ -1556,7 +1555,7 @@ void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) /* Rebuild rigid body world */ /* NOTE: this needs to be called before frame update to work correctly */ -void BKE_rigidbody_rebuild_world(Scene *scene, float ctime) +void BKE_rigidbody_rebuild_world(const struct EvaluationContext *eval_ctx, Scene *scene, float ctime) { RigidBodyWorld *rbw = scene->rigidbody_world; PointCache *cache; @@ -1568,14 +1567,14 @@ 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_listbase_count(&rbw->group->gobject)) { + if (rbw->physics_world == NULL || rbw->numbodies != BLI_listbase_count(&rbw->group->view_layer->object_bases)) { cache->flag |= PTCACHE_OUTDATED; } if (ctime == startframe + 1 && rbw->ltime == startframe) { if (cache->flag & PTCACHE_OUTDATED) { BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED); - rigidbody_update_simulation(scene, rbw, true); + rigidbody_update_simulation(eval_ctx, scene, rbw, true); BKE_ptcache_validate(cache, (int)ctime); cache->last_exact = 0; cache->flag &= ~PTCACHE_REDO_NEEDED; @@ -1584,7 +1583,7 @@ void BKE_rigidbody_rebuild_world(Scene *scene, float ctime) } /* Run RigidBody simulation for the specified physics world */ -void BKE_rigidbody_do_simulation(Scene *scene, float ctime) +void BKE_rigidbody_do_simulation(const struct EvaluationContext *eval_ctx, Scene *scene, float ctime) { float timestep; RigidBodyWorld *rbw = scene->rigidbody_world; @@ -1622,14 +1621,14 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime) } /* advance simulation, we can only step one frame forward */ - if (can_simulate) { + if (ctime == rbw->ltime + 1) { /* write cache for first frame when on second frame */ if (rbw->ltime == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) { BKE_ptcache_write(&pid, startframe); } /* update and validate simulation */ - rigidbody_update_simulation(scene, rbw, false); + rigidbody_update_simulation(eval_ctx, scene, rbw, false); /* calculate how much time elapsed since last step in seconds */ timestep = 1.0f / (float)FPS * (ctime - rbw->ltime) * rbw->time_scale; @@ -1673,8 +1672,8 @@ void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime) void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle) {} bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float ctime) { return false; } void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) {} -void BKE_rigidbody_rebuild_world(Scene *scene, float ctime) {} -void BKE_rigidbody_do_simulation(Scene *scene, float ctime) {} +void BKE_rigidbody_rebuild_world(const struct EvaluationContext *eval_ctx, Scene *scene, float ctime) {} +void BKE_rigidbody_do_simulation(const struct EvaluationContext *eval_ctx, Scene *scene, float ctime) {} #ifdef __GNUC__ # pragma GCC diagnostic pop @@ -1685,7 +1684,7 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime) {} /* -------------------- */ /* Depsgraph evaluation */ -void BKE_rigidbody_rebuild_sim(EvaluationContext *UNUSED(eval_ctx), +void BKE_rigidbody_rebuild_sim(const struct EvaluationContext *eval_ctx, Scene *scene) { float ctime = BKE_scene_frame_get(scene); @@ -1696,11 +1695,11 @@ void BKE_rigidbody_rebuild_sim(EvaluationContext *UNUSED(eval_ctx), /* rebuild sim data (i.e. after resetting to start of timeline) */ if (BKE_scene_check_rigidbody_active(scene)) { - BKE_rigidbody_rebuild_world(scene, ctime); + BKE_rigidbody_rebuild_world(eval_ctx, scene, ctime); } } -void BKE_rigidbody_eval_simulation(EvaluationContext *UNUSED(eval_ctx), +void BKE_rigidbody_eval_simulation(const struct EvaluationContext *eval_ctx, Scene *scene) { float ctime = BKE_scene_frame_get(scene); @@ -1711,11 +1710,11 @@ void BKE_rigidbody_eval_simulation(EvaluationContext *UNUSED(eval_ctx), /* evaluate rigidbody sim */ if (BKE_scene_check_rigidbody_active(scene)) { - BKE_rigidbody_do_simulation(scene, ctime); + BKE_rigidbody_do_simulation(eval_ctx, scene, ctime); } } -void BKE_rigidbody_object_sync_transforms(EvaluationContext *UNUSED(eval_ctx), +void BKE_rigidbody_object_sync_transforms(const struct EvaluationContext *UNUSED(eval_ctx), Scene *scene, Object *ob) { diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 126761ed14b..a4ccf3b9bba 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -49,6 +49,7 @@ #include "DNA_space_types.h" #include "DNA_view3d_types.h" #include "DNA_windowmanager_types.h" +#include "DNA_workspace_types.h" #include "DNA_gpencil_types.h" #include "BLI_math.h" @@ -67,8 +68,8 @@ #include "BKE_action.h" #include "BKE_armature.h" #include "BKE_cachefile.h" +#include "BKE_collection.h" #include "BKE_colortools.h" -#include "BKE_depsgraph.h" #include "BKE_editmesh.h" #include "BKE_fcurve.h" #include "BKE_freestyle.h" @@ -78,6 +79,7 @@ #include "BKE_icons.h" #include "BKE_idprop.h" #include "BKE_image.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_remap.h" #include "BKE_linestyle.h" @@ -92,9 +94,13 @@ #include "BKE_sequencer.h" #include "BKE_sound.h" #include "BKE_unit.h" +#include "BKE_workspace.h" #include "BKE_world.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" +#include "DEG_depsgraph_debug.h" +#include "DEG_depsgraph_query.h" #include "RE_engine.h" @@ -107,6 +113,8 @@ const char *RE_engine_id_BLENDER_RENDER = "BLENDER_RENDER"; const char *RE_engine_id_BLENDER_GAME = "BLENDER_GAME"; +const char *RE_engine_id_BLENDER_CLAY = "BLENDER_CLAY"; +const char *RE_engine_id_BLENDER_EEVEE = "BLENDER_EEVEE"; const char *RE_engine_id_CYCLES = "CYCLES"; void free_avicodecdata(AviCodecData *acd) @@ -157,25 +165,37 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; sce_dst->ed = NULL; - sce_dst->theDag = NULL; - sce_dst->depsgraph = NULL; + sce_dst->depsgraph_hash = NULL; sce_dst->obedit = NULL; - sce_dst->stats = NULL; sce_dst->fps_info = NULL; - BLI_duplicatelist(&(sce_dst->base), &(sce_src->base)); - for (Base *base_dst = sce_dst->base.first, *base_src = sce_src->base.first; - base_dst; - base_dst = base_dst->next, base_src = base_src->next) + /* layers and collections */ + sce_dst->collection = MEM_dupallocN(sce_src->collection); + SceneCollection *mc_src = BKE_collection_master(&sce_src->id); + SceneCollection *mc_dst = BKE_collection_master(&sce_dst->id); + + /* Recursively creates a new SceneCollection tree. */ + BKE_collection_copy_data(mc_dst, mc_src, flag_subdata); + + IDPropertyTemplate val = {0}; + BLI_duplicatelist(&sce_dst->view_layers, &sce_src->view_layers); + for (ViewLayer *view_layer_src = sce_src->view_layers.first, *view_layer_dst = sce_dst->view_layers.first; + view_layer_src; + view_layer_src = view_layer_src->next, view_layer_dst = view_layer_dst->next) { - if (base_src == sce_src->basact) { - sce_dst->basact = base_dst; - } + BKE_view_layer_copy_data(view_layer_dst, view_layer_src, mc_dst, mc_src, flag_subdata); + } + + sce_dst->collection_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP); + if (sce_src->collection_properties) { + IDP_MergeGroup_ex(sce_dst->collection_properties, sce_src->collection_properties, true, flag_subdata); + } + sce_dst->layer_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP); + if (sce_src->layer_properties) { + IDP_MergeGroup_ex(sce_dst->layer_properties, sce_src->layer_properties, true, flag_subdata); } BLI_duplicatelist(&(sce_dst->markers), &(sce_src->markers)); - BLI_duplicatelist(&(sce_dst->transform_spaces), &(sce_src->transform_spaces)); - BLI_duplicatelist(&(sce_dst->r.layers), &(sce_src->r.layers)); BLI_duplicatelist(&(sce_dst->r.views), &(sce_src->r.views)); BKE_keyingsets_copy(&(sce_dst->keyingsets), &(sce_src->keyingsets)); @@ -190,17 +210,6 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons sce_dst->rigidbody_world = BKE_rigidbody_world_copy(sce_src->rigidbody_world, flag_subdata); } - /* copy Freestyle settings */ - for (SceneRenderLayer *srl_dst = sce_dst->r.layers.first, *srl_src = sce_src->r.layers.first; - srl_src; - srl_dst = srl_dst->next, srl_src = srl_src->next) - { - if (srl_dst->prop != NULL) { - srl_dst->prop = IDP_CopyProperty_ex(srl_dst->prop, flag_subdata); - } - BKE_freestyle_config_copy(&srl_dst->freestyleConfig, &srl_src->freestyleConfig, flag_subdata); - } - /* copy color management settings */ BKE_color_managed_display_settings_copy(&sce_dst->display_settings, &sce_src->display_settings); BKE_color_managed_view_settings_copy(&sce_dst->view_settings, &sce_src->view_settings); @@ -289,16 +298,14 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) * But for now, let's keep it well isolated here. */ if (type == SCE_COPY_EMPTY) { ToolSettings *ts; - ListBase rl, rv; + ListBase rv; sce_copy = BKE_scene_add(bmain, sce->id.name + 2); - rl = sce_copy->r.layers; rv = sce_copy->r.views; curvemapping_free_data(&sce_copy->r.mblur_shutter_curve); sce_copy->r = sce->r; - sce_copy->r.layers = rl; - sce_copy->r.actlay = 0; + sce_copy->active_view_layer = 0; sce_copy->r.views = rv; sce_copy->unit = sce->unit; sce_copy->physics_settings = sce->physics_settings; @@ -396,8 +403,8 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) if (type == SCE_COPY_FULL) { /* Copy Freestyle LineStyle datablocks. */ - for (SceneRenderLayer *srl_dst = sce_copy->r.layers.first; srl_dst; srl_dst = srl_dst->next) { - for (FreestyleLineSet *lineset = srl_dst->freestyleConfig.linesets.first; lineset; lineset = lineset->next) { + for (ViewLayer *view_layer_dst = sce_copy->view_layers.first; view_layer_dst; view_layer_dst = view_layer_dst->next) { + for (FreestyleLineSet *lineset = view_layer_dst->freestyle_config.linesets.first; lineset; lineset = lineset->next) { if (lineset->linestyle) { /* XXX Not copying anim/actions here? */ BKE_id_copy_ex(bmain, (ID *)lineset->linestyle, (ID **)&lineset->linestyle, 0, false); @@ -449,17 +456,13 @@ void BKE_scene_make_local(Main *bmain, Scene *sce, const bool lib_local) } /** Free (or release) any data used by this scene (does not free the scene itself). */ -void BKE_scene_free(Scene *sce) +void BKE_scene_free_ex(Scene *sce, const bool do_id_user) { - SceneRenderLayer *srl; - BKE_animdata_free((ID *)sce, false); /* check all sequences */ BKE_sequencer_clear_scene_in_allseqs(G.main, sce); - sce->basact = NULL; - BLI_freelistN(&sce->base); BKE_sequencer_editing_free(sce); BKE_keyingsets_free(&sce->keyingsets); @@ -487,17 +490,7 @@ void BKE_scene_free(Scene *sce) sce->r.ffcodecdata.properties = NULL; } - for (srl = sce->r.layers.first; srl; srl = srl->next) { - if (srl->prop != NULL) { - IDP_FreeProperty(srl->prop); - MEM_freeN(srl->prop); - } - BKE_freestyle_config_free(&srl->freestyleConfig); - } - BLI_freelistN(&sce->markers); - BLI_freelistN(&sce->transform_spaces); - BLI_freelistN(&sce->r.layers); BLI_freelistN(&sce->r.views); if (sce->toolsettings) { @@ -532,11 +525,8 @@ void BKE_scene_free(Scene *sce) sce->toolsettings = NULL; } - DAG_scene_free(sce); - if (sce->depsgraph) - DEG_graph_free(sce->depsgraph); - - MEM_SAFE_FREE(sce->stats); + BKE_scene_free_depsgraph_hash(sce); + MEM_SAFE_FREE(sce->fps_info); BKE_sound_destroy_scene(sce); @@ -545,6 +535,37 @@ void BKE_scene_free(Scene *sce) BKE_previewimg_free(&sce->preview); curvemapping_free_data(&sce->r.mblur_shutter_curve); + + for (ViewLayer *view_layer = sce->view_layers.first, *view_layer_next; view_layer; view_layer = view_layer_next) { + view_layer_next = view_layer->next; + + BLI_remlink(&sce->view_layers, view_layer); + BKE_view_layer_free_ex(view_layer, do_id_user); + } + + /* Master Collection */ + BKE_collection_master_free(&sce->id, do_id_user); + MEM_freeN(sce->collection); + sce->collection = NULL; + + /* LayerCollection engine settings. */ + if (sce->collection_properties) { + IDP_FreeProperty(sce->collection_properties); + MEM_freeN(sce->collection_properties); + sce->collection_properties = NULL; + } + + /* Render engine setting. */ + if (sce->layer_properties) { + IDP_FreeProperty(sce->layer_properties); + MEM_freeN(sce->layer_properties); + sce->layer_properties = NULL; + } +} + +void BKE_scene_free(Scene *sce) +{ + BKE_scene_free_ex(sce, true); } void BKE_scene_init(Scene *sce) @@ -597,7 +618,7 @@ void BKE_scene_init(Scene *sce) */ sce->r.color_mgt_flag |= R_COLOR_MANAGEMENT; - sce->r.gauss = 1.0; + sce->r.gauss = 1.5f; /* deprecated but keep for upwards compat */ sce->r.postgamma = 1.0; @@ -749,7 +770,7 @@ void BKE_scene_init(Scene *sce) sce->r.ffcodecdata.audio_bitrate = 192; sce->r.ffcodecdata.audio_channels = 2; - BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_RENDER, sizeof(sce->r.engine)); + BKE_viewrender_init(&sce->view_render); sce->audio.distance_model = 2.0f; sce->audio.doppler_factor = 1.0f; @@ -762,7 +783,6 @@ void BKE_scene_init(Scene *sce) sce->r.osa = 8; /* note; in header_info.c the scene copy happens..., if you add more to renderdata it has to be checked there */ - BKE_scene_add_render_layer(sce, NULL); /* multiview - stereo */ BKE_scene_add_render_view(sce, STEREO_LEFT_NAME); @@ -801,7 +821,7 @@ void BKE_scene_init(Scene *sce) sce->gm.angulardeactthreshold = 1.0f; sce->gm.deactivationtime = 0.0f; - sce->gm.flag = GAME_DISPLAY_LISTS; + sce->gm.flag = 0; sce->gm.matmode = GAME_MAT_MULTITEX; sce->gm.obstacleSimulation = OBSTSIMULATION_NONE; @@ -895,6 +915,20 @@ void BKE_scene_init(Scene *sce) sce->toolsettings->gpencil_v2d_align = GP_PROJECT_VIEWSPACE; sce->toolsettings->gpencil_seq_align = GP_PROJECT_VIEWSPACE; sce->toolsettings->gpencil_ima_align = GP_PROJECT_VIEWSPACE; + + /* Master Collection */ + sce->collection = MEM_callocN(sizeof(SceneCollection), "Master Collection"); + BLI_strncpy(sce->collection->name, "Master Collection", sizeof(sce->collection->name)); + + /* Engine settings */ + IDPropertyTemplate val = {0}; + sce->collection_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP); + BKE_layer_collection_engine_settings_create(sce->collection_properties); + + sce->layer_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP); + BKE_view_layer_engine_settings_create(sce->layer_properties); + + BKE_view_layer_add(sce, "View Layer"); } Scene *BKE_scene_add(Main *bmain, const char *name) @@ -910,44 +944,46 @@ Scene *BKE_scene_add(Main *bmain, const char *name) return sce; } -Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name) +/** + * Check if there is any intance of the object in the scene + */ +bool BKE_scene_object_find(Scene *scene, Object *ob) { - Base *base; - - for (base = scene->base.first; base; base = base->next) { - if (STREQ(base->object->id.name + 2, name)) { - break; + for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + if (BLI_findptr(&view_layer->object_bases, ob, offsetof(Base, object))) { + return true; } } - - return base; + return false; } -Base *BKE_scene_base_find(Scene *scene, Object *ob) +Object *BKE_scene_object_find_by_name(Scene *scene, const char *name) { - return BLI_findptr(&scene->base, ob, offsetof(Base, object)); + for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + if (STREQ(base->object->id.name + 2, name)) { + return base->object; + } + } + } + return NULL; } /** * Sets the active scene, mainly used when running in background mode (``--scene`` command line argument). * This is also called to set the scene directly, bypassing windowing code. - * Otherwise #ED_screen_set_scene is used when changing scenes by the user. + * Otherwise #WM_window_change_active_scene is used when changing scenes by the user. */ void BKE_scene_set_background(Main *bmain, Scene *scene) { - Scene *sce; - Base *base; Object *ob; Group *group; - GroupObject *go; - int flag; /* check for cyclic sets, for reading old files but also for definite security (py?) */ BKE_scene_validate_setscene(bmain, scene); /* can happen when switching modes in other scenes */ - if (scene->obedit && !(scene->obedit->mode & OB_MODE_EDIT)) - scene->obedit = NULL; + scene->obedit = NULL; /* deselect objects (for dataselect) */ for (ob = bmain->object.first; ob; ob = ob->id.next) @@ -955,30 +991,20 @@ void BKE_scene_set_background(Main *bmain, Scene *scene) /* group flags again */ for (group = bmain->group.first; group; group = group->id.next) { - for (go = group->gobject.first; go; go = go->next) { - if (go->ob) { - go->ob->flag |= OB_FROMGROUP; - } + FOREACH_GROUP_OBJECT(group, object) + { + object->flag |= OB_FROMGROUP; } + FOREACH_GROUP_OBJECT_END } - /* sort baselist for scene and sets */ - for (sce = scene; sce; sce = sce->set) - DAG_scene_relations_rebuild(bmain, sce); - /* copy layers and flags from bases to objects */ - for (base = scene->base.first; base; base = base->next) { - ob = base->object; - ob->lay = base->lay; - - /* group patch... */ - base->flag &= ~(OB_FROMGROUP); - flag = ob->flag & (OB_FROMGROUP); - base->flag |= flag; - - /* not too nice... for recovering objects with lost data */ - //if (ob->pose == NULL) base->flag &= ~OB_POSEMODE; - ob->flag = base->flag; + for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + ob = base->object; + /* group patch... */ + BKE_scene_object_base_flag_sync_from_base(base); + } } /* no full animation update, this to enable render code to work (render code calls own animation updates) */ } @@ -998,8 +1024,9 @@ Scene *BKE_scene_set_name(Main *bmain, const char *name) } /* Used by metaballs, return *all* objects (including duplis) existing in the scene (including scene's sets) */ -int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter, - Scene **scene, int val, Base **base, Object **ob) +int BKE_scene_base_iter_next( + const EvaluationContext *eval_ctx, SceneBaseIter *iter, + Scene **scene, int val, Base **base, Object **ob) { bool run_again = true; @@ -1017,17 +1044,19 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter, /* the first base */ if (iter->phase == F_START) { - *base = (*scene)->base.first; + ViewLayer *view_layer = eval_ctx->view_layer; + *base = view_layer->object_bases.first; if (*base) { *ob = (*base)->object; iter->phase = F_SCENE; } else { - /* exception: empty scene */ + /* exception: empty scene layer */ while ((*scene)->set) { (*scene) = (*scene)->set; - if ((*scene)->base.first) { - *base = (*scene)->base.first; + ViewLayer *view_layer_set = BKE_view_layer_from_scene_get((*scene)); + if (view_layer_set->object_bases.first) { + *base = view_layer_set->object_bases.first; *ob = (*base)->object; iter->phase = F_SCENE; break; @@ -1046,8 +1075,9 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter, /* (*scene) is finished, now do the set */ while ((*scene)->set) { (*scene) = (*scene)->set; - if ((*scene)->base.first) { - *base = (*scene)->base.first; + ViewLayer *view_layer_set = BKE_view_layer_from_scene_get((*scene)); + if (view_layer_set->object_bases.first) { + *base = view_layer_set->object_bases.first; *ob = (*base)->object; break; } @@ -1081,7 +1111,7 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter, } /* handle dupli's */ if (iter->dupob) { - (*base)->flag |= OB_FROMDUPLI; + (*base)->flag_legacy |= OB_FROMDUPLI; *ob = iter->dupob->ob; iter->phase = F_DUPLI; @@ -1100,7 +1130,7 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter, } else if (iter->phase == F_DUPLI) { iter->phase = F_SCENE; - (*base)->flag &= ~OB_FROMDUPLI; + (*base)->flag_legacy &= ~OB_FROMDUPLI; if (iter->dupli_refob) { /* Restore last object's real matrix. */ @@ -1125,13 +1155,15 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter, return iter->phase; } -Object *BKE_scene_camera_find(Scene *sc) +Scene *BKE_scene_find_from_collection(const Main *bmain, const SceneCollection *scene_collection) { - Base *base; - - for (base = sc->base.first; base; base = base->next) - if (base->object->type == OB_CAMERA) - return base->object; + for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) { + for (ViewLayer *layer = scene->view_layers.first; layer; layer = layer->next) { + if (BKE_view_layer_has_collection(layer, scene_collection)) { + return scene; + } + } + } return NULL; } @@ -1233,49 +1265,14 @@ char *BKE_scene_find_last_marker_name(Scene *scene, int frame) return best_marker ? best_marker->name : NULL; } - -Base *BKE_scene_base_add(Scene *sce, Object *ob) -{ - Base *b = MEM_callocN(sizeof(*b), __func__); - BLI_addhead(&sce->base, b); - - b->object = ob; - b->flag = ob->flag; - b->lay = ob->lay; - - return b; -} - -void BKE_scene_base_unlink(Scene *sce, Base *base) +void BKE_scene_remove_rigidbody_object(Scene *scene, Object *ob) { /* remove rigid body constraint from world before removing object */ - if (base->object->rigidbody_constraint) - BKE_rigidbody_remove_constraint(sce, base->object); + if (ob->rigidbody_constraint) + BKE_rigidbody_remove_constraint(scene, ob); /* remove rigid body object from world before removing object */ - if (base->object->rigidbody_object) - BKE_rigidbody_remove_object(sce, base->object); - - BLI_remlink(&sce->base, base); - if (sce->basact == base) - sce->basact = NULL; -} - -void BKE_scene_base_deselect_all(Scene *sce) -{ - Base *b; - - for (b = sce->base.first; b; b = b->next) { - b->flag &= ~SELECT; - b->object->flag = b->flag; - } -} - -void BKE_scene_base_select(Scene *sce, Base *selbase) -{ - selbase->flag |= SELECT; - selbase->object->flag = selbase->flag; - - sce->basact = selbase; + if (ob->rigidbody_object) + BKE_rigidbody_remove_object(scene, ob); } /* checks for cycle, returns 1 if it's all OK */ @@ -1327,109 +1324,6 @@ void BKE_scene_frame_set(struct Scene *scene, double cfra) scene->r.cfra = (int)intpart; } -#ifdef WITH_LEGACY_DEPSGRAPH -/* drivers support/hacks - * - this method is called from scene_update_tagged_recursive(), so gets included in viewport + render - * - these are always run since the depsgraph can't handle non-object data - * - these happen after objects are all done so that we can read in their final transform values, - * though this means that objects can't refer to scene info for guidance... - */ -static void scene_update_drivers(Main *UNUSED(bmain), Scene *scene) -{ - SceneRenderLayer *srl; - float ctime = BKE_scene_frame_get(scene); - - /* scene itself */ - if (scene->adt && scene->adt->drivers.first) { - BKE_animsys_evaluate_animdata(scene, &scene->id, scene->adt, ctime, ADT_RECALC_DRIVERS); - } - - /* world */ - /* TODO: what about world textures? but then those have nodes too... */ - if (scene->world) { - ID *wid = (ID *)scene->world; - AnimData *adt = BKE_animdata_from_id(wid); - - if (adt && adt->drivers.first) - BKE_animsys_evaluate_animdata(scene, wid, adt, ctime, ADT_RECALC_DRIVERS); - } - - /* nodes */ - if (scene->nodetree) { - ID *nid = (ID *)scene->nodetree; - AnimData *adt = BKE_animdata_from_id(nid); - - if (adt && adt->drivers.first) - BKE_animsys_evaluate_animdata(scene, nid, adt, ctime, ADT_RECALC_DRIVERS); - } - - /* world nodes */ - if (scene->world && scene->world->nodetree) { - ID *nid = (ID *)scene->world->nodetree; - AnimData *adt = BKE_animdata_from_id(nid); - - if (adt && adt->drivers.first) - BKE_animsys_evaluate_animdata(scene, nid, adt, ctime, ADT_RECALC_DRIVERS); - } - - /* freestyle */ - for (srl = scene->r.layers.first; srl; srl = srl->next) { - FreestyleConfig *config = &srl->freestyleConfig; - FreestyleLineSet *lineset; - - for (lineset = config->linesets.first; lineset; lineset = lineset->next) { - if (lineset->linestyle) { - ID *lid = &lineset->linestyle->id; - AnimData *adt = BKE_animdata_from_id(lid); - - if (adt && adt->drivers.first) - BKE_animsys_evaluate_animdata(scene, lid, adt, ctime, ADT_RECALC_DRIVERS); - } - } - } -} - -/* deps hack - do extra recalcs at end */ -static void scene_depsgraph_hack(EvaluationContext *eval_ctx, Scene *scene, Scene *scene_parent) -{ - Base *base; - - scene->customdata_mask = scene_parent->customdata_mask; - - /* sets first, we allow per definition current scene to have - * dependencies on sets, but not the other way around. */ - if (scene->set) - scene_depsgraph_hack(eval_ctx, scene->set, scene_parent); - - for (base = scene->base.first; base; base = base->next) { - Object *ob = base->object; - - if (ob->depsflag) { - int recalc = 0; - // printf("depshack %s\n", ob->id.name + 2); - - if (ob->depsflag & OB_DEPS_EXTRA_OB_RECALC) - recalc |= OB_RECALC_OB; - if (ob->depsflag & OB_DEPS_EXTRA_DATA_RECALC) - recalc |= OB_RECALC_DATA; - - ob->recalc |= recalc; - BKE_object_handle_update(eval_ctx, scene_parent, ob); - - if (ob->dup_group && (ob->transflag & OB_DUPLIGROUP)) { - GroupObject *go; - - for (go = ob->dup_group->gobject.first; go; go = go->next) { - if (go->ob) - go->ob->recalc |= recalc; - } - BKE_group_handle_recalc_and_update(eval_ctx, scene_parent, ob, ob->dup_group); - } - } - } -} -#endif /* WITH_LEGACY_DEPSGRAPH */ - /* 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 @@ -1445,7 +1339,7 @@ static void scene_depsgraph_hack(EvaluationContext *eval_ctx, Scene *scene, Scen static void scene_armature_depsgraph_workaround(Main *bmain) { Object *ob; - if (BLI_listbase_is_empty(&bmain->armature) || !DAG_id_type_tagged(bmain, ID_OB)) { + if (BLI_listbase_is_empty(&bmain->armature) || !DEG_id_type_tagged(bmain, ID_OB)) { return; } for (ob = bmain->object.first; ob; ob = ob->id.next) { @@ -1458,372 +1352,27 @@ static void scene_armature_depsgraph_workaround(Main *bmain) } #endif -#ifdef WITH_LEGACY_DEPSGRAPH -static void scene_rebuild_rbw_recursive(Scene *scene, float ctime) -{ - if (scene->set) - scene_rebuild_rbw_recursive(scene->set, ctime); - - if (BKE_scene_check_rigidbody_active(scene)) - BKE_rigidbody_rebuild_world(scene, ctime); -} - -static void scene_do_rb_simulation_recursive(Scene *scene, float ctime) -{ - if (scene->set) - scene_do_rb_simulation_recursive(scene->set, ctime); - - if (BKE_scene_check_rigidbody_active(scene)) - BKE_rigidbody_do_simulation(scene, ctime); -} -#endif - -/* Used to visualize CPU threads activity during threaded object update, - * would pollute STDERR with whole bunch of timing information which then - * could be parsed and nicely visualized. - */ -#ifdef WITH_LEGACY_DEPSGRAPH -# undef DETAILED_ANALYSIS_OUTPUT -#else -/* ALWAYS KEEY DISABLED! */ -# undef DETAILED_ANALYSIS_OUTPUT -#endif - -/* Mballs evaluation uses BKE_scene_base_iter_next which calls - * duplilist for all objects in the scene. This leads to conflict - * accessing and writing same data from multiple threads. - * - * Ideally Mballs shouldn't do such an iteration and use DAG - * queries instead. For the time being we've got new DAG - * let's keep it simple and update mballs in a single thread. - */ -#define MBALL_SINGLETHREAD_HACK - -#ifdef WITH_LEGACY_DEPSGRAPH -typedef struct StatisicsEntry { - struct StatisicsEntry *next, *prev; - Object *object; - double start_time; - double duration; -} StatisicsEntry; - -typedef struct ThreadedObjectUpdateState { - /* TODO(sergey): We might want this to be per-thread object. */ - EvaluationContext *eval_ctx; - Scene *scene; - Scene *scene_parent; - double base_time; - -#ifdef MBALL_SINGLETHREAD_HACK - bool has_mballs; -#endif - - /* Execution statistics */ - bool has_updated_objects; - ListBase *statistics; -} ThreadedObjectUpdateState; - -static void scene_update_object_add_task(void *node, void *user_data); - -static void scene_update_all_bases(EvaluationContext *eval_ctx, Scene *scene, Scene *scene_parent) -{ - Base *base; - - for (base = scene->base.first; base; base = base->next) { - Object *object = base->object; - - BKE_object_handle_update_ex(eval_ctx, scene_parent, object, scene->rigidbody_world, true); - - if (object->dup_group && (object->transflag & OB_DUPLIGROUP)) - BKE_group_handle_recalc_and_update(eval_ctx, scene_parent, object, object->dup_group); - - /* always update layer, so that animating layers works (joshua july 2010) */ - /* XXX commented out, this has depsgraph issues anyway - and this breaks setting scenes - * (on scene-set, the base-lay is copied to ob-lay (ton nov 2012) */ - // base->lay = ob->lay; - } -} - -static void scene_update_object_func(TaskPool * __restrict pool, void *taskdata, int threadid) -{ -/* Disable print for now in favor of summary statistics at the end of update. */ -#define PRINT if (false) printf - - ThreadedObjectUpdateState *state = (ThreadedObjectUpdateState *) BLI_task_pool_userdata(pool); - void *node = taskdata; - Object *object = DAG_get_node_object(node); - EvaluationContext *eval_ctx = state->eval_ctx; - Scene *scene = state->scene; - Scene *scene_parent = state->scene_parent; - -#ifdef MBALL_SINGLETHREAD_HACK - if (object && object->type == OB_MBALL) { - state->has_mballs = true; - } - else -#endif - if (object) { - double start_time = 0.0; - bool add_to_stats = false; - - if (G.debug & G_DEBUG_DEPSGRAPH) { - if (object->recalc & OB_RECALC_ALL) { - printf("Thread %d: update object %s\n", threadid, object->id.name); - } - - start_time = PIL_check_seconds_timer(); - - if (object->recalc & OB_RECALC_ALL) { - state->has_updated_objects = true; - add_to_stats = true; - } - } - - /* We only update object itself here, dupli-group will be updated - * separately from main thread because of we've got no idea about - * dependencies inside the group. - */ - BKE_object_handle_update_ex(eval_ctx, scene_parent, object, scene->rigidbody_world, false); - - /* Calculate statistics. */ - if (add_to_stats) { - StatisicsEntry *entry; - - entry = MEM_mallocN(sizeof(StatisicsEntry), "update thread statistics"); - entry->object = object; - entry->start_time = start_time; - entry->duration = PIL_check_seconds_timer() - start_time; - - BLI_addtail(&state->statistics[threadid], entry); - } - } - else { - PRINT("Threda %d: update node %s\n", threadid, - DAG_get_node_name(scene, node)); - } - - /* Update will decrease child's valency and schedule child with zero valency. */ - DAG_threaded_update_handle_node_updated(node, scene_update_object_add_task, pool); - -#undef PRINT -} - -static void scene_update_object_add_task(void *node, void *user_data) -{ - TaskPool *task_pool = user_data; - - BLI_task_pool_push(task_pool, scene_update_object_func, node, false, TASK_PRIORITY_LOW); -} - -static void print_threads_statistics(ThreadedObjectUpdateState *state) -{ - int i, tot_thread; - double finish_time; - - if ((G.debug & G_DEBUG_DEPSGRAPH) == 0) { - return; - } - -#ifdef DETAILED_ANALYSIS_OUTPUT - if (state->has_updated_objects) { - tot_thread = BLI_system_thread_count(); - - fprintf(stderr, "objects update base time %f\n", state->base_time); - - for (i = 0; i < tot_thread; i++) { - StatisicsEntry *entry; - for (entry = state->statistics[i].first; - entry; - entry = entry->next) - { - fprintf(stderr, "thread %d object %s start_time %f duration %f\n", - i, entry->object->id.name + 2, - entry->start_time, entry->duration); - } - BLI_freelistN(&state->statistics[i]); - } - } -#else - finish_time = PIL_check_seconds_timer(); - tot_thread = BLI_system_thread_count(); - int total_objects = 0; - - for (i = 0; i < tot_thread; i++) { - int thread_total_objects = 0; - double thread_total_time = 0.0; - StatisicsEntry *entry; - - if (state->has_updated_objects) { - /* Don't pollute output if no objects were updated. */ - for (entry = state->statistics[i].first; - entry; - entry = entry->next) - { - thread_total_objects++; - thread_total_time += entry->duration; - } - - printf("Thread %d: total %d objects in %f sec.\n", - i, - thread_total_objects, - thread_total_time); - - for (entry = state->statistics[i].first; - entry; - entry = entry->next) - { - printf(" %s in %f sec\n", entry->object->id.name + 2, entry->duration); - } - - total_objects += thread_total_objects; - } - - BLI_freelistN(&state->statistics[i]); - } - if (state->has_updated_objects) { - printf("Scene updated %d objects in %f sec\n", - total_objects, - finish_time - state->base_time); - } -#endif -} - -static bool scene_need_update_objects(Main *bmain) -{ - return - /* Object datablocks themselves (for OB_RECALC_OB) */ - DAG_id_type_tagged(bmain, ID_OB) || - - /* Objects data datablocks (for OB_RECALC_DATA) */ - DAG_id_type_tagged(bmain, ID_ME) || /* Mesh */ - DAG_id_type_tagged(bmain, ID_CU) || /* Curve */ - DAG_id_type_tagged(bmain, ID_MB) || /* MetaBall */ - DAG_id_type_tagged(bmain, ID_LA) || /* Lamp */ - DAG_id_type_tagged(bmain, ID_LT) || /* Lattice */ - DAG_id_type_tagged(bmain, ID_CA) || /* Camera */ - DAG_id_type_tagged(bmain, ID_KE) || /* KE */ - DAG_id_type_tagged(bmain, ID_SPK) || /* Speaker */ - DAG_id_type_tagged(bmain, ID_AR); /* Armature */ -} - -static void scene_update_objects(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, Scene *scene_parent) -{ - TaskScheduler *task_scheduler; - TaskPool *task_pool; - ThreadedObjectUpdateState state; - bool need_singlethread_pass; - bool need_free_scheduler; - - /* Early check for whether we need to invoke all the task-based - * things (spawn new ppol, traverse dependency graph and so on). - * - * Basically if there's no ID datablocks tagged for update which - * corresponds to object->recalc flags (which are checked in - * BKE_object_handle_update() then we do nothing here. - */ - if (!scene_need_update_objects(bmain)) { - return; - } - - state.eval_ctx = eval_ctx; - state.scene = scene; - state.scene_parent = scene_parent; - - if (G.debug & G_DEBUG_DEPSGRAPH_NO_THREADS) { - task_scheduler = BLI_task_scheduler_create(1); - need_free_scheduler = true; - } - else { - task_scheduler = BLI_task_scheduler_get(); - need_free_scheduler = false; - } - - /* Those are only needed when blender is run with --debug argument. */ - if (G.debug & G_DEBUG_DEPSGRAPH) { - const int tot_thread = BLI_task_scheduler_num_threads(task_scheduler); - state.statistics = MEM_callocN(tot_thread * sizeof(*state.statistics), - "scene update objects stats"); - state.has_updated_objects = false; - state.base_time = PIL_check_seconds_timer(); - } - -#ifdef MBALL_SINGLETHREAD_HACK - state.has_mballs = false; -#endif - - task_pool = BLI_task_pool_create(task_scheduler, &state); - - DAG_threaded_update_begin(scene, scene_update_object_add_task, task_pool); - BLI_task_pool_work_and_wait(task_pool); - BLI_task_pool_free(task_pool); - - if (G.debug & G_DEBUG_DEPSGRAPH) { - print_threads_statistics(&state); - MEM_freeN(state.statistics); - } - - /* We do single thread pass to update all the objects which are in cyclic dependency. - * Such objects can not be handled by a generic DAG traverse and it's really tricky - * to detect whether cycle could be solved or not. - * - * In this situation we simply update all remaining objects in a single thread and - * it'll happen in the same exact order as it was in single-threaded DAG. - * - * We couldn't use threaded update for objects which are in cycle because they might - * access data of each other which is being re-evaluated. - * - * Also, as was explained above, for now we also update all the mballs in single thread. - * - * - sergey - - */ - need_singlethread_pass = DAG_is_acyclic(scene) == false; -#ifdef MBALL_SINGLETHREAD_HACK - need_singlethread_pass |= state.has_mballs; -#endif - - if (need_singlethread_pass) { - scene_update_all_bases(eval_ctx, scene, scene_parent); - } - - if (need_free_scheduler) { - BLI_task_scheduler_free(task_scheduler); - } -} - -static void scene_update_tagged_recursive(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, Scene *scene_parent) -{ - scene->customdata_mask = scene_parent->customdata_mask; - - /* sets first, we allow per definition current scene to have - * dependencies on sets, but not the other way around. */ - if (scene->set) - scene_update_tagged_recursive(eval_ctx, bmain, scene->set, scene_parent); - - /* scene objects */ - scene_update_objects(eval_ctx, bmain, scene, scene_parent); - - /* scene drivers... */ - scene_update_drivers(bmain, scene); - - /* update masking curves */ - BKE_mask_update_scene(bmain, scene); - -} -#endif /* WITH_LEGACY_DEPSGRAPH */ - static bool check_rendered_viewport_visible(Main *bmain) { wmWindowManager *wm = bmain->wm.first; wmWindow *window; for (window = wm->windows.first; window != NULL; window = window->next) { - bScreen *screen = window->screen; + const bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook); + WorkSpace *workspace = BKE_workspace_active_get(window->workspace_hook); + Scene *scene = window->scene; + ViewRender *view_render = BKE_viewrender_get(scene, workspace); ScrArea *area; + RenderEngineType *type = RE_engines_find(view_render->engine_id); + if ((type->draw_engine != NULL) || (type->render_to_view == NULL)) { + continue; + } + const bool use_legacy = (type->flag & RE_USE_LEGACY_PIPELINE) != 0; for (area = screen->areabase.first; area != NULL; area = area->next) { View3D *v3d = area->spacedata.first; if (area->spacetype != SPACE_VIEW3D) { continue; } - if (v3d->drawtype == OB_RENDER) { + if (v3d->drawtype == OB_RENDER || !use_legacy) { return true; } } @@ -1852,318 +1401,94 @@ static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene) if (check_rendered_viewport_visible(bmain)) { BMesh *bm = mesh->edit_btmesh->bm; BM_mesh_bm_to_me(bm, mesh, (&(struct BMeshToMeshParams){0})); - DAG_id_tag_update(&mesh->id, 0); + DEG_id_tag_update(&mesh->id, 0); } } } } -void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *scene) -{ - Scene *sce_iter; -#ifdef WITH_LEGACY_DEPSGRAPH - bool use_new_eval = !DEG_depsgraph_use_legacy(); -#endif - - /* keep this first */ - BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_PRE); - - /* (re-)build dependency graph if needed */ - for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set) { - DAG_scene_relations_update(bmain, sce_iter); - /* Uncomment this to check if dependency graph was properly tagged for update. */ -#if 0 -#ifdef WITH_LEGACY_DEPSGRAPH - if (use_new_eval) -#endif - { - DAG_scene_relations_validate(bmain, sce_iter); - } -#endif - } - - /* flush editing data if needed */ +/* TODO(sergey): This actually should become view_layer_graph or so. + * Same applies to update_for_newframe. + */ +void BKE_scene_graph_update_tagged(EvaluationContext *eval_ctx, + Depsgraph *depsgraph, + Main *bmain, + Scene *scene, + ViewLayer *view_layer) +{ + /* TODO(sergey): Temporary solution for until pipeline.c is ported. */ + if (view_layer == NULL) { + view_layer = DEG_get_evaluated_view_layer(depsgraph); + BLI_assert(view_layer != NULL); + } + /* TODO(sergey): Some functions here are changing global state, + * for example, clearing update tags from bmain. + */ + /* (Re-)build dependency graph if needed. */ + DEG_graph_relations_update(depsgraph, bmain, scene, view_layer); + /* Uncomment this to check if graph was properly tagged for update. */ + // DEG_debug_graph_relations_validate(depsgraph, bmain, scene); + /* Flush editing data if needed. */ prepare_mesh_for_viewport_render(bmain, scene); - - /* flush recalc flags to dependencies */ - DAG_ids_flush_tagged(bmain); - - /* removed calls to quick_cache, see pointcache.c */ - - /* clear "LIB_TAG_DOIT" flag from all materials, to prevent infinite recursion problems later - * when trying to find materials with drivers that need evaluating [#32017] + /* Flush recalc flags to dependencies. */ + DEG_graph_flush_update(bmain, depsgraph); + /* Update all objects: drivers, matrices, displists, etc. flags set + * by depgraph or manual, no layer check here, gets correct flushed. */ - BKE_main_id_tag_idcode(bmain, ID_MA, LIB_TAG_DOIT, false); - BKE_main_id_tag_idcode(bmain, ID_LA, LIB_TAG_DOIT, false); - - /* update all objects: drivers, matrices, displists, etc. flags set - * by depgraph or manual, no layer check here, gets correct flushed - * - * in the future this should handle updates for all datablocks, not - * only objects and scenes. - brecht */ -#ifdef WITH_LEGACY_DEPSGRAPH - if (!use_new_eval) { - scene_update_tagged_recursive(eval_ctx, bmain, scene, scene); - } - else -#endif - { - DEG_evaluate_on_refresh(eval_ctx, scene->depsgraph, scene); - } - - /* update sound system animation (TODO, move to depsgraph) */ + DEG_evaluate_on_refresh(eval_ctx, depsgraph); + /* Update sound system animation (TODO, move to depsgraph). */ BKE_sound_update_scene(bmain, scene); - - /* extra call here to recalc scene animation (for sequencer) */ - { - AnimData *adt = BKE_animdata_from_id(&scene->id); - float ctime = BKE_scene_frame_get(scene); - - if (adt && (adt->recalc & ADT_RECALC_ANIM)) - BKE_animsys_evaluate_animdata(scene, &scene->id, adt, ctime, 0); - } - - /* Extra call here to recalc material animation. - * - * Need to do this so changing material settings from the graph/dopesheet - * will update stuff in the viewport. - */ -#ifdef WITH_LEGACY_DEPSGRAPH - if (!use_new_eval && DAG_id_type_tagged(bmain, ID_MA)) { - Material *material; - float ctime = BKE_scene_frame_get(scene); - - for (material = bmain->mat.first; - material; - material = material->id.next) - { - AnimData *adt = BKE_animdata_from_id(&material->id); - if (adt && (adt->recalc & ADT_RECALC_ANIM)) - BKE_animsys_evaluate_animdata(scene, &material->id, adt, ctime, 0); - } - } - - /* Also do the same for node trees. */ - if (!use_new_eval && DAG_id_type_tagged(bmain, ID_NT)) { - float ctime = BKE_scene_frame_get(scene); - - FOREACH_NODETREE(bmain, ntree, id) - { - AnimData *adt = BKE_animdata_from_id(&ntree->id); - if (adt && (adt->recalc & ADT_RECALC_ANIM)) - BKE_animsys_evaluate_animdata(scene, &ntree->id, adt, ctime, 0); - } - FOREACH_NODETREE_END - } -#endif - - /* notify editors and python about recalc */ - BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_POST); - /* Inform editors about possible changes. */ - DAG_ids_check_recalc(bmain, scene, false); - - /* clear recalc flags */ - DAG_ids_clear_recalc(bmain); + DEG_ids_check_recalc(bmain, depsgraph, scene, view_layer, false); + /* Clear recalc flags. */ + DEG_ids_clear_recalc(bmain); } /* applies changes right away, does all sets too */ -void BKE_scene_update_for_newframe(EvaluationContext *eval_ctx, Main *bmain, Scene *sce, unsigned int lay) -{ - BKE_scene_update_for_newframe_ex(eval_ctx, bmain, sce, lay, false); -} - -void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain, Scene *sce, unsigned int lay, bool do_invisible_flush) -{ - float ctime = BKE_scene_frame_get(sce); - Scene *sce_iter; -#ifdef DETAILED_ANALYSIS_OUTPUT - double start_time = PIL_check_seconds_timer(); -#endif -#ifdef WITH_LEGACY_DEPSGRAPH - bool use_new_eval = !DEG_depsgraph_use_legacy(); -#else - /* TODO(sergey): Pass to evaluation routines instead of storing layer in the dependency graph? */ - (void) do_invisible_flush; -#endif - - DAG_editors_update_pre(bmain, sce, true); - - /* keep this first */ - BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_FRAME_CHANGE_PRE); - BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_SCENE_UPDATE_PRE); - - /* update animated image textures for particles, modifiers, gpu, etc, - * call this at the start so modifiers with textures don't lag 1 frame */ - BKE_image_update_frame(bmain, sce->r.cfra); - -#ifdef WITH_LEGACY_DEPSGRAPH - /* rebuild rigid body worlds before doing the actual frame update - * this needs to be done on start frame but animation playback usually starts one frame later - * we need to do it here to avoid rebuilding the world on every simulation change, which can be very expensive +void BKE_scene_graph_update_for_newframe(EvaluationContext *eval_ctx, + Depsgraph *depsgraph, + Main *bmain, + Scene *scene, + ViewLayer *view_layer) +{ + /* TODO(sergey): Temporary solution for until pipeline.c is ported. */ + if (view_layer == NULL) { + view_layer = DEG_get_evaluated_view_layer(depsgraph); + BLI_assert(view_layer != NULL); + } + /* TODO(sergey): Some functions here are changing global state, + * for example, clearing update tags from bmain. */ - if (!use_new_eval) { - scene_rebuild_rbw_recursive(sce, ctime); - } -#endif - - BKE_sound_set_cfra(sce->r.cfra); - - /* clear animation overrides */ - /* XXX TODO... */ - - for (sce_iter = sce; sce_iter; sce_iter = sce_iter->set) - DAG_scene_relations_update(bmain, sce_iter); - -#ifdef WITH_LEGACY_DEPSGRAPH - if (!use_new_eval) { - /* flush recalc flags to dependencies, if we were only changing a frame - * this would not be necessary, but if a user or a script has modified - * some datablock before BKE_scene_update_tagged was called, we need the flush */ - DAG_ids_flush_tagged(bmain); - - /* Following 2 functions are recursive - * so don't call within 'scene_update_tagged_recursive' */ - DAG_scene_update_flags(bmain, sce, lay, true, do_invisible_flush); // only stuff that moves or needs display still - BKE_mask_evaluate_all_masks(bmain, ctime, true); - } -#endif - - /* Update animated cache files for modifiers. */ - BKE_cachefile_update_frame(bmain, sce, ctime, (((double)sce->r.frs_sec) / (double)sce->r.frs_sec_base)); - + const float ctime = BKE_scene_frame_get(scene); + /* Keep this first. */ + BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_FRAME_CHANGE_PRE); + /* Update animated image textures for particles, modifiers, gpu, etc, + * call this at the start so modifiers with textures don't lag 1 frame. + */ + BKE_image_update_frame(bmain, scene->r.cfra); + BKE_sound_set_cfra(scene->r.cfra); + DEG_graph_relations_update(depsgraph, bmain, scene, view_layer); + /* Update animated cache files for modifiers. + * + * TODO(sergey): Make this a depsgraph node? + */ + BKE_cachefile_update_frame(bmain, scene, ctime, + (((double)scene->r.frs_sec) / (double)scene->r.frs_sec_base)); #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 - * can be overridden by settings from Scene, which owns the Texture through a hierarchy - * such as Scene->World->MTex/Texture) can still get correctly overridden. + /* Update all objects: drivers, matrices, displists, etc. flags set + * by depgraph or manual, no layer check here, gets correct flushed. */ -#ifdef WITH_LEGACY_DEPSGRAPH - if (!use_new_eval) { - BKE_animsys_evaluate_all_animation(bmain, sce, ctime); - /*...done with recursive funcs */ - } -#endif - - /* clear "LIB_TAG_DOIT" flag from all materials, to prevent infinite recursion problems later - * when trying to find materials with drivers that need evaluating [#32017] - */ - BKE_main_id_tag_idcode(bmain, ID_MA, LIB_TAG_DOIT, false); - BKE_main_id_tag_idcode(bmain, ID_LA, LIB_TAG_DOIT, false); - - /* run rigidbody sim */ - /* NOTE: current position is so that rigidbody sim affects other objects, might change in the future */ -#ifdef WITH_LEGACY_DEPSGRAPH - if (!use_new_eval) { - scene_do_rb_simulation_recursive(sce, ctime); - } -#endif - - /* BKE_object_handle_update() on all objects, groups and sets */ -#ifdef WITH_LEGACY_DEPSGRAPH - if (use_new_eval) { - DEG_evaluate_on_framechange(eval_ctx, bmain, sce->depsgraph, ctime, lay); - } - else { - scene_update_tagged_recursive(eval_ctx, bmain, sce, sce); - } -#else - DEG_evaluate_on_framechange(eval_ctx, bmain, sce->depsgraph, ctime, lay); -#endif - - /* update sound system animation (TODO, move to depsgraph) */ - BKE_sound_update_scene(bmain, sce); - -#ifdef WITH_LEGACY_DEPSGRAPH - if (!use_new_eval) { - scene_depsgraph_hack(eval_ctx, sce, sce); - } -#endif - - /* notify editors and python about recalc */ - BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_SCENE_UPDATE_POST); - BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_FRAME_CHANGE_POST); - + DEG_evaluate_on_framechange(eval_ctx, bmain, depsgraph, ctime); + /* Update sound system animation (TODO, move to depsgraph). */ + BKE_sound_update_scene(bmain, scene); + /* Notify editors and python about recalc. */ + BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_FRAME_CHANGE_POST); /* Inform editors about possible changes. */ - DAG_ids_check_recalc(bmain, sce, true); - + DEG_ids_check_recalc(bmain, depsgraph, scene, view_layer, true); /* clear recalc flags */ - DAG_ids_clear_recalc(bmain); - -#ifdef DETAILED_ANALYSIS_OUTPUT - fprintf(stderr, "frame update start_time %f duration %f\n", start_time, PIL_check_seconds_timer() - start_time); -#endif -} - -/* return default layer, also used to patch old files */ -SceneRenderLayer *BKE_scene_add_render_layer(Scene *sce, const char *name) -{ - SceneRenderLayer *srl; - - if (!name) - name = DATA_("RenderLayer"); - - srl = MEM_callocN(sizeof(SceneRenderLayer), "new render layer"); - BLI_strncpy(srl->name, name, sizeof(srl->name)); - BLI_uniquename(&sce->r.layers, srl, DATA_("RenderLayer"), '.', offsetof(SceneRenderLayer, name), sizeof(srl->name)); - BLI_addtail(&sce->r.layers, srl); - - /* note, this is also in render, pipeline.c, to make layer when scenedata doesnt have it */ - srl->lay = (1 << 20) - 1; - srl->layflag = 0x7FFF; /* solid ztra halo edge strand */ - srl->passflag = SCE_PASS_COMBINED | SCE_PASS_Z; - srl->pass_alpha_threshold = 0.5f; - BKE_freestyle_config_init(&srl->freestyleConfig); - - return srl; -} - -bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer *srl) -{ - const int act = BLI_findindex(&scene->r.layers, srl); - Scene *sce; - - if (act == -1) { - return false; - } - else if ( (scene->r.layers.first == scene->r.layers.last) && - (scene->r.layers.first == srl)) - { - /* ensure 1 layer is kept */ - return false; - } - - BKE_freestyle_config_free(&srl->freestyleConfig); - - if (srl->prop) { - IDP_FreeProperty(srl->prop); - MEM_freeN(srl->prop); - } - - BLI_remlink(&scene->r.layers, srl); - MEM_freeN(srl); - - scene->r.actlay = 0; - - for (sce = bmain->scene.first; sce; sce = sce->id.next) { - if (sce->nodetree) { - bNode *node; - for (node = sce->nodetree->nodes.first; node; node = node->next) { - if (node->type == CMP_NODE_R_LAYERS && (Scene *)node->id == scene) { - if (node->custom1 == act) - node->custom1 = 0; - else if (node->custom1 > act) - node->custom1--; - } - } - } - } - - return true; + DEG_ids_clear_recalc(bmain); } /* return default view */ @@ -2246,21 +1571,34 @@ float get_render_aosss_error(const RenderData *r, float error) return error; } -/* helper function for the SETLOOPER macro */ -Base *_setlooper_base_step(Scene **sce_iter, Base *base) +/** + * Helper function for the SETLOOPER and SETLOOPER_VIEW_LAYER macros + * + * It iterates over the bases of the active layer and then the bases + * of the active layer of the background (set) scenes recursively. + */ +Base *_setlooper_base_step(Scene **sce_iter, ViewLayer *view_layer, Base *base) { if (base && base->next) { - /* common case, step to the next */ + /* Common case, step to the next. */ return base->next; } - else if (base == NULL && (*sce_iter)->base.first) { - /* first time looping, return the scenes first base */ - return (Base *)(*sce_iter)->base.first; + else if ((base == NULL) && (view_layer != NULL)) { + /* First time looping, return the scenes first base. */ + /* For the first loop we should get the layer from workspace when available. */ + if (view_layer->object_bases.first) { + return (Base *)view_layer->object_bases.first; + } + /* No base on this scene layer. */ + goto next_set; } else { - /* reached the end, get the next base in the set */ +next_set: + /* Reached the end, get the next base in the set. */ while ((*sce_iter = (*sce_iter)->set)) { - base = (Base *)(*sce_iter)->base.first; + ViewLayer *view_layer_set = BKE_view_layer_from_scene_get((*sce_iter)); + base = (Base *)view_layer_set->object_bases.first; + if (base) { return base; } @@ -2272,56 +1610,80 @@ Base *_setlooper_base_step(Scene **sce_iter, Base *base) bool BKE_scene_use_new_shading_nodes(const Scene *scene) { - const RenderEngineType *type = RE_engines_find(scene->r.engine); - return (type && type->flag & RE_USE_SHADING_NODES); + return BKE_viewrender_use_new_shading_nodes(&scene->view_render); } bool BKE_scene_use_shading_nodes_custom(Scene *scene) { - RenderEngineType *type = RE_engines_find(scene->r.engine); - return (type && type->flag & RE_USE_SHADING_NODES_CUSTOM); + return BKE_viewrender_use_shading_nodes_custom(&scene->view_render); } bool BKE_scene_use_world_space_shading(Scene *scene) { - const RenderEngineType *type = RE_engines_find(scene->r.engine); + RenderEngineType *type = RE_engines_find(scene->view_render.engine_id); return ((scene->r.mode & R_USE_WS_SHADING) || (type && (type->flag & RE_USE_SHADING_NODES))); } bool BKE_scene_use_spherical_stereo(Scene *scene) { - RenderEngineType *type = RE_engines_find(scene->r.engine); - return (type && type->flag & RE_USE_SPHERICAL_STEREO); + return BKE_viewrender_use_spherical_stereo(&scene->view_render); } -bool BKE_scene_uses_blender_internal(const Scene *scene) +bool BKE_scene_uses_blender_internal(const Scene *scene) { - return STREQ(scene->r.engine, RE_engine_id_BLENDER_RENDER); + return BKE_viewrender_uses_blender_internal(&scene->view_render); } bool BKE_scene_uses_blender_game(const Scene *scene) { - return STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME); + return BKE_viewrender_uses_blender_game(&scene->view_render); +} + +bool BKE_scene_uses_blender_eevee(const Scene *scene) +{ + return BKE_viewrender_uses_blender_eevee(&scene->view_render); } -void BKE_scene_base_flag_to_objects(struct Scene *scene) +void BKE_scene_base_flag_to_objects(ViewLayer *view_layer) { - Base *base = scene->base.first; + Base *base = view_layer->object_bases.first; while (base) { - base->object->flag = base->flag; + BKE_scene_object_base_flag_sync_from_base(base); base = base->next; } } -void BKE_scene_base_flag_from_objects(struct Scene *scene) +void BKE_scene_object_base_flag_sync_from_base(Base *base) { - Base *base = scene->base.first; + Object *ob = base->object; - while (base) { - base->flag = base->object->flag; - base = base->next; + /* keep the object only flags untouched */ + int flag = ob->flag & OB_FROMGROUP; + + ob->flag = base->flag; + ob->flag |= flag; + + if ((base->flag & BASE_SELECTED) != 0) { + ob->flag |= SELECT; + } + else { + ob->flag &= ~SELECT; + } +} + +void BKE_scene_object_base_flag_sync_from_object(Base *base) +{ + Object *ob = base->object; + base->flag = ob->flag; + + if ((ob->flag & SELECT) != 0) { + base->flag |= BASE_SELECTED; + BLI_assert((base->flag & BASE_SELECTABLED) != 0); + } + else { + base->flag &= ~BASE_SELECTED; } } @@ -2385,6 +1747,81 @@ int BKE_render_preview_pixel_size(const RenderData *r) return r->preview_pixel_size; } +/* ***************************************************** */ +/* render engine settings */ + +ViewRender *BKE_viewrender_get(Scene *scene, WorkSpace *workspace) +{ + if (workspace == NULL || BKE_workspace_use_scene_settings_get(workspace)) { + return &scene->view_render; + } + return BKE_workspace_view_render_get(workspace); +} + +/** + * Initialize a static created struct for WorkSpace and Scene to store the viewport + * related drawing data. + */ +void BKE_viewrender_init(ViewRender *view_render) +{ + BLI_strncpy(view_render->engine_id, RE_engine_id_BLENDER_EEVEE, sizeof(view_render->engine_id)); +} + +/** + * Do not free ViewRender itself since it's not even allocated. + */ +void BKE_viewrender_free(ViewRender *UNUSED(view_render)) +{ + /* Do nothing. */ +} + +/** + * Copy used by libblock copying. + */ +void BKE_viewrender_copy(ViewRender *to, const ViewRender *from) +{ + *to = *from; +} + +bool BKE_viewrender_use_new_shading_nodes(const ViewRender *view_render) +{ + RenderEngineType *type = RE_engines_find(view_render->engine_id); + return (type && type->flag & RE_USE_SHADING_NODES); +} + +bool BKE_viewrender_use_shading_nodes_custom(const ViewRender *view_render) +{ + RenderEngineType *type = RE_engines_find(view_render->engine_id); + return (type && type->flag & RE_USE_SHADING_NODES_CUSTOM); +} + +bool BKE_viewrender_use_spherical_stereo(const ViewRender *view_render) +{ + const char *engine_id = view_render->engine_id; + RenderEngineType *type = RE_engines_find(engine_id); + return (type && type->flag & RE_USE_SPHERICAL_STEREO); +} + +bool BKE_viewrender_uses_blender_internal(const ViewRender *view_render) +{ + const char *engine_id = view_render->engine_id; + return STREQ(engine_id, RE_engine_id_BLENDER_RENDER); +} + +bool BKE_viewrender_uses_blender_game(const ViewRender *view_render) +{ + const char *engine_id = view_render->engine_id; + return STREQ(engine_id, RE_engine_id_BLENDER_GAME); +} + +bool BKE_viewrender_uses_blender_eevee(const ViewRender *view_render) +{ + const char *engine_id = view_render->engine_id; + return STREQ(engine_id, RE_engine_id_BLENDER_EEVEE); +} + +/* ***************************************************** */ + /* Apply the needed correction factor to value, based on unit_type (only length-related are affected currently) * and unit->scale_length. */ @@ -2690,3 +2127,106 @@ int BKE_scene_multiview_num_videos_get(const RenderData *rd) return BKE_scene_multiview_num_views_get(rd); } } + +/* Manipulation of depsgraph storage. */ + +/* This is a key which identifies depsgraph. */ +typedef struct DepsgraphKey { + ViewLayer *view_layer; + /* TODO(sergey): Need to include window somehow (same layer might be in a + * different states in different windows). + */ +} DepsgraphKey; + +static unsigned int depsgraph_key_hash(const void *key_v) +{ + const DepsgraphKey *key = key_v; + unsigned int hash = BLI_ghashutil_ptrhash(key->view_layer); + /* TODO(sergey): Include hash from other fields in the key. */ + return hash; +} + +static bool depsgraph_key_compare(const void *key_a_v, const void *key_b_v) +{ + const DepsgraphKey *key_a = key_a_v; + const DepsgraphKey *key_b = key_b_v; + /* TODO(sergey): Compare rest of */ + return !(key_a->view_layer == key_b->view_layer); +} + +static void depsgraph_key_free(void *key_v) +{ + DepsgraphKey *key = key_v; + MEM_freeN(key); +} + +static void depsgraph_key_value_free(void *value) +{ + Depsgraph *depsgraph = value; + DEG_graph_free(depsgraph); +} + +void BKE_scene_allocate_depsgraph_hash(Scene *scene) +{ + scene->depsgraph_hash = BLI_ghash_new(depsgraph_key_hash, + depsgraph_key_compare, + "Scene Depsgraph Hash"); +} + +void BKE_scene_ensure_depsgraph_hash(Scene *scene) +{ + if (scene->depsgraph_hash == NULL) { + BKE_scene_allocate_depsgraph_hash(scene); + } +} + +void BKE_scene_free_depsgraph_hash(Scene *scene) +{ + if (scene->depsgraph_hash == NULL) { + return; + } + BLI_ghash_free(scene->depsgraph_hash, + depsgraph_key_free, + depsgraph_key_value_free); +} + +/* Query depsgraph for a specific contexts. */ + +Depsgraph *BKE_scene_get_depsgraph(Scene *scene, + ViewLayer *view_layer, + bool allocate) +{ + BLI_assert(scene != NULL); + BLI_assert(view_layer != NULL); + /* Make sure hash itself exists. */ + if (allocate) { + BKE_scene_ensure_depsgraph_hash(scene); + } + if (scene->depsgraph_hash == NULL) { + return NULL; + } + /* Either ensure item is in the hash or simply return NULL if it's not, + * depending on whether caller wants us to create depsgraph or not. + */ + DepsgraphKey key; + key.view_layer = view_layer; + Depsgraph *depsgraph; + if (allocate) { + DepsgraphKey **key_ptr; + Depsgraph **depsgraph_ptr; + if (!BLI_ghash_ensure_p_ex(scene->depsgraph_hash, + &key, + (void ***)&key_ptr, + (void ***)&depsgraph_ptr)) + { + *key_ptr = MEM_mallocN(sizeof(DepsgraphKey), __func__); + **key_ptr = key; + *depsgraph_ptr = DEG_graph_new(); + } + depsgraph = *depsgraph_ptr; + } + else { + depsgraph = BLI_ghash_lookup(scene->depsgraph_hash, &key); + } + return depsgraph; +} diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 78caf1fe1f3..754f59d2e33 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -45,13 +45,16 @@ #include "DNA_screen_types.h" #include "DNA_space_types.h" #include "DNA_view3d_types.h" +#include "DNA_workspace_types.h" #include "BLI_listbase.h" #include "BLI_utildefines.h" #include "BLI_rect.h" +#include "BKE_icons.h" #include "BKE_idprop.h" #include "BKE_screen.h" +#include "BKE_workspace.h" /* ************ Spacetype/regiontype handling ************** */ @@ -180,6 +183,7 @@ ARegion *BKE_area_region_copy(SpaceType *st, ARegion *ar) BLI_listbase_clear(&newar->panels_category_active); BLI_listbase_clear(&newar->ui_lists); newar->swinid = 0; + newar->manipulator_map = NULL; newar->regiontimer = NULL; newar->headerstr = NULL; @@ -289,6 +293,43 @@ void BKE_spacedata_id_unref(struct ScrArea *sa, struct SpaceLink *sl, struct ID } } +/** + * Avoid bad-level calls to #WM_manipulatormap_tag_refresh. + */ +static void (*region_refresh_tag_manipulatormap_callback)(struct wmManipulatorMap *) = NULL; + +void BKE_region_callback_refresh_tag_manipulatormap_set(void (*callback)(struct wmManipulatorMap *)) +{ + region_refresh_tag_manipulatormap_callback = callback; +} + +void BKE_screen_manipulator_tag_refresh(struct bScreen *sc) +{ + if (region_refresh_tag_manipulatormap_callback == NULL) { + return; + } + + ScrArea *sa; + ARegion *ar; + for (sa = sc->areabase.first; sa; sa = sa->next) { + for (ar = sa->regionbase.first; ar; ar = ar->next) { + if (ar->manipulator_map != NULL) { + region_refresh_tag_manipulatormap_callback(ar->manipulator_map); + } + } + } +} + +/** + * Avoid bad-level calls to #WM_manipulatormap_delete. + */ +static void (*region_free_manipulatormap_callback)(struct wmManipulatorMap *) = NULL; + +void BKE_region_callback_free_manipulatormap_set(void (*callback)(struct wmManipulatorMap *)) +{ + region_free_manipulatormap_callback = callback; +} + /* not region itself */ void BKE_area_region_free(SpaceType *st, ARegion *ar) { @@ -338,6 +379,11 @@ void BKE_area_region_free(SpaceType *st, ARegion *ar) MEM_freeN(uilst->properties); } } + + if (ar->manipulator_map != NULL) { + region_free_manipulatormap_callback(ar->manipulator_map); + } + BLI_freelistN(&ar->ui_lists); BLI_freelistN(&ar->ui_previews); BLI_freelistN(&ar->panels_category); @@ -382,6 +428,8 @@ void BKE_screen_free(bScreen *sc) BLI_freelistN(&sc->edgebase); BLI_freelistN(&sc->areabase); + BKE_previewimg_free(&sc->preview); + /* Region and timer are freed by the window manager. */ MEM_SAFE_FREE(sc->tool_tip); } @@ -583,7 +631,7 @@ void BKE_screen_view3d_sync(View3D *v3d, struct Scene *scene) } } -void BKE_screen_view3d_scene_sync(bScreen *sc) +void BKE_screen_view3d_scene_sync(bScreen *sc, Scene *scene) { /* are there cameras in the views that are not in the scene? */ ScrArea *sa; @@ -592,55 +640,26 @@ void BKE_screen_view3d_scene_sync(bScreen *sc) for (sl = sa->spacedata.first; sl; sl = sl->next) { if (sl->spacetype == SPACE_VIEW3D) { View3D *v3d = (View3D *) sl; - BKE_screen_view3d_sync(v3d, sc->scene); + BKE_screen_view3d_sync(v3d, scene); } } } } -void BKE_screen_view3d_main_sync(ListBase *screen_lb, Scene *scene) +void BKE_screen_transform_orientation_remove( + const bScreen *screen, const WorkSpace *workspace, const TransformOrientation *orientation) { - bScreen *sc; - ScrArea *sa; - SpaceLink *sl; + const int orientation_index = BKE_workspace_transform_orientation_get_index(workspace, orientation); - /* from scene copy to the other views */ - for (sc = screen_lb->first; sc; sc = sc->id.next) { - if (sc->scene != scene) - continue; - - for (sa = sc->areabase.first; sa; sa = sa->next) - for (sl = sa->spacedata.first; sl; sl = sl->next) - if (sl->spacetype == SPACE_VIEW3D) - BKE_screen_view3d_sync((View3D *)sl, scene); - } -} - -void BKE_screen_view3d_twmode_remove(View3D *v3d, const int i) -{ - const int selected_index = (v3d->twmode - V3D_MANIP_CUSTOM); - if (selected_index == i) { - v3d->twmode = V3D_MANIP_GLOBAL; /* fallback to global */ - } - else if (selected_index > i) { - v3d->twmode--; - } -} - -void BKE_screen_view3d_main_twmode_remove(ListBase *screen_lb, Scene *scene, const int i) -{ - bScreen *sc; + for (ScrArea *area = screen->areabase.first; area; area = area->next) { + for (SpaceLink *sl = area->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_VIEW3D) { + View3D *v3d = (View3D *)sl; - for (sc = screen_lb->first; sc; sc = sc->id.next) { - if (sc->scene == scene) { - ScrArea *sa; - for (sa = sc->areabase.first; sa; sa = sa->next) { - SpaceLink *sl; - for (sl = sa->spacedata.first; sl; sl = sl->next) { - if (sl->spacetype == SPACE_VIEW3D) { - View3D *v3d = (View3D *)sl; - BKE_screen_view3d_twmode_remove(v3d, i); - } + if (v3d->custom_orientation_index == orientation_index) { + /* could also use orientation_index-- */ + v3d->twmode = V3D_MANIP_GLOBAL; + v3d->custom_orientation_index = -1; } } } @@ -687,3 +706,13 @@ void BKE_screen_gpu_fx_validate(GPUFXSettings *fx_settings) GPU_fx_compositor_init_ssao_settings(fx_ssao); } } + +bool BKE_screen_is_fullscreen_area(const bScreen *screen) +{ + return ELEM(screen->state, SCREENMAXIMIZED, SCREENFULL); +} + +bool BKE_screen_is_used(const bScreen *screen) +{ + return (screen->winid != 0); +} diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index 11ee8a5ca6f..424f4269f3c 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -63,9 +63,9 @@ #include "BLT_translation.h" #include "BKE_animsys.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_image.h" +#include "BKE_layer.h" #include "BKE_main.h" #include "BKE_sequencer.h" #include "BKE_movieclip.h" @@ -75,6 +75,8 @@ #include "BKE_library.h" #include "BKE_idprop.h" +#include "DEG_depsgraph.h" + #include "RNA_access.h" #include "RE_pipeline.h" @@ -88,8 +90,10 @@ #include "BKE_context.h" #include "BKE_sound.h" +#include "RE_engine.h" + #ifdef WITH_AUDASPACE -# include AUD_SPECIAL_H +# include <AUD_Special.h> #endif /* mutable state for sequencer */ @@ -3260,6 +3264,10 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq // have_seq = (scene->r.scemode & R_DOSEQ) && scene->ed && scene->ed->seqbase.first); /* UNUSED */ have_comp = (scene->r.scemode & R_DOCOMP) && scene->use_nodes && scene->nodetree; + /* Get depsgraph and scene layer for the strip. */ + ViewLayer *view_layer = BKE_view_layer_from_scene_get(scene); + Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true); + orig_data.scemode = scene->r.scemode; orig_data.cfra = scene->r.cfra; orig_data.subframe = scene->r.subframe; @@ -3315,10 +3323,12 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq context->scene->r.seq_prev_type = 3 /* == OB_SOLID */; /* opengl offscreen render */ - BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay); + context->eval_ctx->engine_type = RE_engines_find(scene->view_render.engine_id); + BKE_scene_graph_update_for_newframe(context->eval_ctx, depsgraph, context->bmain, scene, view_layer); ibuf = sequencer_view3d_cb( /* set for OpenGL render (NULL when scrubbing) */ - scene, camera, width, height, IB_rect, draw_flags, context->scene->r.seq_prev_type, + context->eval_ctx, scene, view_layer, camera, width, height, IB_rect, + draw_flags, context->scene->r.seq_prev_type, scene->r.alphamode, context->gpu_samples, viewname, context->gpu_fx, context->gpu_offscreen, err_out); if (ibuf == NULL) { @@ -3345,7 +3355,14 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq if (re == NULL) re = RE_NewSceneRender(scene); - BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay); + /* NOTE: Without this tag rendering from command line fails. + * TODO(sergey): Need some proper solution with ported + * BKE_scene_set_background() or DEG_on_visible_change() ? + */ + RE_SetDepsgraph(re, depsgraph); + DEG_graph_id_tag_update(context->bmain, depsgraph, &scene->id, 0); + + BKE_scene_graph_update_for_newframe(context->eval_ctx, depsgraph, context->bmain, scene, view_layer); RE_BlenderFrame(re, context->bmain, scene, NULL, camera, scene->lay, frame, false); /* restore previous state after it was toggled on & off by RE_BlenderFrame */ @@ -3405,7 +3422,7 @@ finally: scene->r.subframe = orig_data.subframe; if (is_frame_update) { - BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay); + BKE_scene_graph_update_for_newframe(context->eval_ctx, depsgraph, context->bmain, scene, view_layer); } #ifdef DURIAN_CAMERA_SWITCH diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 618f495dbf1..e91c3e43b83 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -57,6 +57,8 @@ #include "BLI_strict_flags.h" +#include "DEG_depsgraph.h" + /* for timing... */ #if 0 # include "PIL_time_utildefines.h" @@ -614,8 +616,9 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) } /* Main shrinkwrap function */ -void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedMesh *dm, - float (*vertexCos)[3], int numVerts, bool for_render) +void shrinkwrapModifier_deform( + const EvaluationContext *eval_ctx, ShrinkwrapModifierData *smd, Object *ob, DerivedMesh *dm, + float (*vertexCos)[3], int numVerts, bool for_render) { DerivedMesh *ss_mesh = NULL; @@ -670,7 +673,8 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM ssmd.subdivType = ME_CC_SUBSURF; /* catmull clark */ ssmd.levels = smd->subsurfLevels; /* levels */ - ss_mesh = subsurf_make_derived_from_derived(dm, &ssmd, NULL, (ob->mode & OB_MODE_EDIT) ? SUBSURF_IN_EDIT_MODE : 0); + ss_mesh = subsurf_make_derived_from_derived( + dm, &ssmd, NULL, (eval_ctx->object_mode & OB_MODE_EDIT) ? SUBSURF_IN_EDIT_MODE : 0); if (ss_mesh) { calc.vert = ss_mesh->getVertDataArray(ss_mesh, CD_MVERT); diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 3cf98b284b1..9f9818127bc 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -83,6 +83,8 @@ #include "BKE_smoke.h" #include "BKE_texture.h" +#include "DEG_depsgraph.h" + #include "RE_shader_ext.h" #include "GPU_glew.h" @@ -126,7 +128,7 @@ void smoke_initWaveletBlenderRNA(struct WTURBULENCE *UNUSED(wt), float *UNUSED(s void smoke_initBlenderRNA(struct FLUID_3D *UNUSED(fluid), float *UNUSED(alpha), float *UNUSED(beta), float *UNUSED(dt_factor), float *UNUSED(vorticity), int *UNUSED(border_colli), float *UNUSED(burning_rate), float *UNUSED(flame_smoke), float *UNUSED(flame_smoke_color), float *UNUSED(flame_vorticity), float *UNUSED(flame_ignition_temp), float *UNUSED(flame_max_temp)) {} -struct DerivedMesh *smokeModifier_do(SmokeModifierData *UNUSED(smd), Scene *UNUSED(scene), Object *UNUSED(ob), DerivedMesh *UNUSED(dm)) { return NULL; } +struct DerivedMesh *smokeModifier_do(SmokeModifierData *UNUSED(smd), const struct EvaluationContext *UNUSED(eval_ctx), Scene *UNUSED(scene), Object *UNUSED(ob), DerivedMesh *UNUSED(dm)) { return NULL; } float smoke_get_velocity_at(struct Object *UNUSED(ob), float UNUSED(position[3]), float UNUSED(velocity[3])) { return 0.0f; } #endif /* WITH_SMOKE */ @@ -693,16 +695,16 @@ void smokeModifier_copy(struct SmokeModifierData *smd, struct SmokeModifierData #ifdef WITH_SMOKE // forward decleration -static void smoke_calc_transparency(SmokeDomainSettings *sds, Scene *scene); +static void smoke_calc_transparency(SmokeDomainSettings *sds, ViewLayer *view_layer); static float calc_voxel_transp(float *result, float *input, int res[3], int *pixel, float *tRay, float correct); -static int get_lamp(Scene *scene, float *light) +static int get_lamp(ViewLayer *view_layer, float *light) { Base *base_tmp = NULL; int found_lamp = 0; // try to find a lamp, preferably local - for (base_tmp = scene->base.first; base_tmp; base_tmp = base_tmp->next) { + for (base_tmp = FIRSTBASE(view_layer); base_tmp; base_tmp = base_tmp->next) { if (base_tmp->object->type == OB_LAMP) { Lamp *la = base_tmp->object->data; @@ -2097,7 +2099,7 @@ BLI_INLINE void apply_inflow_fields(SmokeFlowSettings *sfs, float emission_value } } -static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sds, float dt) +static void update_flowsfluids(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, SmokeDomainSettings *sds, float dt) { Object **flowobjs = NULL; EmissionMap *emaps = NULL; @@ -2204,7 +2206,7 @@ static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sd else { /* MOD_SMOKE_FLOW_SOURCE_MESH */ /* update flow object frame */ BLI_mutex_lock(&object_update_lock); - BKE_object_modifier_update_subframe(scene, collob, true, 5, BKE_scene_frame_get(scene), eModifierType_Smoke); + BKE_object_modifier_update_subframe(eval_ctx, scene, collob, true, 5, BKE_scene_frame_get(scene), eModifierType_Smoke); BLI_mutex_unlock(&object_update_lock); /* apply flow */ @@ -2516,12 +2518,12 @@ static void update_effectors_task_cb( } } -static void update_effectors(Scene *scene, Object *ob, SmokeDomainSettings *sds, float UNUSED(dt)) +static void update_effectors(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, SmokeDomainSettings *sds, float UNUSED(dt)) { ListBase *effectors; /* make sure smoke flow influence is 0.0f */ sds->effector_weights->weight[PFIELD_SMOKEFLOW] = 0.0f; - effectors = pdInitEffectors(scene, ob, NULL, sds->effector_weights, true); + effectors = pdInitEffectors(eval_ctx, scene, ob, NULL, sds->effector_weights, true); if (effectors) { // precalculate wind forces @@ -2551,7 +2553,7 @@ static void update_effectors(Scene *scene, Object *ob, SmokeDomainSettings *sds, pdEndEffectors(&effectors); } -static void step(Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh *domain_dm, float fps) +static void step(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh *domain_dm, float fps) { SmokeDomainSettings *sds = smd->domain; /* stability values copied from wturbulence.cpp */ @@ -2621,11 +2623,11 @@ static void step(Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh * for (substep = 0; substep < totalSubsteps; substep++) { // calc animated obstacle velocities - update_flowsfluids(scene, ob, sds, dtSubdiv); + update_flowsfluids(eval_ctx, scene, ob, sds, dtSubdiv); update_obstacles(scene, ob, sds, dtSubdiv, substep, totalSubsteps); if (sds->total_cells > 1) { - update_effectors(scene, ob, sds, dtSubdiv); // DG TODO? problem --> uses forces instead of velocity, need to check how they need to be changed with variable dt + update_effectors(eval_ctx, scene, ob, sds, dtSubdiv); // DG TODO? problem --> uses forces instead of velocity, need to check how they need to be changed with variable dt smoke_step(sds->fluid, gravity, dtSubdiv); } } @@ -2718,7 +2720,8 @@ static DerivedMesh *createDomainGeometry(SmokeDomainSettings *sds, Object *ob) return result; } -static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm) +static void smokeModifier_process( + SmokeModifierData *smd, const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, DerivedMesh *dm) { if ((smd->type & MOD_SMOKE_TYPE_FLOW)) { @@ -2839,11 +2842,11 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object * } - step(scene, ob, smd, dm, scene->r.frs_sec / scene->r.frs_sec_base); + step(eval_ctx, scene, ob, smd, dm, scene->r.frs_sec / scene->r.frs_sec_base); } // create shadows before writing cache so they get stored - smoke_calc_transparency(sds, scene); + smoke_calc_transparency(sds, eval_ctx->view_layer); if (sds->wt && sds->total_cells > 1) { smoke_turbulence_step(sds->wt, sds->fluid); @@ -2860,13 +2863,14 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object * } } -struct DerivedMesh *smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm) +struct DerivedMesh *smokeModifier_do( + SmokeModifierData *smd, const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, DerivedMesh *dm) { /* lock so preview render does not read smoke data while it gets modified */ if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) BLI_rw_mutex_lock(smd->domain->fluid_mutex, THREAD_LOCK_WRITE); - smokeModifier_process(smd, scene, ob, dm); + smokeModifier_process(smd, eval_ctx, scene, ob, dm); if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) BLI_rw_mutex_unlock(smd->domain->fluid_mutex); @@ -2981,7 +2985,7 @@ static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, f cb(result, input, res, pixel, tRay, correct); } -static void smoke_calc_transparency(SmokeDomainSettings *sds, Scene *scene) +static void smoke_calc_transparency(SmokeDomainSettings *sds, ViewLayer *view_layer) { float bv[6] = {0}; float light[3]; @@ -2989,7 +2993,7 @@ static void smoke_calc_transparency(SmokeDomainSettings *sds, Scene *scene) float *density = smoke_get_density(sds->fluid); float correct = -7.0f * sds->dx; - if (!get_lamp(scene, light)) return; + if (!get_lamp(view_layer, light)) return; /* convert light pos to sim cell space */ mul_m4_v3(sds->imat, light); diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c index 563148992d9..3cfa8787f4b 100644 --- a/source/blender/blenkernel/intern/softbody.c +++ b/source/blender/blenkernel/intern/softbody.c @@ -74,6 +74,7 @@ variables on the UI for now #include "BKE_curve.h" #include "BKE_effect.h" #include "BKE_global.h" +#include "BKE_group.h" #include "BKE_modifier.h" #include "BKE_softbody.h" #include "BKE_pointcache.h" @@ -81,6 +82,8 @@ variables on the UI for now #include "BKE_mesh.h" #include "BKE_scene.h" +#include "DEG_depsgraph.h" + #include "PIL_time.h" /* callbacks for errors and interrupts and some goo */ @@ -512,35 +515,26 @@ static void ccd_build_deflector_hash_single(GHash *hash, Object *ob) /** * \note group overrides scene when not NULL. */ -static void ccd_build_deflector_hash(Scene *scene, Group *group, Object *vertexowner, GHash *hash) +static void ccd_build_deflector_hash(ViewLayer *view_layer, Group *group, Object *vertexowner, GHash *hash) { Object *ob; if (!hash) return; + /* Explicit collision group. */ if (group) { - /* Explicit collision group */ - for (GroupObject *go = group->gobject.first; go; go = go->next) { - ob = go->ob; - - if (ob == vertexowner || ob->type != OB_MESH) - continue; - - ccd_build_deflector_hash_single(hash, ob); - } + view_layer = group->view_layer; } - else { - for (Base *base = scene->base.first; base; base = base->next) { - /*Only proceed for mesh object in same layer */ - if (base->object->type == OB_MESH && (base->lay & vertexowner->lay)) { - ob= base->object; - if ((vertexowner) && (ob == vertexowner)) { - /* if vertexowner is given we don't want to check collision with owner object */ - continue; - } - ccd_build_deflector_hash_single(hash, ob); + for (Base *base = FIRSTBASE(view_layer); base; base = base->next) { + /* Only proceed for mesh object in same layer. */ + if (base->object->type == OB_MESH) { + ob = base->object; + if (ob == vertexowner) { + /* If vertexowner is given we don't want to check collision with owner object. */ + continue; } + ccd_build_deflector_hash_single(hash, ob); } } } @@ -558,37 +552,29 @@ static void ccd_update_deflector_hash_single(GHash *hash, Object *ob) /** * \note group overrides scene when not NULL. */ -static void ccd_update_deflector_hash(Scene *scene, Group *group, Object *vertexowner, GHash *hash) +static void ccd_update_deflector_hash(ViewLayer *view_layer, Group *group, Object *vertexowner, GHash *hash) { Object *ob; if ((!hash) || (!vertexowner)) return; + /* Explicit collision group. */ if (group) { - /* Explicit collision group */ - for (GroupObject *go = group->gobject.first; go; go = go->next) { - ob = go->ob; + view_layer = group->view_layer; + } - if (ob == vertexowner || ob->type != OB_MESH) + for (Base *base = FIRSTBASE(view_layer); base; base = base->next) { + /* Only proceed for mesh object in same layer. */ + if (base->object->type == OB_MESH) { + ob = base->object; + if (ob == vertexowner) { + /* If vertexowner is given we don't want to check collision with owner object. */ continue; + } ccd_update_deflector_hash_single(hash, ob); } } - else { - for (Base *base = scene->base.first; base; base = base->next) { - /*Only proceed for mesh object in same layer */ - if (base->object->type == OB_MESH && (base->lay & vertexowner->lay)) { - ob= base->object; - if (ob == vertexowner) { - /* if vertexowner is given we don't want to check collision with owner object */ - continue; - } - - ccd_update_deflector_hash_single(hash, ob); - } - } - } } @@ -977,29 +963,21 @@ static void free_softbody_intern(SoftBody *sb) /** * \note group overrides scene when not NULL. */ -static bool are_there_deflectors(Scene *scene, Group *group, unsigned int layer) +static bool are_there_deflectors(ViewLayer *view_layer) { - if (group) { - for (GroupObject *go = group->gobject.first; go; go = go->next) { - if (go->ob->pd && go->ob->pd->deflect) + for (Base *base = FIRSTBASE(view_layer); base; base = base->next) { + if (base->object->pd) { + if (base->object->pd->deflect) return 1; } } - else { - for (Base *base = scene->base.first; base; base= base->next) { - if ( (base->lay & layer) && base->object->pd) { - if (base->object->pd->deflect) - return 1; - } - } - } return 0; } -static int query_external_colliders(Scene *scene, Group *group, Object *me) +static int query_external_colliders(ViewLayer *view_layer, Group *group) { - return(are_there_deflectors(scene, group, me->lay)); + return(are_there_deflectors(group != NULL ? group->view_layer : view_layer)); } /* --- dependency information functions*/ @@ -1544,12 +1522,12 @@ static void _scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow, } -static void scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow) +static void scan_for_ext_spring_forces(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float timenow) { SoftBody *sb = ob->soft; ListBase *do_effector = NULL; - do_effector = pdInitEffectors(scene, ob, NULL, sb->effector_weights, true); + do_effector = pdInitEffectors(eval_ctx, scene, ob, NULL, sb->effector_weights, true); _scan_for_ext_spring_forces(scene, ob, timenow, 0, sb->totspring, do_effector); pdEndEffectors(&do_effector); } @@ -1561,7 +1539,7 @@ static void *exec_scan_for_ext_spring_forces(void *data) return NULL; } -static void sb_sfesf_threads_run(Scene *scene, struct Object *ob, float timenow, int totsprings, int *UNUSED(ptr_to_break_func(void))) +static void sb_sfesf_threads_run(const struct EvaluationContext *eval_ctx, Scene *scene, struct Object *ob, float timenow, int totsprings, int *UNUSED(ptr_to_break_func(void))) { ListBase *do_effector = NULL; ListBase threads; @@ -1569,7 +1547,7 @@ static void sb_sfesf_threads_run(Scene *scene, struct Object *ob, float timenow, int i, totthread, left, dec; int lowsprings =100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */ - do_effector= pdInitEffectors(scene, ob, NULL, ob->soft->effector_weights, true); + do_effector= pdInitEffectors(eval_ctx, scene, ob, NULL, ob->soft->effector_weights, true); /* figure the number of threads while preventing pretty pointless threading overhead */ totthread= BKE_scene_num_threads(scene); @@ -2227,7 +2205,7 @@ static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float t MEM_freeN(sb_threads); } -static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, float timenow) +static void softbody_calc_forcesEx(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float forcetime, float timenow) { /* rule we never alter free variables :bp->vec bp->pos in here ! * this will ruin adaptive stepsize AKA heun! (BM) @@ -2243,7 +2221,7 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl /* gravity = sb->grav * sb_grav_force_scale(ob); */ /* UNUSED */ /* check conditions for various options */ - do_deflector= query_external_colliders(scene, sb->collision_group, ob); + do_deflector= query_external_colliders(eval_ctx->view_layer, sb->collision_group); /* do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF)); */ /* UNUSED */ do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL); do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES)); @@ -2252,10 +2230,10 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl /* bproot= sb->bpoint; */ /* need this for proper spring addressing */ /* UNUSED */ if (do_springcollision || do_aero) - sb_sfesf_threads_run(scene, ob, timenow, sb->totspring, NULL); + sb_sfesf_threads_run(eval_ctx, scene, ob, timenow, sb->totspring, NULL); /* after spring scan because it uses Effoctors too */ - do_effector= pdInitEffectors(scene, ob, NULL, sb->effector_weights, true); + do_effector= pdInitEffectors(eval_ctx, scene, ob, NULL, sb->effector_weights, true); if (do_deflector) { float defforce[3]; @@ -2272,11 +2250,11 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl } -static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, float timenow) +static void softbody_calc_forces(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float forcetime, float timenow) { /* redirection to the new threaded Version */ if (!(G.debug_value & 0x10)) { // 16 - softbody_calc_forcesEx(scene, ob, forcetime, timenow); + softbody_calc_forcesEx(eval_ctx, scene, ob, forcetime, timenow); return; } else { @@ -2307,7 +2285,7 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa } /* check conditions for various options */ - do_deflector= query_external_colliders(scene, sb->collision_group, ob); + do_deflector= query_external_colliders(eval_ctx->view_layer, sb->collision_group); do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF)); do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL); do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES)); @@ -2315,9 +2293,9 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa iks = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */ /* bproot= sb->bpoint; */ /* need this for proper spring addressing */ /* UNUSED */ - if (do_springcollision || do_aero) scan_for_ext_spring_forces(scene, ob, timenow); + if (do_springcollision || do_aero) scan_for_ext_spring_forces(eval_ctx, scene, ob, timenow); /* after spring scan because it uses Effoctors too */ - do_effector= pdInitEffectors(scene, ob, NULL, ob->soft->effector_weights, true); + do_effector= pdInitEffectors(eval_ctx, scene, ob, NULL, ob->soft->effector_weights, true); if (do_deflector) { float defforce[3]; @@ -3504,7 +3482,7 @@ static void softbody_reset(Object *ob, SoftBody *sb, float (*vertexCos)[3], int } } -static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime) +static void softbody_step(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, SoftBody *sb, float dtime) { /* the simulator */ float forcetime; @@ -3518,11 +3496,11 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime) */ if (dtime < 0 || dtime > 10.5f) return; - ccd_update_deflector_hash(scene, sb->collision_group, ob, sb->scratch->colliderhash); + ccd_update_deflector_hash(eval_ctx->view_layer, sb->collision_group, ob, sb->scratch->colliderhash); if (sb->scratch->needstobuildcollider) { - if (query_external_colliders(scene, sb->collision_group, ob)) { - ccd_build_deflector_hash(scene, sb->collision_group, ob, sb->scratch->colliderhash); + if (query_external_colliders(eval_ctx->view_layer, sb->collision_group)) { + ccd_build_deflector_hash(eval_ctx->view_layer, sb->collision_group, ob, sb->scratch->colliderhash); } sb->scratch->needstobuildcollider=0; } @@ -3552,12 +3530,12 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime) sb->scratch->flag &= ~SBF_DOFUZZY; /* do predictive euler step */ - softbody_calc_forces(scene, ob, forcetime, timedone/dtime); + softbody_calc_forces(eval_ctx, scene, ob, forcetime, timedone/dtime); softbody_apply_forces(ob, forcetime, 1, NULL, mid_flags); /* crop new slope values to do averaged slope step */ - softbody_calc_forces(scene, ob, forcetime, timedone/dtime); + softbody_calc_forces(eval_ctx, scene, ob, forcetime, timedone/dtime); softbody_apply_forces(ob, forcetime, 2, &err, mid_flags); softbody_apply_goalsnap(ob); @@ -3638,7 +3616,7 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime) } /* simulates one step. framenr is in frames */ -void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], int numVerts) +void sbObjectStep(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], int numVerts) { SoftBody *sb= ob->soft; PointCache *cache; @@ -3646,7 +3624,6 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i float dtime, timescale; int framedelta, framenr, startframe, endframe; int cache_result; - cache= sb->pointcache; framenr= (int)cfra; @@ -3715,7 +3692,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i } /* try to read from cache */ - bool can_simulate = (framenr == sb->last_frame+1) && !(cache->flag & PTCACHE_BAKED); + bool can_simulate = (framenr == sb->last_frame + 1) && !(cache->flag & PTCACHE_BAKED); cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe, can_simulate); @@ -3754,7 +3731,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i dtime = framedelta*timescale; /* do simulation */ - softbody_step(scene, ob, sb, dtime); + softbody_step(eval_ctx, scene, ob, sb, dtime); softbody_to_object(ob, vertexCos, numVerts, 0); diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index 45d1f969d64..747ffdafe8b 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -48,13 +48,11 @@ #include "DNA_speaker_types.h" #ifdef WITH_AUDASPACE -# include AUD_SOUND_H -# include AUD_SEQUENCE_H -# include AUD_HANDLE_H -# include AUD_SPECIAL_H -# ifdef WITH_SYSTEM_AUDASPACE -# include "../../../intern/audaspace/intern/AUD_Set.h" -# endif +# include <AUD_Sound.h> +# include <AUD_Sequence.h> +# include <AUD_Handle.h> +# include <AUD_Special.h> +# include "../../../intern/audaspace/intern/AUD_Set.h" #endif #include "BKE_global.h" @@ -228,7 +226,7 @@ void BKE_sound_init_once(void) atexit(BKE_sound_exit_once); } -static AUD_Device *sound_device; +static AUD_Device *sound_device = NULL; void *BKE_sound_get_device(void) { @@ -237,6 +235,9 @@ void *BKE_sound_get_device(void) void BKE_sound_init(struct Main *bmain) { + /* Make sure no instance of the sound system is running, otherwise we get leaks. */ + BKE_sound_exit(); + AUD_DeviceSpecs specs; int device, buffersize; const char *device_name; @@ -302,7 +303,6 @@ void BKE_sound_exit_once(void) sound_device = NULL; AUD_exitOnce(); -#ifdef WITH_SYSTEM_AUDASPACE if (audio_device_names != NULL) { int i; for (i = 0; audio_device_names[i]; i++) { @@ -311,7 +311,6 @@ void BKE_sound_exit_once(void) free(audio_device_names); audio_device_names = NULL; } -#endif } /* XXX unused currently */ @@ -807,13 +806,76 @@ void BKE_sound_read_waveform(bSound *sound, short *stop) BLI_spin_unlock(sound->spinlock); } -void BKE_sound_update_scene(Main *bmain, struct Scene *scene) +static void sound_update_base(Scene *scene, Base *base, void *new_set) { - Object *ob; - Base *base; + Object *ob = base->object; NlaTrack *track; NlaStrip *strip; Speaker *speaker; + float quat[4]; + + if ((ob->id.tag & LIB_TAG_DOIT) == 0) { + return; + } + + ob->id.tag &= ~LIB_TAG_DOIT; + + if ((ob->type != OB_SPEAKER) || !ob->adt) { + return; + } + + for (track = ob->adt->nla_tracks.first; track; track = track->next) { + for (strip = track->strips.first; strip; strip = strip->next) { + if (strip->type != NLASTRIP_TYPE_SOUND) { + continue; + } + speaker = (Speaker *)ob->data; + + if (AUD_removeSet(scene->speaker_handles, strip->speaker_handle)) { + if (speaker->sound) { + AUD_SequenceEntry_move(strip->speaker_handle, (double)strip->start / FPS, FLT_MAX, 0); + } + else { + AUD_Sequence_remove(scene->sound_scene, strip->speaker_handle); + strip->speaker_handle = NULL; + } + } + else { + if (speaker->sound) { + strip->speaker_handle = AUD_Sequence_add(scene->sound_scene, + speaker->sound->playback_handle, + (double)strip->start / FPS, FLT_MAX, 0); + AUD_SequenceEntry_setRelative(strip->speaker_handle, 0); + } + } + + if (strip->speaker_handle) { + const bool mute = ((strip->flag & NLASTRIP_FLAG_MUTED) || (speaker->flag & SPK_MUTED)); + AUD_addSet(new_set, strip->speaker_handle); + AUD_SequenceEntry_setVolumeMaximum(strip->speaker_handle, speaker->volume_max); + AUD_SequenceEntry_setVolumeMinimum(strip->speaker_handle, speaker->volume_min); + AUD_SequenceEntry_setDistanceMaximum(strip->speaker_handle, speaker->distance_max); + AUD_SequenceEntry_setDistanceReference(strip->speaker_handle, speaker->distance_reference); + AUD_SequenceEntry_setAttenuation(strip->speaker_handle, speaker->attenuation); + AUD_SequenceEntry_setConeAngleOuter(strip->speaker_handle, speaker->cone_angle_outer); + AUD_SequenceEntry_setConeAngleInner(strip->speaker_handle, speaker->cone_angle_inner); + AUD_SequenceEntry_setConeVolumeOuter(strip->speaker_handle, speaker->cone_volume_outer); + + mat4_to_quat(quat, ob->obmat); + AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_LOCATION, CFRA, ob->obmat[3], 1); + AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_ORIENTATION, CFRA, quat, 1); + AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_VOLUME, CFRA, &speaker->volume, 1); + AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_PITCH, CFRA, &speaker->pitch, 1); + AUD_SequenceEntry_setSound(strip->speaker_handle, speaker->sound->playback_handle); + AUD_SequenceEntry_setMuted(strip->speaker_handle, mute); + } + } + } +} + +void BKE_sound_update_scene(Main *bmain, Scene *scene) +{ + Base *base; Scene *sce_it; void *new_set = AUD_createSet(); @@ -822,59 +884,18 @@ void BKE_sound_update_scene(Main *bmain, struct Scene *scene) /* cheap test to skip looping over all objects (no speakers is a common case) */ if (!BLI_listbase_is_empty(&bmain->speaker)) { - for (SETLOOPER(scene, sce_it, base)) { - ob = base->object; - if ((ob->type != OB_SPEAKER) || !ob->adt) { - continue; - } - for (track = ob->adt->nla_tracks.first; track; track = track->next) { - for (strip = track->strips.first; strip; strip = strip->next) { - if (strip->type != NLASTRIP_TYPE_SOUND) { - continue; - } - speaker = (Speaker *)ob->data; - - if (AUD_removeSet(scene->speaker_handles, strip->speaker_handle)) { - if (speaker->sound) { - AUD_SequenceEntry_move(strip->speaker_handle, (double)strip->start / FPS, FLT_MAX, 0); - } - else { - AUD_Sequence_remove(scene->sound_scene, strip->speaker_handle); - strip->speaker_handle = NULL; - } - } - else { - if (speaker->sound) { - strip->speaker_handle = AUD_Sequence_add(scene->sound_scene, - speaker->sound->playback_handle, - (double)strip->start / FPS, FLT_MAX, 0); - AUD_SequenceEntry_setRelative(strip->speaker_handle, 0); - } - } - - if (strip->speaker_handle) { - const bool mute = ((strip->flag & NLASTRIP_FLAG_MUTED) || (speaker->flag & SPK_MUTED)); - AUD_addSet(new_set, strip->speaker_handle); - AUD_SequenceEntry_setVolumeMaximum(strip->speaker_handle, speaker->volume_max); - AUD_SequenceEntry_setVolumeMinimum(strip->speaker_handle, speaker->volume_min); - AUD_SequenceEntry_setDistanceMaximum(strip->speaker_handle, speaker->distance_max); - AUD_SequenceEntry_setDistanceReference(strip->speaker_handle, speaker->distance_reference); - AUD_SequenceEntry_setAttenuation(strip->speaker_handle, speaker->attenuation); - AUD_SequenceEntry_setConeAngleOuter(strip->speaker_handle, speaker->cone_angle_outer); - AUD_SequenceEntry_setConeAngleInner(strip->speaker_handle, speaker->cone_angle_inner); - AUD_SequenceEntry_setConeVolumeOuter(strip->speaker_handle, speaker->cone_volume_outer); - - mat4_to_quat(quat, ob->obmat); - AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_LOCATION, CFRA, ob->obmat[3], 1); - AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_ORIENTATION, CFRA, quat, 1); - AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_VOLUME, CFRA, &speaker->volume, 1); - AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_PITCH, CFRA, &speaker->pitch, 1); - AUD_SequenceEntry_setSound(strip->speaker_handle, speaker->sound->playback_handle); - AUD_SequenceEntry_setMuted(strip->speaker_handle, mute); - } - } + BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, true); + + for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + for (base = view_layer->object_bases.first; base; base = base->next) { + sound_update_base(scene, base, new_set); } } + + for (SETLOOPER_SET_ONLY(scene, sce_it, base)) { + sound_update_base(scene, base, new_set); + } + } while ((handle = AUD_getSet(scene->speaker_handles))) { @@ -907,28 +928,12 @@ float BKE_sound_get_length(bSound *sound) char **BKE_sound_get_device_names(void) { if (audio_device_names == NULL) { -#ifdef WITH_SYSTEM_AUDASPACE audio_device_names = AUD_getDeviceNames(); -#else - static const char *names[] = { - "Null", "SDL", "OpenAL", "JACK", NULL - }; - audio_device_names = (char **)names; -#endif } return audio_device_names; } -bool BKE_sound_is_jack_supported(void) -{ -#ifdef WITH_SYSTEM_AUDASPACE - return 1; -#else - return (bool)AUD_isJackSupported(); -#endif -} - #else /* WITH_AUDASPACE */ #include "BLI_utildefines.h" @@ -975,5 +980,6 @@ void BKE_sound_set_scene_sound_pan(void *UNUSED(handle), float UNUSED(pan), char void BKE_sound_set_scene_volume(struct Scene *UNUSED(scene), float UNUSED(volume)) {} void BKE_sound_set_scene_sound_pitch(void *UNUSED(handle), float UNUSED(pitch), char UNUSED(animated)) {} float BKE_sound_get_length(struct bSound *UNUSED(sound)) { return 0; } -bool BKE_sound_is_jack_supported(void) { return false; } +char **BKE_sound_get_device_names(void) { static char *names[1] = {NULL}; return names; } + #endif /* WITH_AUDASPACE */ diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 8e46cabff02..10792b7d579 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -85,6 +85,8 @@ #include "CCGSubSurf.h" +#include "DEG_depsgraph.h" + #ifdef WITH_OPENSUBDIV # include "opensubdiv_capi.h" #endif @@ -1932,7 +1934,8 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d) no[1] = b_dZ * a_cX - b_dX * a_cZ; no[2] = b_dX * a_cY - b_dY * a_cX; - /* don't normalize, GL_NORMALIZE is enabled */ + normalize_v3(no); /* we no longer rely on GL_NORMALIZE */ + glNormal3fv(no); } @@ -3440,261 +3443,6 @@ static void ccgDM_drawMappedFacesMat(DerivedMesh *dm, #undef PASSATTRIB } -static void ccgDM_drawFacesTex_common(DerivedMesh *dm, - DMSetDrawOptionsTex drawParams, - DMSetDrawOptionsMappedTex drawParamsMapped, - DMCompareDrawOptions compareDrawOptions, - void *userData, DMDrawFlag flag) -{ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; - CCGSubSurf *ss = ccgdm->ss; - CCGKey key; - int colType; - const MLoopCol *mloopcol = NULL; - MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY); - DMFlagMat *faceFlags = ccgdm->faceFlags; - DMDrawOption draw_option; - int i, totpoly; - bool flush; - const bool use_tface = (flag & DM_DRAW_USE_ACTIVE_UV) != 0; - const bool use_colors = (flag & DM_DRAW_USE_COLORS) != 0; - unsigned int next_actualFace; - unsigned int gridFaces = ccgSubSurf_getGridSize(ss) - 1; - int mat_index; - int tot_element, start_element, tot_drawn; - - if (use_colors) { - colType = CD_TEXTURE_MLOOPCOL; - mloopcol = dm->getLoopDataArray(dm, colType); - if (!mloopcol) { - colType = CD_PREVIEW_MLOOPCOL; - mloopcol = dm->getLoopDataArray(dm, colType); - } - if (!mloopcol) { - colType = CD_MLOOPCOL; - mloopcol = dm->getLoopDataArray(dm, colType); - } - } - -#ifdef WITH_OPENSUBDIV - if (ccgdm->useGpuBackend) { - const int active_uv_layer = CustomData_get_active_layer_index(&dm->loopData, CD_MLOOPUV); - if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, true, active_uv_layer) == false)) { - return; - } - if (drawParams == NULL) { - ccgSubSurf_drawGLMesh(ss, true, -1, -1); - return; - } - const int level = ccgSubSurf_getSubdivisionLevels(ss); - const int face_side = 1 << level; - const int grid_side = 1 << (level - 1); - const int face_patches = face_side * face_side; - const int grid_patches = grid_side * grid_side; - const int num_base_faces = ccgSubSurf_getNumGLMeshBaseFaces(ss); - int current_patch = 0; - int mat_nr = -1; - int start_draw_patch = 0, num_draw_patches = 0; - bool draw_smooth = false; - for (i = 0; i < num_base_faces; ++i) { - const int num_face_verts = ccgSubSurf_getNumGLMeshBaseFaceVerts(ss, i); - const int num_patches = (num_face_verts == 4) ? face_patches - : num_face_verts * grid_patches; - if (faceFlags) { - mat_nr = faceFlags[i].mat_nr; - draw_smooth = (faceFlags[i].flag & ME_SMOOTH); - } - else { - mat_nr = 0; - draw_smooth = false; - } - - if (drawParams != NULL) { - MTexPoly *tp = (use_tface && mtexpoly) ? &mtexpoly[i] : NULL; - draw_option = drawParams(tp, (mloopcol != NULL), mat_nr); - } - else { - draw_option = (drawParamsMapped) - ? drawParamsMapped(userData, i, mat_nr) - : DM_DRAW_OPTION_NORMAL; - } - - flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == num_base_faces - 1); - - const int next_face = min_ii(i + 1, num_base_faces - 1); - if (!flush && compareDrawOptions) { - flush |= compareDrawOptions(userData, i, next_face) == 0; - } - if (!flush && faceFlags) { - bool new_draw_smooth = (faceFlags[next_face].flag & ME_SMOOTH); - flush |= (new_draw_smooth != draw_smooth); - } - - current_patch += num_patches; - - if (flush) { - if (draw_option != DM_DRAW_OPTION_SKIP) { - num_draw_patches += num_patches; - } - if (num_draw_patches != 0) { - glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT); - ccgSubSurf_drawGLMesh(ss, - true, - start_draw_patch, - num_draw_patches); - } - start_draw_patch = current_patch; - num_draw_patches = 0; - } - else { - num_draw_patches += num_patches; - } - } - glShadeModel(GL_SMOOTH); - return; - } -#endif - - CCG_key_top_level(&key, ss); - ccgdm_pbvh_update(ccgdm); - - GPU_vertex_setup(dm); - GPU_normal_setup(dm); - GPU_triangle_setup(dm); - if (flag & DM_DRAW_USE_TEXPAINT_UV) - GPU_texpaint_uv_setup(dm); - else - GPU_uv_setup(dm); - if (mloopcol) { - GPU_color_setup(dm, colType); - } - - next_actualFace = 0; - - /* lastFlag = 0; */ /* UNUSED */ - for (mat_index = 0; mat_index < dm->drawObject->totmaterial; mat_index++) { - GPUBufferMaterial *bufmat = dm->drawObject->materials + mat_index; - next_actualFace = bufmat->polys[0]; - totpoly = bufmat->totpolys; - - tot_element = 0; - tot_drawn = 0; - start_element = 0; - - for (i = 0; i < totpoly; i++) { - int polyindex = bufmat->polys[i]; - CCGFace *f = ccgdm->faceMap[polyindex].face; - int numVerts = ccgSubSurf_getFaceNumVerts(f); - int index = ccgDM_getFaceMapIndex(ss, f); - int orig_index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f)); - int mat_nr; - int facequads = numVerts * gridFaces * gridFaces; - int actualFace = ccgdm->faceMap[polyindex].startFace; - - if (i != totpoly - 1) { - polyindex = bufmat->polys[i + 1]; - next_actualFace = ccgdm->faceMap[polyindex].startFace; - } - - if (faceFlags) { - mat_nr = faceFlags[orig_index].mat_nr; - } - else { - mat_nr = 0; - } - - if (drawParams) { - MTexPoly *tp = (use_tface && mtexpoly) ? &mtexpoly[actualFace] : NULL; - draw_option = drawParams(tp, (mloopcol != NULL), mat_nr); - } - else if (index != ORIGINDEX_NONE) - draw_option = (drawParamsMapped) ? drawParamsMapped(userData, index, mat_nr) : DM_DRAW_OPTION_NORMAL; - else - draw_option = DM_DRAW_OPTION_NORMAL; - - /* flush buffer if current triangle isn't drawable or it's last triangle */ - flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == totpoly - 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; - } - - tot_element += facequads * 6; - - if (flush) { - if (draw_option != DM_DRAW_OPTION_SKIP) - tot_drawn += facequads * 6; - - if (tot_drawn) { - if (mloopcol && draw_option != DM_DRAW_OPTION_NO_MCOL) - GPU_color_switch(1); - else - GPU_color_switch(0); - - GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, bufmat->start + start_element, tot_drawn); - tot_drawn = 0; - } - - start_element = tot_element; - } - else { - tot_drawn += facequads * 6; - } - } - } - - - GPU_buffers_unbind(); -} - -static void ccgDM_drawFacesTex(DerivedMesh *dm, - DMSetDrawOptionsTex setDrawOptions, - DMCompareDrawOptions compareDrawOptions, - void *userData, DMDrawFlag flag) -{ - ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData, flag); -} - -static void ccgDM_drawMappedFacesTex(DerivedMesh *dm, - DMSetDrawOptionsMappedTex setDrawOptions, - DMCompareDrawOptions compareDrawOptions, - void *userData, DMDrawFlag flag) -{ - ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag); -} - -/* same as cdDM_drawUVEdges */ -static void ccgDM_drawUVEdges(DerivedMesh *dm) -{ - MPoly *mpoly = dm->getPolyArray(dm); - int totpoly = dm->getNumPolys(dm); - int prevstart = 0; - bool prevdraw = true; - int curpos = 0; - int i; - - GPU_uvedge_setup(dm); - for (i = 0; i < totpoly; i++, mpoly++) { - const bool draw = (mpoly->flag & ME_HIDE) == 0; - - if (prevdraw != draw) { - if (prevdraw && (curpos != prevstart)) { - glDrawArrays(GL_LINES, prevstart, curpos - prevstart); - } - prevstart = curpos; - } - - curpos += 2 * mpoly->totloop; - prevdraw = draw; - } - if (prevdraw && (curpos != prevstart)) { - glDrawArrays(GL_LINES, prevstart, curpos - prevstart); - } - GPU_buffers_unbind(); -} - static void ccgDM_drawMappedFaces(DerivedMesh *dm, DMSetDrawOptions setDrawOptions, DMSetMaterial setMaterial, @@ -4042,12 +3790,14 @@ static void ccgDM_release(DerivedMesh *dm) { ccgdm->multires.mmd = NULL; } - if (ccgdm->multires.mmd) { - if (ccgdm->multires.modified_flags & MULTIRES_COORDS_MODIFIED) - multires_modifier_update_mdisps(dm); - if (ccgdm->multires.modified_flags & MULTIRES_HIDDEN_MODIFIED) + if (ccgdm->multires.modified_flags & MULTIRES_COORDS_MODIFIED) { + /* TODO/OBMODE, pass real mode? */ + multires_modifier_update_mdisps(dm, OB_MODE_OBJECT); + } + if (ccgdm->multires.modified_flags & MULTIRES_HIDDEN_MODIFIED) { multires_modifier_update_hidden(dm); + } } } @@ -4441,7 +4191,8 @@ static int ccgDM_use_grid_pbvh(CCGDerivedMesh *ccgdm) return 1; } -static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm) +static struct PBVH *ccgDM_getPBVH( + Object *ob, DerivedMesh *dm, eObjectMode object_mode) { CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm; CCGKey key; @@ -4458,7 +4209,7 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm) return NULL; bool grid_pbvh = ccgDM_use_grid_pbvh(ccgdm); - if ((ob->mode & OB_MODE_SCULPT) == 0) { + if ((object_mode & OB_MODE_SCULPT) == 0) { /* In vwpaint, we may use a grid_pbvh for multires/subsurf, under certain conditions. * More complex cases break 'history' trail back to original vertices, in that case we fall back to * deformed cage only (i.e. original deformed mesh). */ @@ -4691,13 +4442,10 @@ static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm) ccgdm->dm.drawEdges = ccgDM_drawEdges; ccgdm->dm.drawLooseEdges = ccgDM_drawLooseEdges; ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid; - ccgdm->dm.drawFacesTex = ccgDM_drawFacesTex; ccgdm->dm.drawFacesGLSL = ccgDM_drawFacesGLSL; ccgdm->dm.drawMappedFaces = ccgDM_drawMappedFaces; - ccgdm->dm.drawMappedFacesTex = ccgDM_drawMappedFacesTex; ccgdm->dm.drawMappedFacesGLSL = ccgDM_drawMappedFacesGLSL; ccgdm->dm.drawMappedFacesMat = ccgDM_drawMappedFacesMat; - ccgdm->dm.drawUVEdges = ccgDM_drawUVEdges; ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp; ccgdm->dm.drawMappedEdges = ccgDM_drawMappedEdges; @@ -5155,8 +4903,7 @@ static bool subsurf_use_gpu_backend(SubsurfFlags flags) */ return (flags & SUBSURF_USE_GPU_BACKEND) != 0 && - (U.opensubdiv_compute_type != USER_OPENSUBDIV_COMPUTE_NONE) && - (openSubdiv_supportGPUDisplay()); + (U.opensubdiv_compute_type != USER_OPENSUBDIV_COMPUTE_NONE); #else (void)flags; return false; diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c index 7c4aa81ee46..4ae9818f891 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -58,7 +58,6 @@ #include "DNA_node_types.h" #include "DNA_material_types.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_library.h" #include "BKE_main.h" diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index f9d34534a45..ebd4c04e8ce 100644 --- a/source/blender/blenkernel/intern/tracking.c +++ b/source/blender/blenkernel/intern/tracking.c @@ -61,6 +61,7 @@ #include "BKE_movieclip.h" #include "BKE_object.h" #include "BKE_scene.h" +#include "BKE_layer.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -400,7 +401,7 @@ void BKE_tracking_get_camera_object_matrix(Scene *scene, Object *ob, float mat[4 if (scene->camera) ob = scene->camera; else - ob = BKE_scene_camera_find(scene); + ob = BKE_view_layer_camera_find(BKE_view_layer_from_scene_get(scene)); } if (ob) diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c new file mode 100644 index 00000000000..dcd4183210d --- /dev/null +++ b/source/blender/blenkernel/intern/workspace.c @@ -0,0 +1,520 @@ +/* + * ***** 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 ***** + */ + +/** \file blender/blenkernel/intern/workspace.c + * \ingroup bke + */ + +/* allow accessing private members of DNA_workspace_types.h */ +#define DNA_PRIVATE_WORKSPACE_ALLOW + +#include <stdlib.h> + +#include "BLI_utildefines.h" +#include "BLI_string.h" +#include "BLI_string_utf8.h" +#include "BLI_string_utils.h" +#include "BLI_listbase.h" + +#include "BKE_global.h" +#include "BKE_library.h" +#include "BKE_main.h" +#include "BKE_scene.h" +#include "BKE_screen.h" +#include "BKE_workspace.h" + +#include "DNA_object_types.h" +#include "DNA_scene_types.h" +#include "DNA_screen_types.h" +#include "DNA_workspace_types.h" + +#include "DEG_depsgraph.h" + +#include "MEM_guardedalloc.h" + + +/* -------------------------------------------------------------------- */ +/* Internal utils */ + +static void workspace_layout_name_set( + WorkSpace *workspace, WorkSpaceLayout *layout, const char *new_name) +{ + BLI_strncpy(layout->name, new_name, sizeof(layout->name)); + BLI_uniquename(&workspace->layouts, layout, "Layout", '.', offsetof(WorkSpaceLayout, name), sizeof(layout->name)); +} + +/** + * This should only be used directly when it is to be expected that there isn't + * a layout within \a workspace that wraps \a screen. Usually - especially outside + * of BKE_workspace - #BKE_workspace_layout_find should be used! + */ +static WorkSpaceLayout *workspace_layout_find_exec( + const WorkSpace *workspace, const bScreen *screen) +{ + return BLI_findptr(&workspace->layouts, screen, offsetof(WorkSpaceLayout, screen)); +} + +static void workspace_relation_add( + ListBase *relation_list, void *parent, void *data) +{ + WorkSpaceDataRelation *relation = MEM_callocN(sizeof(*relation), __func__); + relation->parent = parent; + relation->value = data; + /* add to head, if we switch back to it soon we find it faster. */ + BLI_addhead(relation_list, relation); +} +static void workspace_relation_remove( + ListBase *relation_list, WorkSpaceDataRelation *relation) +{ + BLI_remlink(relation_list, relation); + MEM_freeN(relation); +} + +static void workspace_relation_ensure_updated( + ListBase *relation_list, void *parent, void *data) +{ + WorkSpaceDataRelation *relation = BLI_findptr(relation_list, parent, offsetof(WorkSpaceDataRelation, parent)); + if (relation != NULL) { + relation->value = data; + /* reinsert at the head of the list, so that more commonly used relations are found faster. */ + BLI_remlink(relation_list, relation); + BLI_addhead(relation_list, relation); + } + else { + /* no matching relation found, add new one */ + workspace_relation_add(relation_list, parent, data); + } +} + +static void *workspace_relation_get_data_matching_parent( + const ListBase *relation_list, const void *parent) +{ + WorkSpaceDataRelation *relation = BLI_findptr(relation_list, parent, offsetof(WorkSpaceDataRelation, parent)); + if (relation != NULL) { + return relation->value; + } + else { + return NULL; + } +} + +static void workspace_relation_remove_from_value( + ListBase *relation_list, const void *value) +{ + for (WorkSpaceDataRelation *relation = relation_list->first, *relation_next; relation; relation = relation_next) { + relation_next = relation->next; + + if (relation->value == value) { + workspace_relation_remove(relation_list, relation); + } + } +} + +/** + * Checks if \a screen is already used within any workspace. A screen should never be assigned to multiple + * WorkSpaceLayouts, but that should be ensured outside of the BKE_workspace module and without such checks. + * Hence, this should only be used as assert check before assigining a screen to a workspace. + */ +#ifndef NDEBUG +static bool workspaces_is_screen_used +#else +static bool UNUSED_FUNCTION(workspaces_is_screen_used) +#endif + (const Main *bmain, bScreen *screen) +{ + for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) { + if (workspace_layout_find_exec(workspace, screen)) { + return true; + } + } + + return false; +} + +/* -------------------------------------------------------------------- */ +/* Create, delete, init */ + +WorkSpace *BKE_workspace_add(Main *bmain, const char *name) +{ + WorkSpace *new_workspace = BKE_libblock_alloc(bmain, ID_WS, name, 0); + return new_workspace; +} + +/** + * The function that actually frees the workspace data (not workspace itself). It shouldn't be called + * directly, instead #BKE_workspace_remove should be, which calls this through #BKE_libblock_free then. + * + * Should something like a bke_internal.h be added, this should go there! + */ +void BKE_workspace_free(WorkSpace *workspace) +{ + BKE_workspace_relations_free(&workspace->hook_layout_relations); + BKE_workspace_relations_free(&workspace->scene_viewlayer_relations); + + BLI_freelistN(&workspace->layouts); + BLI_freelistN(&workspace->transform_orientations); + + BKE_viewrender_free(&workspace->view_render); +} + +/** + * Remove \a workspace by freeing itself and its data. This is a higher-level wrapper that + * calls #BKE_workspace_free (through #BKE_libblock_free) to free the workspace data, and frees + * other data-blocks owned by \a workspace and its layouts (currently that is screens only). + * + * Always use this to remove (and free) workspaces. Don't free non-ID workspace members here. + */ +void BKE_workspace_remove(Main *bmain, WorkSpace *workspace) +{ + for (WorkSpaceLayout *layout = workspace->layouts.first, *layout_next; layout; layout = layout_next) { + layout_next = layout->next; + BKE_workspace_layout_remove(bmain, workspace, layout); + } + BKE_libblock_free(bmain, workspace); +} + +WorkSpaceInstanceHook *BKE_workspace_instance_hook_create(const Main *bmain) +{ + WorkSpaceInstanceHook *hook = MEM_callocN(sizeof(WorkSpaceInstanceHook), __func__); + + /* set an active screen-layout for each possible window/workspace combination */ + for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) { + BKE_workspace_hook_layout_for_workspace_set(hook, workspace, workspace->layouts.first); + } + + return hook; +} +void BKE_workspace_instance_hook_free(const Main *bmain, WorkSpaceInstanceHook *hook) +{ + /* workspaces should never be freed before wm (during which we call this function) */ + BLI_assert(!BLI_listbase_is_empty(&bmain->workspaces)); + + /* Free relations for this hook */ + for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) { + for (WorkSpaceDataRelation *relation = workspace->hook_layout_relations.first, *relation_next; + relation; + relation = relation_next) + { + relation_next = relation->next; + if (relation->parent == hook) { + workspace_relation_remove(&workspace->hook_layout_relations, relation); + } + } + } + + MEM_freeN(hook); +} + +/** + * Add a new layout to \a workspace for \a screen. + */ +WorkSpaceLayout *BKE_workspace_layout_add( + WorkSpace *workspace, + bScreen *screen, + const char *name) +{ + WorkSpaceLayout *layout = MEM_callocN(sizeof(*layout), __func__); + + BLI_assert(!workspaces_is_screen_used(G.main, screen)); + layout->screen = screen; + workspace_layout_name_set(workspace, layout, name); + BLI_addtail(&workspace->layouts, layout); + + return layout; +} + +void BKE_workspace_layout_remove( + Main *bmain, + WorkSpace *workspace, WorkSpaceLayout *layout) +{ + BKE_libblock_free(bmain, BKE_workspace_layout_screen_get(layout)); + BLI_freelinkN(&workspace->layouts, layout); +} + +void BKE_workspace_relations_free( + ListBase *relation_list) +{ + for (WorkSpaceDataRelation *relation = relation_list->first, *relation_next; relation; relation = relation_next) { + relation_next = relation->next; + workspace_relation_remove(relation_list, relation); + } +} + + +/* -------------------------------------------------------------------- */ +/* General Utils */ + +void BKE_workspace_view_layer_remove_references( + const Main *bmain, + const ViewLayer *view_layer) +{ + for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) { + workspace_relation_remove_from_value(&workspace->scene_viewlayer_relations, view_layer); + } +} + +void BKE_workspace_transform_orientation_remove( + WorkSpace *workspace, TransformOrientation *orientation) +{ + for (WorkSpaceLayout *layout = workspace->layouts.first; layout; layout = layout->next) { + BKE_screen_transform_orientation_remove(BKE_workspace_layout_screen_get(layout), workspace, orientation); + } + + BLI_freelinkN(&workspace->transform_orientations, orientation); +} + +TransformOrientation *BKE_workspace_transform_orientation_find( + const WorkSpace *workspace, const int index) +{ + return BLI_findlink(&workspace->transform_orientations, index); +} + +/** + * \return the index that \a orientation has within \a workspace's transform-orientation list or -1 if not found. + */ +int BKE_workspace_transform_orientation_get_index( + const WorkSpace *workspace, const TransformOrientation *orientation) +{ + return BLI_findindex(&workspace->transform_orientations, orientation); +} + +WorkSpaceLayout *BKE_workspace_layout_find( + const WorkSpace *workspace, const bScreen *screen) +{ + WorkSpaceLayout *layout = workspace_layout_find_exec(workspace, screen); + if (layout) { + return layout; + } + + printf("%s: Couldn't find layout in this workspace: '%s' screen: '%s'. " + "This should not happen!\n", + __func__, workspace->id.name + 2, screen->id.name + 2); + + return NULL; +} + +/** + * Find the layout for \a screen without knowing which workspace to look in. + * Can also be used to find the workspace that contains \a screen. + * + * \param r_workspace: Optionally return the workspace that contains the looked up layout (if found). + */ +WorkSpaceLayout *BKE_workspace_layout_find_global( + const Main *bmain, const bScreen *screen, + WorkSpace **r_workspace) +{ + WorkSpaceLayout *layout; + + if (r_workspace) { + *r_workspace = NULL; + } + + for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) { + if ((layout = workspace_layout_find_exec(workspace, screen))) { + if (r_workspace) { + *r_workspace = workspace; + } + + return layout; + } + } + + return NULL; +} + +/** + * Circular workspace layout iterator. + * + * \param callback: Custom function which gets executed for each layout. Can return false to stop iterating. + * \param arg: Custom data passed to each \a callback call. + * + * \return the layout at which \a callback returned false. + */ +WorkSpaceLayout *BKE_workspace_layout_iter_circular( + const WorkSpace *workspace, WorkSpaceLayout *start, + bool (*callback)(const WorkSpaceLayout *layout, void *arg), + void *arg, const bool iter_backward) +{ + WorkSpaceLayout *iter_layout; + + if (iter_backward) { + BLI_LISTBASE_CIRCULAR_BACKWARD_BEGIN(&workspace->layouts, iter_layout, start) + { + if (!callback(iter_layout, arg)) { + return iter_layout; + } + } + BLI_LISTBASE_CIRCULAR_BACKWARD_END(&workspace->layouts, iter_layout, start); + } + else { + BLI_LISTBASE_CIRCULAR_FORWARD_BEGIN(&workspace->layouts, iter_layout, start) + { + if (!callback(iter_layout, arg)) { + return iter_layout; + } + } + BLI_LISTBASE_CIRCULAR_FORWARD_END(&workspace->layouts, iter_layout, start) + } + + return NULL; +} + + +/* -------------------------------------------------------------------- */ +/* Getters/Setters */ + +WorkSpace *BKE_workspace_active_get(WorkSpaceInstanceHook *hook) +{ + return hook->active; +} +void BKE_workspace_active_set(WorkSpaceInstanceHook *hook, WorkSpace *workspace) +{ + hook->active = workspace; + if (workspace) { + WorkSpaceLayout *layout = workspace_relation_get_data_matching_parent(&workspace->hook_layout_relations, hook); + if (layout) { + hook->act_layout = layout; + } + } +} + +WorkSpaceLayout *BKE_workspace_active_layout_get(const WorkSpaceInstanceHook *hook) +{ + return hook->act_layout; +} +void BKE_workspace_active_layout_set(WorkSpaceInstanceHook *hook, WorkSpaceLayout *layout) +{ + hook->act_layout = layout; +} + +bScreen *BKE_workspace_active_screen_get(const WorkSpaceInstanceHook *hook) +{ + return hook->act_layout->screen; +} +void BKE_workspace_active_screen_set(WorkSpaceInstanceHook *hook, WorkSpace *workspace, bScreen *screen) +{ + /* we need to find the WorkspaceLayout that wraps this screen */ + WorkSpaceLayout *layout = BKE_workspace_layout_find(hook->active, screen); + BKE_workspace_hook_layout_for_workspace_set(hook, workspace, layout); +} + +Base *BKE_workspace_active_base_get(const WorkSpace *workspace, const Scene *scene) +{ + ViewLayer *view_layer = BKE_workspace_view_layer_get(workspace, scene); + return view_layer->basact; +} + +ListBase *BKE_workspace_transform_orientations_get(WorkSpace *workspace) +{ + return &workspace->transform_orientations; +} + +ViewLayer *BKE_workspace_view_layer_get(const WorkSpace *workspace, const Scene *scene) +{ + return workspace_relation_get_data_matching_parent(&workspace->scene_viewlayer_relations, scene); +} +void BKE_workspace_view_layer_set(WorkSpace *workspace, ViewLayer *layer, Scene *scene) +{ + workspace_relation_ensure_updated(&workspace->scene_viewlayer_relations, scene, layer); +} + +ListBase *BKE_workspace_layouts_get(WorkSpace *workspace) +{ + return &workspace->layouts; +} + + +const char *BKE_workspace_layout_name_get(const WorkSpaceLayout *layout) +{ + return layout->name; +} +void BKE_workspace_layout_name_set(WorkSpace *workspace, WorkSpaceLayout *layout, const char *new_name) +{ + workspace_layout_name_set(workspace, layout, new_name); +} + +bScreen *BKE_workspace_layout_screen_get(const WorkSpaceLayout *layout) +{ + return layout->screen; +} +void BKE_workspace_layout_screen_set(WorkSpaceLayout *layout, bScreen *screen) +{ + layout->screen = screen; +} + +WorkSpaceLayout *BKE_workspace_hook_layout_for_workspace_get( + const WorkSpaceInstanceHook *hook, const WorkSpace *workspace) +{ + return workspace_relation_get_data_matching_parent(&workspace->hook_layout_relations, hook); +} +void BKE_workspace_hook_layout_for_workspace_set( + WorkSpaceInstanceHook *hook, WorkSpace *workspace, WorkSpaceLayout *layout) +{ + hook->act_layout = layout; + workspace_relation_ensure_updated(&workspace->hook_layout_relations, hook, layout); +} + +/** + * Get the render engine of a workspace, to be used in the viewport. + */ +ViewRender *BKE_workspace_view_render_get(WorkSpace *workspace) +{ + return &workspace->view_render; +} + +/* Flags */ +bool BKE_workspace_use_scene_settings_get(const WorkSpace *workspace) +{ + return (workspace->flags & WORKSPACE_USE_SCENE_SETTINGS) != 0; +} + +void BKE_workspace_use_scene_settings_set(WorkSpace *workspace, bool value) +{ + if (value) { + workspace->flags |= WORKSPACE_USE_SCENE_SETTINGS; + } + else { + workspace->flags &= ~WORKSPACE_USE_SCENE_SETTINGS; + } +} + +/* Update / evaluate */ + +void BKE_workspace_update_tagged(struct EvaluationContext *eval_ctx, + Main *bmain, + WorkSpace *workspace, + Scene *scene) +{ + ViewLayer *view_layer = BKE_workspace_view_layer_get(workspace, scene); + struct Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, + view_layer, + true); + BKE_scene_graph_update_tagged(eval_ctx, depsgraph, bmain, scene, view_layer); +} + +void BKE_workspace_update_object_mode( + struct EvaluationContext *eval_ctx, + WorkSpace *workspace) +{ + /* TODO(campbell): Investigate how this should work exactly, + * for now without this 'bmain->eval_ctx' is never set. */ + + eval_ctx->object_mode = workspace->object_mode; +}
\ No newline at end of file diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 10fcfaa444f..5da8dc563e2 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -193,3 +193,14 @@ void BKE_world_make_local(Main *bmain, World *wrld, const bool lib_local) { BKE_id_make_local_generic(bmain, &wrld->id, true, lib_local); } + +void BKE_world_eval(const struct EvaluationContext *UNUSED(eval_ctx), World *world) +{ + if (G.debug & G_DEBUG_DEPSGRAPH) { + printf("%s on %s (%p)\n", __func__, world->id.name, world); + } + if (!BLI_listbase_is_empty(&world->gpumaterial)) { + world->update_flag = 1; + GPU_material_uniform_buffer_tag_dirty(&world->gpumaterial); + } +} diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 5415fbb8ae1..f745a840cea 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -45,8 +45,8 @@ #include "BLI_blenlib.h" #ifdef WITH_AUDASPACE -# include AUD_DEVICE_H -# include AUD_SPECIAL_H +# include <AUD_Device.h> +# include <AUD_Special.h> #endif #include "BLI_utildefines.h" |