diff options
Diffstat (limited to 'source/blender/blenkernel')
178 files changed, 13697 insertions, 20217 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 4d2e9ef8b3c..74416bcd18f 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -95,8 +95,8 @@ struct KeyBlock; struct ModifierData; struct MCol; struct ColorBand; +struct Depsgraph; struct GPUVertexAttribs; -struct GPUDrawObject; struct PBVH; /* number of sub-elements each mesh element has (for interpolation) */ @@ -126,36 +126,6 @@ typedef enum DerivedMeshType { DM_TYPE_CCGDM } DerivedMeshType; -typedef enum DMDrawOption { - /* the element is hidden or otherwise non-drawable */ - DM_DRAW_OPTION_SKIP = 0, - /* normal drawing */ - DM_DRAW_OPTION_NORMAL = 1, - /* draw, but don't set the color from mcol */ - DM_DRAW_OPTION_NO_MCOL = 2, - /* used in drawMappedFaces, use GL stipple for the face */ - DM_DRAW_OPTION_STIPPLE = 3, -} DMDrawOption; - -/* Drawing callback types */ -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), - DM_DRAW_ALWAYS_SMOOTH = (1 << 1), - DM_DRAW_USE_ACTIVE_UV = (1 << 2), - DM_DRAW_USE_TEXPAINT_UV = (1 << 3), - DM_DRAW_SKIP_HIDDEN = (1 << 4), - DM_DRAW_SKIP_SELECT = (1 << 5), - DM_DRAW_SELECT_USE_EDITMODE = (1 << 6), - DM_DRAW_NEED_NORMALS = (1 << 7) -} DMDrawFlag; - typedef enum DMForeachFlag { DM_FOREACH_NOP = 0, DM_FOREACH_USE_NORMAL = (1 << 0), /* foreachMappedVert, foreachMappedLoop, foreachMappedFaceCenter */ @@ -164,14 +134,9 @@ typedef enum DMForeachFlag { typedef enum DMDirtyFlag { /* dm has valid tessellated faces, but tessellated CDDATA need to be updated. */ DM_DIRTY_TESS_CDLAYERS = 1 << 0, - /* One of the MCOL layers have been updated, force updating of GPUDrawObject's colors buffer. - * This is necessary with modern, VBO draw code, as e.g. in vpaint mode me->mcol may be updated - * without actually rebuilding dm (hence by default keeping same GPUDrawObject, and same colors - * buffer, which prevents update during a stroke!). */ - DM_DIRTY_MCOL_UPDATE_DRAW = 1 << 1, /* check this with modifier dependsOnNormals callback to see if normals need recalculation */ - DM_DIRTY_NORMALS = 1 << 2, + DM_DIRTY_NORMALS = 1 << 1, } DMDirtyFlag; typedef struct DerivedMesh DerivedMesh; @@ -182,9 +147,7 @@ struct DerivedMesh { int needsFree; /* checked on ->release, is set to 0 for cached results */ int deformedOnly; /* set by modifier stack if only deformed from original */ BVHCache *bvhCache; - struct GPUDrawObject *drawObject; DerivedMeshType type; - float auto_bump_scale; DMDirtyFlag dirty; int totmat; /* total materials. Will be valid only before object drawing. */ struct Material **mat; /* material array. Will be valid only before object drawing */ @@ -384,117 +347,6 @@ struct DerivedMesh { */ struct PBVH *(*getPBVH)(struct Object *ob, DerivedMesh *dm); - /* 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 - */ - void (*drawEdges)(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdges); - - /** Draw all loose edges (edges w/ no adjoining faces) */ - void (*drawLooseEdges)(DerivedMesh *dm); - - /** Draw all faces - * o Set face normal or vertex normal based on inherited face flag - * o Use inherited face material index to call setMaterial - * o Only if setMaterial returns true - * - * Also called for *final* editmode DerivedMeshes - */ - 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 - */ - void (*drawFacesGLSL)(DerivedMesh *dm, DMSetMaterial setMaterial); - - /** Draw mapped faces (no color, or texture) - * - Only if !setDrawOptions or - * setDrawOptions(userData, mapped-face-index, r_drawSmooth) - * returns true - * - * If drawSmooth is set to true then vertex normals should be set and - * glShadeModel called with GL_SMOOTH. Otherwise the face normal should - * be set and glShadeModel called with GL_FLAT. - * - * The setDrawOptions is allowed to not set drawSmooth (for example, when - * lighting is disabled), in which case the implementation should draw as - * smooth shaded. - */ - void (*drawMappedFaces)(DerivedMesh *dm, - DMSetDrawOptions setDrawOptions, - DMSetMaterial setMaterial, - DMCompareDrawOptions compareDrawOptions, - 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 - * - Only if setMaterial and setDrawOptions return true - */ - void (*drawMappedFacesGLSL)(DerivedMesh *dm, - DMSetMaterial setMaterial, - DMSetDrawOptions setDrawOptions, - void *userData); - - /** Draw mapped edges as lines - * - Only if !setDrawOptions or setDrawOptions(userData, mapped-edge) - * returns true - */ - void (*drawMappedEdges)(DerivedMesh *dm, - DMSetDrawOptions setDrawOptions, - void *userData); - - /** Draw mapped edges as lines with interpolation values - * - Only if !setDrawOptions or - * setDrawOptions(userData, mapped-edge, mapped-v0, mapped-v1, t) - * returns true - * - * NOTE: This routine is optional! - */ - void (*drawMappedEdgesInterp)(DerivedMesh *dm, - DMSetDrawOptions setDrawOptions, - DMSetDrawInterpOptions setDrawInterpOptions, - void *userData); - - /** Draw all faces with materials - * - setMaterial is called for every different material nr - * - setFace is called to verify if a face must be hidden - */ - void (*drawMappedFacesMat)(DerivedMesh *dm, - void (*setMaterial)(void *userData, int matnr, void *attribs), - bool (*setFace)(void *userData, int index), void *userData); - - struct GPUDrawObject *(*gpuObjectNew)(DerivedMesh *dm); - void (*copy_gpu_data)(DerivedMesh *dm, int type, void *varray_p, - const int *mat_orig_to_new, const void *user_data); - /** Release reference to the DerivedMesh. This function decides internally * if the DerivedMesh will be freed, or cached for later use. */ void (*release)(DerivedMesh *dm); @@ -680,56 +532,49 @@ 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); + struct Depsgraph *depsgraph, struct Scene *scene, + struct Object *ob, CustomDataMask dataMask); DerivedMesh *mesh_get_derived_deform( - struct Scene *scene, struct Object *ob, - CustomDataMask dataMask); + struct Depsgraph *depsgraph, struct Scene *scene, + struct Object *ob, CustomDataMask dataMask); DerivedMesh *mesh_create_derived_for_modifier( - struct Scene *scene, struct Object *ob, + struct Depsgraph *depsgraph, 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); + struct Depsgraph *depsgraph, 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); + struct Depsgraph *depsgraph, 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); + struct Depsgraph *depsgraph, struct Scene *scene, + struct Object *ob, CustomDataMask dataMask); DerivedMesh *mesh_create_derived_no_deform( - struct Scene *scene, struct Object *ob, - float (*vertCos)[3], + struct Depsgraph *depsgraph, 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], - CustomDataMask dataMask); -/* for gameengine */ -DerivedMesh *mesh_create_derived_no_virtual( - 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], + struct Depsgraph *depsgraph, 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 *, + struct Depsgraph *depsgraph, struct Scene *scene, struct Object *, struct BMEditMesh *em, CustomDataMask dataMask); DerivedMesh *editbmesh_get_derived_cage_and_final( - struct Scene *scene, struct Object *, + struct Depsgraph *depsgraph, struct Scene *scene, struct Object *, struct BMEditMesh *em, CustomDataMask dataMask, DerivedMesh **r_final); @@ -738,7 +583,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, + struct Depsgraph *depsgraph, 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); @@ -783,25 +628,18 @@ void DM_vertex_attributes_from_gpu( DerivedMesh *dm, struct GPUVertexAttribs *gattribs, DMVertexAttribs *attribs); -void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert, int loop); -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_action.h b/source/blender/blenkernel/BKE_action.h index f7ebe85bcef..72a8ffd7a26 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -163,9 +163,6 @@ struct bPoseChannel *BKE_pose_channel_get_mirrored(const struct bPose *pose, con bool BKE_pose_channels_is_valid(const struct bPose *pose); #endif -/* Copy the data from the action-pose (src) into the pose */ -void extract_pose_from_pose(struct bPose *pose, const struct bPose *src); - /* sets constraint flags */ void BKE_pose_update_constraint_flags(struct bPose *pose); @@ -211,6 +208,7 @@ void BKE_pose_rest(struct bPose *pose); /* Tag pose for recalc. Also tag all related data to be recalc. */ void BKE_pose_tag_recalc(struct Main *bmain, struct bPose *pose); + #ifdef __cplusplus }; #endif diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h index 584f0da323a..0fb83162459 100644 --- a/source/blender/blenkernel/BKE_anim.h +++ b/source/blender/blenkernel/BKE_anim.h @@ -32,7 +32,7 @@ * \author nzc * \since March 2001 */ -struct EvaluationContext; +struct Depsgraph; struct Path; struct Object; struct Scene; @@ -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 Depsgraph *depsgraph, 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(struct Depsgraph *depsgraph, struct Scene *sce, struct Object *ob, bool update); +struct ListBase *object_duplilist(struct Depsgraph *depsgraph, 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(struct Depsgraph *depsgraph, 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..71c63df7bf3 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 */ @@ -68,10 +69,10 @@ bool BKE_animdata_set_action(struct ReportList *reports, struct ID *id, struct b void BKE_animdata_free(struct ID *id, const bool do_id_user); /* Copy AnimData */ -struct AnimData *BKE_animdata_copy(struct Main *bmain, struct AnimData *adt, const bool do_action); +struct AnimData *BKE_animdata_copy(struct Main *bmain, struct AnimData *adt, const bool do_action, const bool do_id_user); /* Copy AnimData */ -bool BKE_animdata_copy_id(struct Main *bmain, struct ID *id_to, struct ID *id_from, const bool do_action); +bool BKE_animdata_copy_id(struct Main *bmain, struct ID *id_to, struct ID *id_from, const bool do_action, const bool do_id_user); /* Copy AnimData Actions */ void BKE_animdata_copy_id_action(struct ID *id, const bool set_newid); @@ -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 --------------- */ @@ -200,10 +200,10 @@ void animsys_evaluate_action_group(struct PointerRNA *ptr, struct bAction *act, /* ------------ Evaluation API --------------- */ -struct EvaluationContext; +struct Depsgraph; -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(struct Depsgraph *depsgraph, struct ID *id); +void BKE_animsys_eval_driver(struct Depsgraph *depsgraph, 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 f6de39c897e..b8d9e5a9af9 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 Depsgraph; struct GHash; struct Main; struct bArmature; @@ -97,10 +99,10 @@ float distfactor_to_bone(const float vec[3], const float b1[3], const float b2[3 void BKE_armature_where_is(struct bArmature *arm); void BKE_armature_where_is_bone(struct Bone *bone, struct Bone *prevbone, const bool use_recursion); void BKE_pose_clear_pointers(struct bPose *pose); +void BKE_pose_remap_bone_pointers(struct bArmature *armature, 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(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); +void BKE_pose_where_is_bone(struct Depsgraph *depsgraph, 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 +119,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(struct Depsgraph *depsgraph, 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); @@ -151,60 +153,78 @@ void b_bone_spline_setup(struct bPoseChannel *pchan, int rest, Mat4 result_array #define PBONE_SELECTABLE(arm, bone) \ (PBONE_VISIBLE(arm, bone) && !((bone)->flag & BONE_UNSELECTABLE)) + +/* context.selected_pose_bones */ +#define FOREACH_PCHAN_SELECTED_IN_OBJECT_BEGIN(_ob, _pchan) \ + for (bPoseChannel *_pchan = (_ob)->pose->chanbase.first; _pchan; _pchan = _pchan->next) { \ + if (PBONE_VISIBLE(((bArmature *)(_ob)->data), (_pchan)->bone) && ((_pchan)->bone->flag & BONE_SELECTED)) { +#define FOREACH_PCHAN_SELECTED_IN_OBJECT_END \ + } \ + } ((void)0) +/* context.visible_pose_bones */ +#define FOREACH_PCHAN_VISIBLE_IN_OBJECT_BEGIN(_ob, _pchan) \ + for (bPoseChannel *_pchan = (_ob)->pose->chanbase.first; _pchan; _pchan = _pchan->next) { \ + if (PBONE_VISIBLE(((bArmature *)(_ob)->data), (_pchan)->bone)) { +#define FOREACH_PCHAN_VISIBLE_IN_OBJECT_END \ + } \ + } ((void)0) + + /* Evaluation helpers */ struct bKinematicConstraint; struct bPose; struct bSplineIKConstraint; -struct EvaluationContext; struct bPoseChannel *BKE_armature_ik_solver_find_root( - struct bPoseChannel *pchan, - struct bKinematicConstraint *data); + struct bPoseChannel *pchan, + struct bKinematicConstraint *data); struct bPoseChannel *BKE_armature_splineik_solver_find_root( - struct bPoseChannel *pchan, - struct bSplineIKConstraint *data); + struct bPoseChannel *pchan, + 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_pose_eval_init(struct EvaluationContext *eval_ctx, - struct Scene *scene, - struct Object *ob); - -void BKE_pose_eval_init_ik(struct EvaluationContext *eval_ctx, - struct Scene *scene, - struct Object *ob); - -void BKE_pose_eval_bone(struct EvaluationContext *eval_ctx, - struct Scene *scene, - struct Object *ob, - int pchan_index); - -void BKE_pose_constraints_evaluate(struct EvaluationContext *eval_ctx, - struct Scene *scene, - struct Object *ob, - int pchan_index); - -void BKE_pose_bone_done(struct EvaluationContext *eval_ctx, - struct Object *ob, - int pchan_index); - -void BKE_pose_iktree_evaluate(struct EvaluationContext *eval_ctx, - struct Scene *scene, - struct Object *ob, - int rootchan_index); - -void BKE_pose_splineik_evaluate(struct EvaluationContext *eval_ctx, - struct Scene *scene, - struct Object *ob, - int rootchan_index); - -void BKE_pose_eval_flush(struct EvaluationContext *eval_ctx, - struct Scene *scene, - struct Object *ob); - -void BKE_pose_eval_proxy_copy(struct EvaluationContext *eval_ctx, - struct Object *ob); +void BKE_splineik_execute_tree( + struct Depsgraph *depsgraph, struct Scene *scene, + struct Object *ob, struct bPoseChannel *pchan_root, float ctime); + +void BKE_pose_eval_init(struct Depsgraph *depsgraph, + struct Scene *scene, + struct Object *ob); + +void BKE_pose_eval_init_ik(struct Depsgraph *depsgraph, + struct Scene *scene, + struct Object *ob); + +void BKE_pose_eval_bone(struct Depsgraph *depsgraph, + struct Scene *scene, + struct Object *ob, + int pchan_index); + +void BKE_pose_constraints_evaluate(struct Depsgraph *depsgraph, + struct Scene *scene, + struct Object *ob, + int pchan_index); + +void BKE_pose_bone_done(struct Depsgraph *depsgraph, + struct Object *ob, + int pchan_index); + +void BKE_pose_iktree_evaluate(struct Depsgraph *depsgraph, + struct Scene *scene, + struct Object *ob, + int rootchan_index); + +void BKE_pose_splineik_evaluate(struct Depsgraph *depsgraph, + struct Scene *scene, + struct Object *ob, + int rootchan_index); + +void BKE_pose_eval_flush(struct Depsgraph *depsgraph, + struct Scene *scene, + struct Object *ob); + +void BKE_pose_eval_proxy_copy(struct Depsgraph *depsgraph, + struct Object *ob); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h index b5d906b2968..194757561d7 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 4 +#define BLENDER_VERSION 280 +#define BLENDER_SUBVERSION 12 /* 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..c647dd3cc0f 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; @@ -91,11 +93,6 @@ typedef struct CameraParams { float clipsta; float clipend; - /* fields */ - int use_fields; - int field_second; - int field_odd; - /* computed viewplane */ float ycor; float viewdx; @@ -112,7 +109,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, 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 +125,8 @@ 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 Depsgraph *depsgraph, + 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 +145,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_cdderivedmesh.h b/source/blender/blenkernel/BKE_cdderivedmesh.h index 4876461bfe0..61810a5f029 100644 --- a/source/blender/blenkernel/BKE_cdderivedmesh.h +++ b/source/blender/blenkernel/BKE_cdderivedmesh.h @@ -53,6 +53,10 @@ struct DerivedMesh *CDDM_new(int numVerts, int numEdges, int numFaces, * data to not overwrite the original */ struct DerivedMesh *CDDM_from_mesh(struct Mesh *mesh); +/* creates a CDDerivedMesh from the given Mesh with custom allocation type. */ +struct DerivedMesh *CDDM_from_mesh_ex(struct Mesh *mesh, int alloctype); + + struct DerivedMesh *CDDM_from_bmesh(struct BMesh *bm, const bool use_mdisps); /* creates a CDDerivedMesh from the given BMEditMesh */ diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h index 6c517bd02df..94daf615054 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 Depsgraph; #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, struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3]); int cloth_uses_vgroup(struct ClothModifierData *clmd); @@ -235,7 +236,8 @@ 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( + 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..d3a4d2b8d5b --- /dev/null +++ b/source/blender/blenkernel/BKE_collection.h @@ -0,0 +1,115 @@ +/* + * ***** 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 ViewLayer; + +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 ID *owner_id, 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); +bool BKE_collection_object_exists(struct SceneCollection *scene_collection, struct Object *ob); +struct SceneCollection *BKE_collection_from_index(struct Scene *scene, const int index); + +void BKE_collection_new_name_get(struct ID *owner_id, struct SceneCollection *sc_parent, char *rname); + +bool BKE_collection_objects_select(struct ViewLayer *view_layer, struct SceneCollection *scene_collection); + +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_BEGIN(_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_BEGIN(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..54ddb61d922 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 Depsgraph; /* ---------------------------------------------------------------------------- */ #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)(struct Depsgraph *depsgraph, 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(struct Depsgraph *depsgraph, 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 Depsgraph *depsgraph, struct bConstraint *con, struct bConstraintOb *ob, struct ListBase *targets, float ctime); +void BKE_constraints_solve(struct Depsgraph *depsgraph, 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 6de323258bd..12525fe9a50 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,11 +70,14 @@ struct bGPDpalettecolor; struct bGPDbrush; struct wmWindow; struct wmWindowManager; +struct RenderEngineType; struct SpaceText; struct SpaceImage; struct SpaceClip; struct ID; +#include "DNA_object_enums.h" + /* Structs */ struct bContext; @@ -110,7 +119,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 +150,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); @@ -158,14 +171,13 @@ struct SpaceFile *CTX_wm_space_file(const bContext *C); struct SpaceSeq *CTX_wm_space_seq(const bContext *C); struct SpaceOops *CTX_wm_space_outliner(const bContext *C); struct SpaceNla *CTX_wm_space_nla(const bContext *C); -struct SpaceTime *CTX_wm_space_time(const bContext *C); struct SpaceNode *CTX_wm_space_node(const bContext *C); -struct SpaceLogic *CTX_wm_space_logic(const bContext *C); struct SpaceIpo *CTX_wm_space_graph(const bContext *C); struct SpaceAction *CTX_wm_space_action(const bContext *C); struct SpaceInfo *CTX_wm_space_info(const bContext *C); struct SpaceUserPref *CTX_wm_space_userpref(const bContext *C); struct SpaceClip *CTX_wm_space_clip(const bContext *C); +struct SpaceTopBar *CTX_wm_space_topbar(const bContext *C); void CTX_wm_manager_set(bContext *C, struct wmWindowManager *wm); void CTX_wm_window_set(bContext *C, struct wmWindow *win); @@ -173,6 +185,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); @@ -243,9 +256,16 @@ 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 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); @@ -300,6 +320,12 @@ 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); + +/* Will Return NULL if depsgraph is not allocated yet. + * Only used by handful of operators which are run on file load. + */ +struct Depsgraph *CTX_data_depsgraph_on_load(const bContext *C); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_crazyspace.h b/source/blender/blenkernel/BKE_crazyspace.h index ee6c5c57678..e9745ed50fa 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 Depsgraph; /* crazyspace.c */ float (*BKE_crazyspace_get_mapped_editverts( - struct Scene *scene, struct Object *obedit))[3]; + struct Depsgraph *depsgraph, 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, + struct Depsgraph *depsgraph, 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, + struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]); void BKE_crazyspace_build_sculpt( - struct Scene *scene, struct Object *ob, + struct Depsgraph *depsgraph, 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..975cea7364d 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 Depsgraph; 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(struct Depsgraph *depsgraph, 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( + struct Depsgraph *depsgraph, 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( + struct Depsgraph *depsgraph, + 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..6559f9a954f 100644 --- a/source/blender/blenkernel/BKE_data_transfer.h +++ b/source/blender/blenkernel/BKE_data_transfer.h @@ -38,6 +38,7 @@ extern "C" { #include "BKE_customdata.h" +struct Depsgraph; struct Object; struct Scene; struct SpaceTransform; @@ -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, + struct Depsgraph *depsgraph, 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, + struct Depsgraph *depsgraph, 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, + struct Depsgraph *depsgraph, 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..09e9b667369 100644 --- a/source/blender/blenkernel/BKE_displist.h +++ b/source/blender/blenkernel/BKE_displist.h @@ -60,8 +60,8 @@ enum { struct Scene; struct Object; struct ListBase; +struct Depsgraph; struct DerivedMesh; -struct EvaluationContext; /* used for curves, nurbs, mball, importing */ typedef struct DispList { @@ -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( + struct Depsgraph *depsgraph, 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 Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, const bool for_orco); +void BKE_displist_make_curveTypes_forRender( + struct Depsgraph *depsgraph, 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 Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct ListBase *dispbase); +void BKE_displist_make_mball( + struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); +void BKE_displist_make_mball_forRender( + struct Depsgraph *depsgraph, 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(struct Depsgraph *depsgraph, 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( + struct Depsgraph *depsgraph, 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..8f795bc7535 100644 --- a/source/blender/blenkernel/BKE_dynamicpaint.h +++ b/source/blender/blenkernel/BKE_dynamicpaint.h @@ -27,7 +27,9 @@ * \ingroup bke */ +struct Depsgraph; struct Scene; +struct ViewLayer; /* 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, struct Depsgraph *depsgraph, 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, struct Depsgraph *depsgraph, 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..5e456fea64f 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 Depsgraph; /** * 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( + struct Depsgraph *depsgraph, struct BMEditMesh *em, struct Scene *scene, int *r_numVerts))[3]; #endif /* __BKE_EDITMESH_H__ */ diff --git a/source/blender/blenkernel/BKE_bullet.h b/source/blender/blenkernel/BKE_editmesh_tangent.h index dc522d1b22c..9553fbc1a5c 100644 --- a/source/blender/blenkernel/BKE_bullet.h +++ b/source/blender/blenkernel/BKE_editmesh_tangent.h @@ -15,30 +15,26 @@ * 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. + * Contributor(s): Joseph Eagar. * * ***** END GPL LICENSE BLOCK ***** */ -#ifndef __BKE_BULLET_H__ -#define __BKE_BULLET_H__ -/** \file BKE_bullet.h +#ifndef __BKE_EDITMESH_TANGENT_H__ +#define __BKE_EDITMESH_TANGENT_H__ + +/** \file BKE_editmesh_tangent.h * \ingroup bke */ -struct BulletSoftBody; - - -/* allocates and initializes general main data */ -extern struct BulletSoftBody *bsbNew(void); - -/* frees internal data and softbody itself */ -extern void bsbFree(struct BulletSoftBody *sb); - -#endif +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..914dd650493 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 Depsgraph; 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; + struct Depsgraph *depsgraph; 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( + struct Depsgraph *depsgraph, 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(struct Depsgraph *depsgraph, 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..8e04fe2c23a 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 Depsgraph; /* old interface */ -void initElbeemMesh(struct Scene *scene, struct Object *ob, +void initElbeemMesh(struct Depsgraph *depsgraph, 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 ce8de456697..e184fd3796b 100644 --- a/source/blender/blenkernel/BKE_global.h +++ b/source/blender/blenkernel/BKE_global.h @@ -102,7 +102,6 @@ typedef struct Global { /* G.f */ #define G_RENDER_OGL (1 << 0) #define G_SWAP_EXCHANGE (1 << 1) -/* also uses G_FILE_AUTOPLAY */ /* #define G_RENDER_SHADOW (1 << 3) */ /* temp flag, removed */ #define G_BACKBUFSEL (1 << 4) #define G_PICKSEL (1 << 5) @@ -141,28 +140,19 @@ enum { G_DEBUG_DEPSGRAPH_TIME), G_DEBUG_SIMDATA = (1 << 14), /* sim debug data display */ G_DEBUG_GPU_MEM = (1 << 15), /* gpu memory in status bar */ - G_DEBUG_GPU = (1 << 16), /* gpu debug */ + G_DEBUG_GPU = (1 << 16), /* gpu debug */ G_DEBUG_IO = (1 << 17), /* IO Debugging (for Collada, ...)*/ + G_DEBUG_GPU_SHADERS = (1 << 18), /* 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 */ #define G_AUTOPACK (1 << 0) #define G_FILE_COMPRESS (1 << 1) -#define G_FILE_AUTOPLAY (1 << 2) - -#ifdef DNA_DEPRECATED_ALLOW -#define G_FILE_ENABLE_ALL_FRAMES (1 << 3) /* deprecated */ -#define G_FILE_SHOW_DEBUG_PROPS (1 << 4) /* deprecated */ -#define G_FILE_SHOW_FRAMERATE (1 << 5) /* deprecated */ -/* #define G_FILE_SHOW_PROFILE (1 << 6) */ /* deprecated */ -/* #define G_FILE_LOCK (1 << 7) */ /* deprecated */ -/* #define G_FILE_SIGN (1 << 8) */ /* deprecated */ -#endif /* DNA_DEPRECATED_ALLOW */ #define G_FILE_USERPREFS (1 << 9) #define G_FILE_NO_UI (1 << 10) diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h index e07dd259970..0195d1f1243 100644 --- a/source/blender/blenkernel/BKE_group.h +++ b/source/blender/blenkernel/BKE_group.h @@ -34,24 +34,52 @@ */ struct Base; -struct EvaluationContext; +struct Depsgraph; struct Group; struct Main; 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(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *parent, struct Group *group); + +/* Dependency graph evaluation. */ + +void BKE_group_eval_view_layers(struct Depsgraph *depsgraph, + struct Group *group); + +/* Helper macros. */ + +#define FOREACH_GROUP_BASE_BEGIN(_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_BEGIN(_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 \ + } ((void)0) #endif /* __BKE_GROUP_H__ */ diff --git a/source/blender/blenkernel/BKE_icons.h b/source/blender/blenkernel/BKE_icons.h index 686dba21283..766704b8f9c 100644 --- a/source/blender/blenkernel/BKE_icons.h +++ b/source/blender/blenkernel/BKE_icons.h @@ -36,16 +36,45 @@ typedef void (*DrawInfoFreeFP)(void *drawinfo); +enum { + /** ID preview: obj is #ID. */ + ICON_DATA_ID = 0, + /** Preview: obj is #PreviewImage */ + ICON_DATA_PREVIEW, + /** 2D triangles: obj is #Icon_Geom */ + ICON_DATA_GEOM, +}; + struct Icon { void *drawinfo; + /** + * Data defined by #obj_type + * \note for #ICON_DATA_GEOM the memory is owned by the icon, + * could be made into a flag if we want that to be optional. + */ void *obj; + char obj_type; + /** Internal use only. */ + char flag; /** #ID_Type or 0 when not used for ID preview. */ short id_type; DrawInfoFreeFP drawinfo_free; }; +/** Used for #ICON_DATA_GEOM, assigned to #Icon.obj. */ +struct Icon_Geom { + int icon_id; + int coords_len; + int coords_range[2]; + const unsigned char (*coords)[2]; + const unsigned char (*colors)[4]; + /* when not NULL, the memory of coords and colors is a sub-region of this pointer. */ + const void *mem; +}; + typedef struct Icon Icon; +struct ImBuf; struct PreviewImage; struct ID; @@ -68,7 +97,8 @@ void BKE_icon_set(const int icon_id, struct Icon *icon); /* remove icon and free data if library object becomes invalid */ void BKE_icon_id_delete(struct ID *id); -void BKE_icon_delete(const int icon_id); +bool BKE_icon_delete(const int icon_id); +bool BKE_icon_delete_unmanaged(const int icon_id); /* report changes - icon needs to be recalculated */ void BKE_icon_changed(const int icon_id); @@ -120,6 +150,14 @@ struct PreviewImage *BKE_previewimg_cached_thumbnail_read( void BKE_previewimg_cached_release(const char *name); void BKE_previewimg_cached_release_pointer(struct PreviewImage *prv); +int BKE_icon_geom_ensure(struct Icon_Geom *geom); +struct Icon_Geom *BKE_icon_geom_from_memory(const uchar *data, size_t data_len); +struct Icon_Geom *BKE_icon_geom_from_file(const char *filename); + +struct ImBuf *BKE_icon_geom_rasterize( + const struct Icon_Geom *geom, + const unsigned int size_x, const unsigned int size_y); + #define ICON_RENDER_DEFAULT_HEIGHT 32 #endif /* __BKE_ICONS_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..6e9f83cf8a9 100644 --- a/source/blender/blenkernel/BKE_lattice.h +++ b/source/blender/blenkernel/BKE_lattice.h @@ -38,11 +38,13 @@ struct Lattice; struct Main; +struct Mesh; struct Object; struct Scene; struct DerivedMesh; struct BPoint; struct MDeformVert; +struct Depsgraph; void BKE_lattice_resize(struct Lattice *lt, int u, int v, int w, struct Object *ltOb); void BKE_lattice_init(struct Lattice *lt); @@ -61,23 +63,24 @@ 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, - struct DerivedMesh *dm, float (*vertexCos)[3], + struct Mesh *mesh, float (*vertexCos)[3], int numVerts, const char *vgroup, float influence); void armature_deform_verts(struct Object *armOb, struct Object *target, - struct DerivedMesh *dm, float (*vertexCos)[3], + const struct Mesh *mesh, float (*vertexCos)[3], float (*defMats)[3][3], int numVerts, int deformflag, float (*prevCos)[3], const char *defgrp_name); 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(struct Depsgraph *depsgraph, 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); @@ -99,9 +102,17 @@ void BKE_lattice_bitmap_from_flag(struct Lattice *lt, unsigned int *bitmap, cons /* **** Depsgraph evaluation **** */ -struct EvaluationContext; +struct Depsgraph; -void BKE_lattice_eval_geometry(struct EvaluationContext *eval_ctx, +void BKE_lattice_eval_geometry(struct Depsgraph *depsgraph, 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..27e3d32a510 --- /dev/null +++ b/source/blender/blenkernel/BKE_layer.h @@ -0,0 +1,420 @@ +/* + * ***** 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 Depsgraph; +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_default_view(const struct Scene *scene); +struct ViewLayer *BKE_view_layer_default_render(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); + +struct LayerCollection *BKE_layer_collection_first_from_scene_collection(struct ViewLayer *view_layer, const struct SceneCollection *scene_collection); +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_view_layer( + struct Depsgraph *depsgraph, + struct ID *owner_id, + struct ViewLayer *view_layer); + +void BKE_layer_eval_view_layer_indexed( + struct Depsgraph *depsgraph, + struct ID *owner_id, + int view_layer_index); + +/* iterators */ + +void BKE_view_layer_selected_objects_iterator_begin(BLI_Iterator *iter, void *data_in); +void BKE_view_layer_selected_objects_iterator_next(BLI_Iterator *iter); +void BKE_view_layer_selected_objects_iterator_end(BLI_Iterator *iter); + +void BKE_view_layer_visible_objects_iterator_begin(BLI_Iterator *iter, void *data_in); +void BKE_view_layer_visible_objects_iterator_next(BLI_Iterator *iter); +void BKE_view_layer_visible_objects_iterator_end(BLI_Iterator *iter); + +struct ObjectsInModeIteratorData { + int object_mode; + struct ViewLayer *view_layer; + struct Base *base_active; +}; + +void BKE_view_layer_renderable_objects_iterator_begin(BLI_Iterator *iter, void *data_in); +void BKE_view_layer_renderable_objects_iterator_next(BLI_Iterator *iter); +void BKE_view_layer_renderable_objects_iterator_end(BLI_Iterator *iter); + +void BKE_view_layer_bases_in_mode_iterator_begin(BLI_Iterator *iter, void *data_in); +void BKE_view_layer_bases_in_mode_iterator_next(BLI_Iterator *iter); +void BKE_view_layer_bases_in_mode_iterator_end(BLI_Iterator *iter); + +void BKE_view_layer_selected_bases_iterator_begin(BLI_Iterator *iter, void *data_in); +void BKE_view_layer_selected_bases_iterator_next(BLI_Iterator *iter); +void BKE_view_layer_selected_bases_iterator_end(BLI_Iterator *iter); + +void BKE_view_layer_visible_bases_iterator_begin(BLI_Iterator *iter, void *data_in); +void BKE_view_layer_visible_bases_iterator_next(BLI_Iterator *iter); +void BKE_view_layer_visible_bases_iterator_end(BLI_Iterator *iter); + +#define FOREACH_SELECTED_OBJECT_BEGIN(view_layer, _instance) \ + ITER_BEGIN(BKE_view_layer_selected_objects_iterator_begin, \ + BKE_view_layer_selected_objects_iterator_next, \ + BKE_view_layer_selected_objects_iterator_end, \ + view_layer, Object *, _instance) + +#define FOREACH_SELECTED_OBJECT_END \ + ITER_END + +#define FOREACH_VISIBLE_OBJECT_BEGIN(view_layer, _instance) \ + ITER_BEGIN(BKE_view_layer_visible_objects_iterator_begin, \ + BKE_view_layer_visible_objects_iterator_next, \ + BKE_view_layer_visible_objects_iterator_end, \ + view_layer, Object *, _instance) + +#define FOREACH_VISIBLE_OBJECT_END \ + ITER_END + + +#define FOREACH_BASE_IN_MODE_BEGIN(_view_layer, _object_mode, _instance) \ +{ \ + struct ObjectsInModeIteratorData data_ = { \ + .object_mode = _object_mode, \ + .view_layer = _view_layer, \ + .base_active = _view_layer->basact, \ + }; \ + ITER_BEGIN(BKE_view_layer_bases_in_mode_iterator_begin, \ + BKE_view_layer_bases_in_mode_iterator_next, \ + BKE_view_layer_bases_in_mode_iterator_end, \ + &data_, Base *, _instance) + +#define FOREACH_BASE_IN_MODE_END \ + ITER_END; \ +} ((void)0) + +#define FOREACH_BASE_IN_EDIT_MODE_BEGIN(_view_layer, _instance) \ + FOREACH_BASE_IN_MODE_BEGIN(_view_layer, OB_MODE_EDIT, _instance) + +#define FOREACH_BASE_IN_EDIT_MODE_END \ + FOREACH_BASE_IN_MODE_END + +#define FOREACH_OBJECT_IN_MODE_BEGIN(_view_layer, _object_mode, _instance) \ + FOREACH_BASE_IN_MODE_BEGIN(_view_layer, _object_mode, _base) { \ + Object *_instance = _base->object; + +#define FOREACH_OBJECT_IN_MODE_END \ + } FOREACH_BASE_IN_MODE_END + +#define FOREACH_OBJECT_IN_EDIT_MODE_BEGIN(_view_layer, _instance) \ + FOREACH_BASE_IN_EDIT_MODE_BEGIN(_view_layer, _base) { \ + Object *_instance = _base->object; + +#define FOREACH_OBJECT_IN_EDIT_MODE_END \ + } FOREACH_BASE_IN_EDIT_MODE_END + +#define FOREACH_SELECTED_BASE_BEGIN(view_layer, _instance) \ + ITER_BEGIN(BKE_view_layer_selected_bases_iterator_begin, \ + BKE_view_layer_selected_bases_iterator_next, \ + BKE_view_layer_selected_bases_iterator_end, \ + view_layer, Base *, _instance) + +#define FOREACH_SELECTED_BASE_END \ + ITER_END + +#define FOREACH_VISIBLE_BASE_BEGIN(view_layer, _instance) \ + ITER_BEGIN(BKE_view_layer_visible_bases_iterator_begin, \ + BKE_view_layer_visible_bases_iterator_next, \ + BKE_view_layer_visible_bases_iterator_end, \ + view_layer, Base *, _instance) + +#define FOREACH_VISIBLE_BASE_END \ + ITER_END + + +#define FOREACH_OBJECT_BEGIN(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 \ + } \ +} ((void)0) + +#define FOREACH_OBJECT_FLAG_BEGIN(scene, view_layer, flag, _instance) \ +{ \ + IteratorBeginCb func_begin; \ + IteratorCb func_next, func_end; \ + void *data_in; \ + \ + if (flag == SELECT) { \ + func_begin = &BKE_view_layer_selected_objects_iterator_begin; \ + func_next = &BKE_view_layer_selected_objects_iterator_next; \ + func_end = &BKE_view_layer_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; \ +} ((void)0) + +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; +}; + +#define FOREACH_OBJECT_RENDERABLE_BEGIN(scene_, _instance) \ +{ \ + struct ObjectsRenderableIteratorData data_ = { \ + .scene = (scene_), \ + }; \ + ITER_BEGIN(BKE_view_layer_renderable_objects_iterator_begin, \ + BKE_view_layer_renderable_objects_iterator_next, \ + BKE_view_layer_renderable_objects_iterator_end, \ + &data_, Object *, _instance) + + +#define FOREACH_OBJECT_RENDERABLE_END \ + ITER_END; \ +} ((void)0) + + +/* layer_utils.c */ + +struct ObjectsInModeParams { + int object_mode; + uint no_dup_data : 1; + + bool (*filter_fn)(struct Object *ob, void *user_data); + void *filter_userdata; +}; + +Base **BKE_view_layer_array_from_bases_in_mode_params( + struct ViewLayer *view_layer, uint *r_len, + const struct ObjectsInModeParams *params); + +struct Object **BKE_view_layer_array_from_objects_in_mode_params( + struct ViewLayer *view_layer, uint *len, + const struct ObjectsInModeParams *params); + +#define BKE_view_layer_array_from_objects_in_mode(view_layer, r_len, ...) \ + BKE_view_layer_array_from_objects_in_mode_params( \ + view_layer, r_len, \ + &(const struct ObjectsInModeParams)__VA_ARGS__) + +#define BKE_view_layer_array_from_bases_in_mode(view_layer, r_len, ...) \ + BKE_view_layer_array_from_bases_in_mode_params( \ + view_layer, r_len, \ + &(const struct ObjectsInModeParams)__VA_ARGS__) + +bool BKE_view_layer_filter_edit_mesh_has_uvs(struct Object *ob, void *user_data); +bool BKE_view_layer_filter_edit_mesh_has_edges(struct Object *ob, void *user_data); + +/* Utility macros that wrap common args (add more as needed). */ + +#define BKE_view_layer_array_from_objects_in_edit_mode(view_layer, r_len) \ + BKE_view_layer_array_from_objects_in_mode( \ + view_layer, r_len, { \ + .object_mode = OB_MODE_EDIT}); + +#define BKE_view_layer_array_from_bases_in_edit_mode(view_layer, r_len) \ + BKE_view_layer_array_from_bases_in_mode( \ + view_layer, r_len, { \ + .object_mode = OB_MODE_EDIT}); + +#define BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, r_len) \ + BKE_view_layer_array_from_objects_in_mode( \ + view_layer, r_len, { \ + .object_mode = OB_MODE_EDIT, \ + .no_dup_data = true}); + +#define BKE_view_layer_array_from_bases_in_edit_mode_unique_data(view_layer, r_len) \ + BKE_view_layer_array_from_bases_in_mode( \ + view_layer, r_len, { \ + .object_mode = OB_MODE_EDIT, \ + .no_dup_data = true}); + +#define BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(view_layer, r_len) \ + BKE_view_layer_array_from_objects_in_mode( \ + view_layer, r_len, { \ + .object_mode = OB_MODE_EDIT, \ + .no_dup_data = true, \ + .filter_fn = BKE_view_layer_filter_edit_mesh_has_uvs}); + + +#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..c34571fdd7a 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -78,6 +78,7 @@ enum { /* XXX TODO Do we want to keep that? would rather try to get rid of it... */ LIB_ID_COPY_ACTIONS = 1 << 19, /* EXCEPTION! Deep-copy actions used by animdata of copied ID. */ LIB_ID_COPY_KEEP_LIB = 1 << 20, /* Keep the library pointer when copying datablock outside of bmain. */ + LIB_ID_COPY_NO_ANIMDATA = 1 << 21, /* Don't copy id->adt, used by ID datablock localization routines. */ }; void BKE_libblock_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, const int flag); @@ -148,6 +149,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 +160,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..6f32d565562 --- /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, const bool force_auto); +void BKE_main_override_static_operations_create(struct Main *bmain, const bool force_auto); + +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_linestyle.h b/source/blender/blenkernel/BKE_linestyle.h index 3ba4fbe0338..376a324d25c 100644 --- a/source/blender/blenkernel/BKE_linestyle.h +++ b/source/blender/blenkernel/BKE_linestyle.h @@ -48,6 +48,7 @@ struct Main; struct Object; struct ColorBand; struct bContext; +struct ViewLayer; void BKE_linestyle_init(struct FreestyleLineStyle *linestyle); FreestyleLineStyle *BKE_linestyle_new(struct Main *bmain, const char *name); @@ -59,7 +60,7 @@ FreestyleLineStyle *BKE_linestyle_copy(struct Main *bmain, const FreestyleLineSt void BKE_linestyle_make_local(struct Main *bmain, struct FreestyleLineStyle *linestyle, const bool lib_local); -FreestyleLineStyle *BKE_linestyle_active_from_scene(struct Scene *scene); +FreestyleLineStyle *BKE_linestyle_active_from_view_layer(struct ViewLayer *view_layer); LineStyleModifier *BKE_linestyle_color_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type); LineStyleModifier *BKE_linestyle_alpha_modifier_add(FreestyleLineStyle *linestyle, const char *name, int type); diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h index e224155726f..647af88d980 100644 --- a/source/blender/blenkernel/BKE_main.h +++ b/source/blender/blenkernel/BKE_main.h @@ -48,7 +48,7 @@ extern "C" { #endif -struct EvaluationContext; +struct Depsgraph; struct Library; struct MainLock; struct GHash; @@ -110,6 +110,7 @@ typedef struct Main { ListBase vfont; ListBase text; ListBase speaker; + ListBase lightprobe; ListBase sound; ListBase group; ListBase armature; @@ -125,12 +126,10 @@ typedef struct Main { ListBase mask; ListBase linestyle; ListBase cachefiles; + ListBase workspaces; char id_tag_update[MAX_LIBARRAY]; - /* Evaluation context used by viewport */ - struct EvaluationContext *eval_ctx; - /* Must be generated, used and freed by same code - never assume this is valid data unless you know * when, who and how it was created. * Used by code doing a lot of remapping etc. at once to speed things up. */ diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h index 5598f0dc473..976ee5b2691 100644 --- a/source/blender/blenkernel/BKE_mask.h +++ b/source/blender/blenkernel/BKE_mask.h @@ -32,7 +32,7 @@ * \ingroup bke */ -struct EvaluationContext; +struct Depsgraph; struct ImageUser; struct Image; struct ListBase; @@ -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]); @@ -237,8 +236,8 @@ float *BKE_mask_point_segment_feather_diff(struct MaskSpline *spline, struct Mas void BKE_mask_layer_evaluate_animation(struct MaskLayer *masklay, const float ctime); void BKE_mask_layer_evaluate_deform(struct MaskLayer *masklay, const float ctime); -void BKE_mask_eval_animation(struct EvaluationContext *eval_ctx, struct Mask *mask); -void BKE_mask_eval_update(struct EvaluationContext *eval_ctx, struct Mask *mask); +void BKE_mask_eval_animation(struct Depsgraph *depsgraph, struct Mask *mask); +void BKE_mask_eval_update(struct Depsgraph *depsgraph, struct Mask *mask); /* mask_rasterize.c */ struct MaskRasterHandle; diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index f7850913014..43f36618c19 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -97,26 +97,19 @@ struct Material *BKE_material_pop_id(struct Main *bmain, struct ID *id, int inde void BKE_material_clear_id(struct Main *bmain, struct ID *id, bool update_data); /* rendering */ -void init_render_material(struct Material *, int, float *); -void init_render_materials(struct Main *, int r_mode, float *amd, bool do_default_material); -void end_render_material(struct Material *); -void end_render_materials(struct Main *); - -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 Depsgraph; + +void BKE_material_eval(struct Depsgraph *depsgraph, struct Material *material); #ifdef __cplusplus } diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h index f02704ba903..a486e8319c6 100644 --- a/source/blender/blenkernel/BKE_mball.h +++ b/source/blender/blenkernel/BKE_mball.h @@ -32,6 +32,7 @@ * \since March 2001 * \author nzc */ +struct Depsgraph; struct Main; struct MetaBall; struct Object; @@ -71,9 +72,16 @@ void BKE_mball_select_swap(struct MetaBall *mb); /* **** Depsgraph evaluation **** */ -struct EvaluationContext; +struct Depsgraph; -void BKE_mball_eval_geometry(struct EvaluationContext *eval_ctx, +void BKE_mball_eval_geometry(struct Depsgraph *depsgraph, struct MetaBall *mball); +/* Draw Cache */ + +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..df652df177d 100644 --- a/source/blender/blenkernel/BKE_mball_tessellate.h +++ b/source/blender/blenkernel/BKE_mball_tessellate.h @@ -23,12 +23,12 @@ /** \file BKE_mball_tessellate.h * \ingroup bke */ -struct EvaluationContext; +struct Depsgraph; struct Object; struct Scene; void BKE_mball_polygonize( - struct EvaluationContext *eval_ctx, struct Scene *scene, + struct Depsgraph *depsgraph, 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 bf135254941..afb087ed822 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -33,7 +33,10 @@ struct ID; struct BMeshCreateParams; +struct BMeshFromMeshParams; +struct BMeshToMeshParams; struct BoundBox; +struct Depsgraph; struct EdgeHash; struct ListBase; struct LinkNode; @@ -70,10 +73,16 @@ extern "C" { /* *** mesh.c *** */ +struct BMesh *BKE_mesh_to_bmesh_ex( + struct Mesh *me, + const struct BMeshCreateParams *create_params, + const struct BMeshFromMeshParams *convert_params); struct BMesh *BKE_mesh_to_bmesh( struct Mesh *me, struct Object *ob, const bool add_key_index, const struct BMeshCreateParams *params); +struct Mesh *BKE_bmesh_to_mesh(struct BMesh *bm, const struct BMeshToMeshParams *params); + int poly_find_loop_from_vert( const struct MPoly *poly, const struct MLoop *loopstart, unsigned vert); @@ -92,6 +101,17 @@ 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); +struct Mesh * BKE_mesh_from_template( + const struct Mesh *me_src, + int numVerts, int numEdges, int numTessFaces, + int numLoops, int numPolys); + +bool BKE_mesh_ensure_edit_data(struct Mesh *me); +bool BKE_mesh_clear_edit_data(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 +135,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(struct Depsgraph *depsgraph, 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,18 +145,20 @@ 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, - const char *new_name, const bool do_tessface); +bool BKE_mesh_uv_cdlayer_rename_index( + struct Mesh *me, const int loop_index, const int face_index, + const char *new_name, const bool do_tessface); bool BKE_mesh_uv_cdlayer_rename(struct Mesh *me, const char *old_name, const char *new_name, bool do_tessface); 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, - int apply_modifiers, int settings, int calc_tessface, int calc_undeformed); +struct Mesh *BKE_mesh_new_from_object(struct Depsgraph *depsgraph, struct Main *bmain, struct Scene *sce, struct Object *ob, + int apply_modifiers, int calc_tessface, int calc_undeformed); /* vertex level transformations & checks (no derived mesh) */ @@ -330,7 +352,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, @@ -366,6 +388,19 @@ void BKE_mesh_polygon_flip_ex( void BKE_mesh_polygon_flip(struct MPoly *mpoly, struct MLoop *mloop, struct CustomData *ldata); void BKE_mesh_polygons_flip(struct MPoly *mpoly, struct MLoop *mloop, struct CustomData *ldata, int totpoly); +/* merge verts */ +/* Enum for merge_mode of CDDM_merge_verts. + * Refer to mesh.c for details. */ +enum { + MESH_MERGE_VERTS_DUMP_IF_MAPPED, + MESH_MERGE_VERTS_DUMP_IF_EQUAL, +}; +struct Mesh *BKE_mesh_merge_verts( + struct Mesh *mesh, + const int *vtargetmap, const int tot_vtargetmap, + const int merge_mode); + + /* flush flags */ void BKE_mesh_flush_hidden_from_verts_ex( const struct MVert *mvert, @@ -408,7 +443,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( @@ -438,11 +472,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(struct Depsgraph *depsgraph, 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 18cde156f5e..02337110289 100644 --- a/source/blender/blenkernel/BKE_modifier.h +++ b/source/blender/blenkernel/BKE_modifier.h @@ -33,11 +33,12 @@ #include "BKE_customdata.h" struct ID; +struct Depsgraph; struct DerivedMesh; -struct DagForest; -struct DagNode; +struct Mesh; struct Object; struct Scene; +struct ViewLayer; struct ListBase; struct bArmature; struct Main; @@ -126,19 +127,21 @@ typedef enum ModifierApplyFlag { */ } ModifierApplyFlag; - typedef struct ModifierUpdateDepsgraphContext { struct Scene *scene; struct Object *object; - - /* Old depsgraph node handle. */ - struct DagForest *forest; - struct DagNode *obNode; - - /* new depsgraph node handle. */ struct DepsNodeHandle *node; } ModifierUpdateDepsgraphContext; +/* Contains the information for deformXXX and applyXXX functions below that + * doesn't change between consecutive modifiers. */ +typedef struct ModifierEvalContext { + struct Depsgraph *depsgraph; + struct Object *object; + ModifierApplyFlag flag; +} ModifierEvalContext; + + typedef struct ModifierTypeInfo { /* The user visible name for this modifier */ char name[32]; @@ -162,35 +165,37 @@ typedef struct ModifierTypeInfo { */ void (*copyData)(struct ModifierData *md, struct ModifierData *target); - /********************* Deform modifier functions *********************/ + + /********************* Deform modifier functions *********************/ /* DEPRECATED */ /* Only for deform types, should apply the deformation * to the given vertex array. If the deformer requires information from * 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, - float (*vertexCos)[3], int numVerts, - ModifierApplyFlag flag); + void (*deformVerts_DM)(struct ModifierData *md, const struct ModifierEvalContext *ctx, + struct DerivedMesh *derivedData, + float (*vertexCos)[3], int numVerts); /* Like deformMatricesEM but called from object mode (for supporting modifiers in sculpt mode) */ - void (*deformMatrices)(struct ModifierData *md, struct Object *ob, - struct DerivedMesh *derivedData, - float (*vertexCos)[3], float (*defMats)[3][3], int numVerts); + void (*deformMatrices_DM)(struct ModifierData *md, const struct ModifierEvalContext *ctx, + 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, - float (*vertexCos)[3], int numVerts); + void (*deformVertsEM_DM)(struct ModifierData *md, const struct ModifierEvalContext *ctx, + 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_DM)(struct ModifierData *md, const struct ModifierEvalContext *ctx, + struct BMEditMesh *editData, + struct DerivedMesh *derivedData, float (*vertexCos)[3], float (*defMats)[3][3], int numVerts); - /********************* Non-deform modifier functions *********************/ + /********************* Non-deform modifier functions *********************/ /* DEPRECATED */ /* For non-deform types: apply the modifier and return a derived * data object (type is dependent on object type). @@ -199,21 +204,11 @@ typedef struct ModifierTypeInfo { * should read the object data from the derived object instead of the * actual object data. * - * The useRenderParams argument indicates if the modifier is being - * applied in the service of the renderer which may alter quality - * settings. - * - * The isFinalCalc parameter indicates if the modifier is being - * calculated for a final result or for something temporary - * (like orcos). This is a hack at the moment, it is meant so subsurf - * can know if it is safe to reuse its internal cache. - * * 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, - ModifierApplyFlag flag); + struct DerivedMesh *(*applyModifier_DM)(struct ModifierData *md, const struct ModifierEvalContext *ctx, + struct DerivedMesh *derivedData); /* Like applyModifier but called during editmode (for supporting * modifiers). @@ -222,10 +217,60 @@ 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_DM)(struct ModifierData *md, const struct ModifierEvalContext *ctx, + struct BMEditMesh *editData, + struct DerivedMesh *derivedData); + + + /********************* Deform modifier functions *********************/ + + /* Only for deform types, should apply the deformation + * to the given vertex array. If the deformer requires information from + * the object it can obtain it from the mesh argument if non-NULL, + * and otherwise the ob argument. + */ + void (*deformVerts)(struct ModifierData *md, const struct ModifierEvalContext *ctx, + struct Mesh *mesh, float (*vertexCos)[3], int numVerts); + + /* Like deformMatricesEM but called from object mode (for supporting modifiers in sculpt mode) */ + void (*deformMatrices)(struct ModifierData *md, const struct ModifierEvalContext *ctx, + struct Mesh *mesh, float (*vertexCos)[3], float (*defMats)[3][3], int numVerts); + + /* Like deformVerts but called during editmode (for supporting modifiers) + */ + void (*deformVertsEM)(struct ModifierData *md, const struct ModifierEvalContext *ctx, + struct BMEditMesh *editData, + struct Mesh *mesh, float (*vertexCos)[3], int numVerts); + + /* Set deform matrix per vertex for crazyspace correction */ + void (*deformMatricesEM)(struct ModifierData *md, const struct ModifierEvalContext *ctx, + struct BMEditMesh *editData, + struct Mesh *mesh, float (*vertexCos)[3], float (*defMats)[3][3], int numVerts); + + /********************* Non-deform modifier functions *********************/ + + /* For non-deform types: apply the modifier and return a mesh object. + * + * The mesh argument should always be non-NULL; the modifier + * should read the object data from the mesh object instead of the + * actual object data. + * + * The modifier may reuse the mesh argument (i.e. return it in + * modified form), but must not release it. + */ + struct Mesh *(*applyModifier)(struct ModifierData *md, const struct ModifierEvalContext *ctx, + struct Mesh *mesh); + + /* Like applyModifier but called during editmode (for supporting + * modifiers). + * + * The mesh object that is returned must support the operations that + * are expected from editmode objects. The same qualifications regarding + * mesh apply as for applyModifier. + */ + struct Mesh *(*applyModifierEM)(struct ModifierData *md, const struct ModifierEvalContext *ctx, + struct BMEditMesh *editData, + struct Mesh *mesh); /********************* Optional functions *********************/ @@ -272,22 +317,13 @@ 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, - const ModifierUpdateDepsgraphContext *ctx); - /* 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, const ModifierUpdateDepsgraphContext *ctx); - + /* Should return true if the modifier needs to be recalculated on time * changes. * @@ -433,29 +469,84 @@ void modifier_path_init(char *path, int path_maxlen, const char *name); const char *modifier_path_relbase(struct Object *ob); -/* wrappers for modifier callbacks */ +/* wrappers for modifier callbacks that ensure valid normals */ struct DerivedMesh *modwrap_applyModifier( - ModifierData *md, struct Object *ob, - struct DerivedMesh *dm, - ModifierApplyFlag flag); + ModifierData *md, const struct ModifierEvalContext *ctx, + struct DerivedMesh *dm); struct DerivedMesh *modwrap_applyModifierEM( - ModifierData *md, struct Object *ob, - struct BMEditMesh *em, - struct DerivedMesh *dm, - ModifierApplyFlag flag); + ModifierData *md, const struct ModifierEvalContext *ctx, + struct BMEditMesh *em, struct DerivedMesh *dm); void modwrap_deformVerts( - ModifierData *md, struct Object *ob, + ModifierData *md, const struct ModifierEvalContext *ctx, struct DerivedMesh *dm, - float (*vertexCos)[3], int numVerts, - ModifierApplyFlag flag); + float (*vertexCos)[3], int numVerts); void modwrap_deformVertsEM( - ModifierData *md, struct Object *ob, + ModifierData *md, const struct ModifierEvalContext *ctx, struct BMEditMesh *em, struct DerivedMesh *dm, float (*vertexCos)[3], int numVerts); +/* wrappers for modifier callbacks that accept Mesh and select the proper implementation + * depending on if the modifier has been ported to Mesh or is still using DerivedMesh + */ + +void modifier_deformVerts( + struct ModifierData *md, const struct ModifierEvalContext *ctx, + struct Mesh *mesh, float (*vertexCos)[3], int numVerts); + +void modifier_deformMatrices( + struct ModifierData *md, const struct ModifierEvalContext *ctx, + struct Mesh *mesh, float (*vertexCos)[3], float (*defMats)[3][3], int numVerts); + +void modifier_deformVertsEM( + struct ModifierData *md, const struct ModifierEvalContext *ctx, + struct BMEditMesh *editData, struct Mesh *mesh, + float (*vertexCos)[3], int numVerts); + +void modifier_deformMatricesEM( + struct ModifierData *md, const struct ModifierEvalContext *ctx, + struct BMEditMesh *editData, struct Mesh *mesh, + float (*vertexCos)[3], float (*defMats)[3][3], int numVerts); + +struct Mesh *modifier_applyModifier( + struct ModifierData *md, const struct ModifierEvalContext *ctx, + struct Mesh *mesh); + +struct Mesh *modifier_applyModifierEM( + struct ModifierData *md, const struct ModifierEvalContext *ctx, + struct BMEditMesh *editData, struct Mesh *mesh); + +/* depricated variants of above that accept DerivedMesh */ + +void modifier_deformVerts_DM_deprecated( + struct ModifierData *md, const struct ModifierEvalContext *ctx, + struct DerivedMesh *dm, float (*vertexCos)[3], int numVerts); + +void modifier_deformMatrices_DM_deprecated( + struct ModifierData *md, const struct ModifierEvalContext *ctx, + struct DerivedMesh *dm, + float (*vertexCos)[3], float (*defMats)[3][3], int numVerts); + +void modifier_deformVertsEM_DM_deprecated( + struct ModifierData *md, const struct ModifierEvalContext *ctx, + struct BMEditMesh *editData, struct DerivedMesh *dm, + float (*vertexCos)[3], int numVerts); + +void modifier_deformMatricesEM_DM_deprecated( + struct ModifierData *md, const struct ModifierEvalContext *ctx, + struct BMEditMesh *editData, struct DerivedMesh *dm, + float (*vertexCos)[3], float (*defMats)[3][3], int numVerts); + +struct DerivedMesh *modifier_applyModifier_DM_deprecated( + struct ModifierData *md, const struct ModifierEvalContext *ctx, + struct DerivedMesh *dm); + +struct DerivedMesh *modifier_applyModifierEM_DM_deprecated( + struct ModifierData *md, const struct ModifierEvalContext *ctx, + struct BMEditMesh *editData, struct DerivedMesh *dm); + #endif diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h index 818f79ad8ac..5b5ebbf035c 100644 --- a/source/blender/blenkernel/BKE_movieclip.h +++ b/source/blender/blenkernel/BKE_movieclip.h @@ -32,7 +32,7 @@ * \author Sergey Sharybin */ -struct EvaluationContext; +struct Depsgraph; struct ImBuf; struct Main; struct MovieClip; @@ -85,7 +85,7 @@ bool BKE_movieclip_has_cached_frame(struct MovieClip *clip, struct MovieClipUser bool BKE_movieclip_put_frame_if_possible(struct MovieClip *clip, struct MovieClipUser *user, struct ImBuf *ibuf); /* Evaluaiton. */ -void BKE_movieclip_eval_update(struct EvaluationContext *eval_ctx, struct MovieClip *clip); +void BKE_movieclip_eval_update(struct Depsgraph *depsgraph, struct MovieClip *clip); /* cacheing flags */ #define MOVIECLIP_CACHE_SKIP (1 << 0) diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index 178751d1640..10bc367e909 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -33,6 +33,7 @@ */ enum MultiresModifiedFlags; +struct Depsgraph; struct DerivedMesh; struct MDisps; struct Mesh; @@ -80,18 +81,18 @@ struct DerivedMesh *multires_make_derived_from_derived(struct DerivedMesh *dm, 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(struct Depsgraph *depsgraph, 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_sync_levels_ex( struct Object *ob_dst, struct MultiresModifierData *mmd_src, struct MultiresModifierData *mmd_dst); -int multiresModifier_reshape(struct Scene *scene, struct MultiresModifierData *mmd, +int multiresModifier_reshape(struct Depsgraph *depsgraph, struct Scene *scene, struct MultiresModifierData *mmd, struct Object *dst, struct Object *src); -int multiresModifier_reshapeFromDM(struct Scene *scene, struct MultiresModifierData *mmd, +int multiresModifier_reshapeFromDM(struct Depsgraph *depsgraph, struct Scene *scene, struct MultiresModifierData *mmd, struct Object *ob, struct DerivedMesh *srcdm); -int multiresModifier_reshapeFromDeformMod(struct Scene *scene, struct MultiresModifierData *mmd, +int multiresModifier_reshapeFromDeformMod(struct Depsgraph *depsgraph, struct Scene *scene, struct MultiresModifierData *mmd, struct Object *ob, struct ModifierData *md); void multires_stitch_grids(struct Object *); @@ -109,8 +110,8 @@ 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(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); +void multiresModifier_prepare_join(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct Object *to_ob); int multires_mdisp_corners(struct MDisps *s); diff --git a/source/blender/blenkernel/BKE_navmesh_conversion.h b/source/blender/blenkernel/BKE_navmesh_conversion.h deleted file mode 100644 index 3be363f4d7b..00000000000 --- a/source/blender/blenkernel/BKE_navmesh_conversion.h +++ /dev/null @@ -1,67 +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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -#ifndef __BKE_NAVMESH_CONVERSION_H__ -#define __BKE_NAVMESH_CONVERSION_H__ - -/** \file BKE_navmesh_conversion.h - * \ingroup bke - */ - -struct DerivedMesh; - -/* navmesh_conversion.c */ -int buildNavMeshDataByDerivedMesh(struct DerivedMesh *dm, int *vertsPerPoly, - int *nverts, float **verts, - int *ndtris, unsigned short **dtris, - int *npolys, unsigned short **dmeshes, - unsigned short **polys, int **dtrisToPolysMap, - int **dtrisToTrisMap, int **trisToFacesMap); - -int buildRawVertIndicesData(struct DerivedMesh *dm, int *nverts, float **verts, - int *ntris, unsigned short **tris, int **trisToFacesMap, - int **recastData); - -int buildNavMeshData(const int nverts, const float *verts, - const int ntris, const unsigned short *tris, - const int *recastData, const int *trisToFacesMap, - int *ndtris, unsigned short **dtris, - int *npolys, unsigned short **dmeshes, unsigned short **polys, - int *vertsPerPoly, int **dtrisToPolysMap, int **dtrisToTrisMap); - -int buildPolygonsByDetailedMeshes(const int vertsPerPoly, const int npolys, - unsigned short *polys, const unsigned short *dmeshes, - const float *verts, const unsigned short *dtris, - const int *dtrisToPolysMap); - -int polyNumVerts(const unsigned short *p, const int vertsPerPoly); -int polyIsConvex(const unsigned short *p, const int vertsPerPoly, const float *verts); -int polyFindVertex(const unsigned short *p, const int vertsPerPoly, unsigned short vertexIdx); -float distPointToSegmentSq(const float *point, const float *a, const float *b); - - -#endif /* NAVMESH_CONVERSION_H */ diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index efad8e48e3d..d85f4095eb9 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 @@ -496,7 +498,6 @@ struct bNode *nodeGetActiveTexture(struct bNodeTree *ntree); void nodeUpdate(struct bNodeTree *ntree, struct bNode *node); bool nodeUpdateID(struct bNodeTree *ntree, struct ID *id); void nodeUpdateInternalLinks(struct bNodeTree *ntree, struct bNode *node); -void nodeSynchronizeID(struct bNode *node, bool copy_to_id); int nodeSocketIsHidden(struct bNodeSocket *sock); void ntreeTagUsedSockets(struct bNodeTree *ntree); @@ -690,27 +691,32 @@ 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 * \{ */ -struct ShadeInput; -struct ShadeResult; /* note: types are needed to restore callbacks, don't change values */ /* range 1 - 100 is reserved for common nodes */ /* using toolbox, we add node groups by assuming the values below don't exceed NODE_GROUP_MENU for now */ -#define SH_NODE_OUTPUT 1 +//#define SH_NODE_OUTPUT 1 -#define SH_NODE_MATERIAL 100 +//#define SH_NODE_MATERIAL 100 #define SH_NODE_RGB 101 #define SH_NODE_VALUE 102 #define SH_NODE_MIX_RGB 103 #define SH_NODE_VALTORGB 104 #define SH_NODE_RGBTOBW 105 -#define SH_NODE_TEXTURE 106 +//#define SH_NODE_TEXTURE 106 #define SH_NODE_NORMAL 107 -#define SH_NODE_GEOMETRY 108 +//#define SH_NODE_GEOMETRY 108 #define SH_NODE_MAPPING 109 #define SH_NODE_CURVE_VEC 110 #define SH_NODE_CURVE_RGB 111 @@ -718,7 +724,7 @@ struct ShadeResult; #define SH_NODE_MATH 115 #define SH_NODE_VECT_MATH 116 #define SH_NODE_SQUEEZE 117 -#define SH_NODE_MATERIAL_EXT 118 +//#define SH_NODE_MATERIAL_EXT 118 #define SH_NODE_INVERT 119 #define SH_NODE_SEPRGB 120 #define SH_NODE_COMBRGB 121 @@ -789,6 +795,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 @@ -803,14 +810,10 @@ struct ShadeResult; struct bNodeTreeExec *ntreeShaderBeginExecTree(struct bNodeTree *ntree); void ntreeShaderEndExecTree(struct bNodeTreeExec *exec); -bool ntreeShaderExecTree(struct bNodeTree *ntree, struct ShadeInput *shi, struct ShadeResult *shr); -void ntreeShaderGetTexcoMode(struct bNodeTree *ntree, int osa, short *texco, int *mode); - -/* switch material render loop */ -extern void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *); -void set_node_shader_lamp_loop(void (*lamp_loop_func)(struct ShadeInput *, struct ShadeResult *)); +bool ntreeShaderExecTree(struct bNodeTree *ntree, int thread); void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat, short compatibility); +void ntreeGPUMaterialDomain(struct bNodeTree *ntree, bool *has_surface_output, bool *has_volume_output); /** \} */ @@ -981,7 +984,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, @@ -1040,10 +1043,22 @@ struct bNodeTreeExec *ntreeTexBeginExecTree(struct bNodeTree *ntree); void ntreeTexEndExecTree(struct bNodeTreeExec *exec); int ntreeTexExecTree(struct bNodeTree *ntree, struct TexResult *target, float coord[3], float dxt[3], float dyt[3], int osatex, const short thread, - struct Tex *tex, short which_output, int cfra, int preview, struct ShadeInput *shi, struct MTex *mtex); + struct Tex *tex, short which_output, int cfra, int preview, struct MTex *mtex); /** \} */ void init_nodesystem(void); void free_nodesystem(void); +/* -------------------------------------------------------------------- */ +/* evaluation support, */ + +struct Depsgraph; + +void BKE_nodetree_copy_default_values(struct bNodeTree *ntree_dst, + const struct bNodeTree *ntree_src); + +void BKE_nodetree_shading_params_eval(struct Depsgraph *depsgraph, + 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 7cc43f33e3a..1d28d7f52c7 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -36,33 +36,32 @@ extern "C" { #include "BLI_compiler_attrs.h" struct Base; -struct EvaluationContext; +struct Depsgraph; struct Scene; +struct ViewLayer; struct Object; struct BoundBox; struct View3D; struct SoftBody; -struct BulletSoftBody; struct MovieClip; struct Main; 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(struct Depsgraph *depsgraph, 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); -struct BulletSoftBody *copy_bulletsoftbody(const struct BulletSoftBody *sb, const int flag); struct ParticleSystem *BKE_object_copy_particlesystem(struct ParticleSystem *psys, const int flag); void BKE_object_copy_particlesystems(struct Object *ob_dst, const struct Object *ob_src, const int flag); void BKE_object_copy_softbody(struct Object *ob_dst, const struct Object *ob_src); 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); @@ -81,7 +80,17 @@ void BKE_object_copy_proxy_drivers(struct Object *ob, struct Object *target); bool BKE_object_exists_check(const struct Object *obtest); bool BKE_object_is_in_editmode(const struct Object *ob); bool BKE_object_is_in_editmode_vgroup(const struct Object *ob); +bool BKE_object_is_in_editmode_and_selected(const struct Object *ob); bool BKE_object_is_in_wpaint_select_vert(const struct Object *ob); +bool BKE_object_has_mode_data(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,22 +98,18 @@ 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) ATTR_NONNULL(1); -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); - 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); void BKE_object_make_local(struct Main *bmain, struct Object *ob, const bool lib_local); @@ -124,14 +129,28 @@ void BKE_object_matrix_local_get(struct Object *ob, float mat[4][4]); bool BKE_object_pose_context_check(const struct Object *ob); struct Object *BKE_object_pose_armature_get(struct Object *ob); +struct Object *BKE_object_pose_armature_get_visible(struct Object *ob, struct ViewLayer *view_layer); + +struct Object **BKE_object_pose_array_get_ex(struct ViewLayer *view_layer, unsigned int *r_objects_len, bool unique); +struct Object **BKE_object_pose_array_get_unique(struct ViewLayer *view_layer, unsigned int *r_objects_len); +struct Object **BKE_object_pose_array_get(struct ViewLayer *view_layer, unsigned int *r_objects_len); + +struct Base **BKE_object_pose_base_array_get_ex(struct ViewLayer *view_layer, unsigned int *r_bases_len, bool unique); +struct Base **BKE_object_pose_base_array_get_unique(struct ViewLayer *view_layer, unsigned int *r_bases_len); +struct Base **BKE_object_pose_base_array_get(struct ViewLayer *view_layer, unsigned int *r_bases_len); -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_get_parent_matrix( + struct Scene *scene, struct Object *ob, + struct Object *par, float parentmat[4][4]); +void BKE_object_where_is_calc( + struct Depsgraph *depsgraph, 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); + struct Depsgraph *depsgraph, struct Scene *scene, struct RigidBodyWorld *rbw, + struct Object *ob, float r_originmat[3][3]); +void BKE_object_where_is_calc_time( + struct Depsgraph *depsgraph, 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 Depsgraph *depsgraph, 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]); @@ -149,16 +168,17 @@ void BKE_object_empty_draw_type_set(struct Object *ob, const int value); void BKE_object_boundbox_flag(struct Object *ob, int flag, const bool set); void BKE_object_minmax(struct Object *ob, float r_min[3], float r_max[3], const bool use_hidden); bool BKE_object_minmax_dupli( - struct Scene *scene, struct Object *ob, float r_min[3], float r_max[3], const bool use_hidden); + struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, + float r_min[3], float r_max[3], const bool use_hidden); /* sometimes min-max isn't enough, we need to loop over each point */ 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 Depsgraph *depsgraph, 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); @@ -186,47 +206,61 @@ void BKE_object_tfm_protected_restore( /* Dependency graph evaluation callbacks. */ void BKE_object_eval_local_transform( - struct EvaluationContext *eval_ctx, + struct Depsgraph *depsgraph, struct Object *ob); void BKE_object_eval_parent( - struct EvaluationContext *eval_ctx, + struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); void BKE_object_eval_constraints( - struct EvaluationContext *eval_ctx, + struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); -void BKE_object_eval_done(struct EvaluationContext *eval_ctx, struct Object *ob); +void BKE_object_eval_done(struct Depsgraph *depsgraph, struct Object *ob); bool BKE_object_eval_proxy_copy( - struct EvaluationContext *eval_ctx, + struct Depsgraph *depsgraph, struct Object *object); void BKE_object_eval_uber_transform( - struct EvaluationContext *eval_ctx, + struct Depsgraph *depsgraph, struct Object *ob); void BKE_object_eval_uber_data( - struct EvaluationContext *eval_ctx, + struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); void BKE_object_eval_cloth( - struct EvaluationContext *eval_ctx, + struct Depsgraph *depsgraph, struct Scene *scene, struct Object *object); - void BKE_object_eval_transform_all( - struct EvaluationContext *eval_ctx, + struct Depsgraph *depsgraph, struct Scene *scene, struct Object *object); +void BKE_object_eval_update_shading( + struct Depsgraph *depsgraph, + struct Object *object); +void BKE_object_data_select_update( + struct Depsgraph *depsgraph, + struct ID *object_data); + +void BKE_object_eval_flush_base_flags( + struct Depsgraph *depsgraph, + struct Scene *scene, const int view_layer_index, + struct Object *object, int base_index, + const bool is_from_set); + void BKE_object_handle_data_update( - struct EvaluationContext *eval_ctx, + struct Depsgraph *depsgraph, 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( + struct Depsgraph *depsgraph, + struct Scene *scene, struct Object *ob); void BKE_object_handle_update_ex( - struct EvaluationContext *eval_ctx, + struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct RigidBodyWorld *rbw, const bool do_proxy_update); @@ -273,18 +307,17 @@ typedef enum eObjectSet { } eObjectSet; struct LinkNode *BKE_object_relational_superset( - struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter); + 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); + struct Depsgraph *depsgraph, 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 285b9b3f99f..717f4c4f6e8 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 Depsgraph; enum eOverlayFlags; @@ -91,8 +93,8 @@ 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); +void BKE_paint_invalidate_cursor_overlay(struct Scene *scene, struct ViewLayer *view_layer, struct CurveMapping *curve); void BKE_paint_invalidate_overlay_all(void); eOverlayControlFlags BKE_paint_get_overlay_flags(void); void BKE_paint_reset_overlay_invalid(eOverlayControlFlags flag); @@ -126,7 +128,7 @@ 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); 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); @@ -248,8 +250,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( + struct Depsgraph *depsgraph, 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 0cda7dceb33..0c8d00e16a3 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -49,6 +49,7 @@ struct ParticleSettings; struct Main; struct Object; struct Scene; +struct Depsgraph; struct DerivedMesh; struct ModifierData; struct MTFace; @@ -62,6 +63,8 @@ struct RNG; struct BVHTreeRay; struct BVHTreeRayHit; struct EdgeHash; +struct Depsgraph; +struct ViewLayer; #define PARTICLE_COLLISION_MAX_COLLISIONS 10 @@ -77,6 +80,7 @@ struct EdgeHash; /* common stuff that many particle functions need */ typedef struct ParticleSimulationData { + struct Depsgraph *depsgraph; struct Scene *scene; struct Object *ob; struct ParticleSystem *psys; @@ -144,7 +148,7 @@ typedef struct ParticleThreadContext { float *jit, *jitoff, *weight; float maxweight; - int *index, *skip, jitlevel; + int *index, jitlevel; int cfrom, distr; @@ -286,8 +290,8 @@ BLI_INLINE void psys_frand_vec(ParticleSystem *psys, unsigned int seed, float ve int count_particles(struct ParticleSystem *psys); int count_particles_mod(struct ParticleSystem *psys, int totgr, int cur); -int psys_get_child_number(struct Scene *scene, struct ParticleSystem *psys); -int psys_get_tot_child(struct Scene *scene, struct ParticleSystem *psys); +int psys_get_child_number(struct Scene *scene, struct ParticleSystem *psys, const bool use_render_params); +int psys_get_tot_child(struct Scene *scene, struct ParticleSystem *psys, const bool use_render_params); struct ParticleSystem *psys_get_current(struct Object *ob); /* for rna */ @@ -298,7 +302,7 @@ 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(struct Depsgraph *depsgraph, 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); @@ -310,8 +314,6 @@ void BKE_particlesettings_free(struct ParticleSettings *part); void psys_free_path_cache(struct ParticleSystem *psys, struct PTCacheEdit *edit); void psys_free(struct Object *ob, struct ParticleSystem *psys); -void psys_render_set(struct Object *ob, struct ParticleSystem *psys, float viewmat[4][4], float winmat[4][4], int winx, int winy, int timeoffset); -void psys_render_restore(struct Object *ob, struct ParticleSystem *psys); bool psys_render_simplify_params(struct ParticleSystem *psys, struct ChildParticle *cpa, float *params); void psys_interpolate_uvs(const struct MTFace *tface, int quad, const float w[4], float uvco[2]); @@ -322,7 +324,7 @@ void copy_particle_key(struct ParticleKey *to, struct ParticleKey *from, int tim CustomDataMask psys_emitter_customdata_mask(struct ParticleSystem *psys); void psys_particle_on_emitter(struct ParticleSystemModifierData *psmd, int distr, int index, int index_dmcache, float fuv[4], float foffset, float vec[3], float nor[3], - float utan[3], float vtan[3], float orco[3], float ornor[3]); + float utan[3], float vtan[3], float orco[3]); struct ParticleSystemModifierData *psys_get_modifier(struct Object *ob, struct ParticleSystem *psys); struct ModifierData *object_add_particle_system(struct Scene *scene, struct Object *ob, const char *name); @@ -339,9 +341,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(struct Depsgraph *depsgraph, 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(struct Depsgraph *depsgraph, 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); @@ -354,7 +356,7 @@ void BKE_particlesettings_clump_curve_init(struct ParticleSettings *part); void BKE_particlesettings_rough_curve_init(struct ParticleSettings *part); void BKE_particlesettings_twist_curve_init(struct ParticleSettings *part); void psys_apply_child_modifiers(struct ParticleThreadContext *ctx, struct ListBase *modifiers, - struct ChildParticle *cpa, struct ParticleTexture *ptex, const float orco[3], const float ornor[3], float hairmat[4][4], + struct ChildParticle *cpa, struct ParticleTexture *ptex, const float orco[3], float hairmat[4][4], struct ParticleCacheKey *keys, struct ParticleCacheKey *parent_keys, const float parent_orco[3]); void psys_sph_init(struct ParticleSimulationData *sim, struct SPHData *sphdata); @@ -374,7 +376,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(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, struct ParticleSystem *psys); /* particle_system.c */ struct ParticleSystem *psys_get_target_system(struct Object *ob, struct ParticleTarget *pt); @@ -389,7 +391,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(struct Depsgraph *depsgraph, 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); @@ -420,7 +422,7 @@ float *psys_cache_vgroup(struct DerivedMesh *dm, struct ParticleSystem *psys, in void psys_get_texture(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleTexture *ptex, int event, float cfra); void psys_interpolate_face(struct MVert *mvert, struct MFace *mface, struct MTFace *tface, float (*orcodata)[3], float w[4], float vec[3], float nor[3], float utan[3], float vtan[3], - float orco[3], float ornor[3]); + float orco[3]); float psys_particle_value_from_verts(struct DerivedMesh *dm, short from, struct ParticleData *pa, float *values); void psys_get_from_key(struct ParticleKey *key, float loc[3], float vel[3], float rot[4], float *time); @@ -428,7 +430,7 @@ void psys_get_from_key(struct ParticleKey *key, float loc[3], float vel[3], floa void BKE_psys_collision_neartest_cb(void *userdata, int index, const struct BVHTreeRay *ray, struct BVHTreeRayHit *hit); void psys_particle_on_dm(struct DerivedMesh *dm_final, int from, int index, int index_dmcache, const float fw[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3], - float orco[3], float ornor[3]); + float orco[3]); /* particle_system.c */ void distribute_particles(struct ParticleSimulationData *sim, int from); @@ -438,34 +440,7 @@ int psys_particle_dm_face_lookup(struct DerivedMesh *dm_final, struct DerivedMes void reset_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, float dtime, float cfra); -float psys_get_current_display_percentage(struct ParticleSystem *psys); - -typedef struct ParticleRenderElem { - int curchild, totchild, reduce; - float lambda, t, scalemin, scalemax; -} ParticleRenderElem; - -typedef struct ParticleRenderData { - ChildParticle *child; - ParticleCacheKey **pathcache; - ParticleCacheKey **childcache; - ListBase pathcachebufs, childcachebufs; - int totchild, totcached, totchildcache; - struct DerivedMesh *dm; - int totdmvert, totdmedge, totdmface; - - float mat[4][4]; - float viewmat[4][4], winmat[4][4]; - int winx, winy; - - int do_simplify; - int timeoffset; - ParticleRenderElem *elems; - - /* ORIGINDEX */ - const int *index_mf_to_mpoly; - const int *index_mp_to_orig; -} ParticleRenderData; +float psys_get_current_display_percentage(struct ParticleSystem *psys, const bool use_render_params); /* psys_reset */ #define PSYS_RESET_ALL 1 @@ -479,10 +454,17 @@ typedef struct ParticleRenderData { /* **** Depsgraph evaluation **** */ -struct EvaluationContext; +struct Depsgraph; -void BKE_particle_system_eval_init(struct EvaluationContext *eval_ctx, +void BKE_particle_system_eval_init(struct Depsgraph *depsgraph, 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..c18288de1bc 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; @@ -128,10 +129,9 @@ bool BKE_pbvh_node_find_nearest_to_ray( /* Drawing */ -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 { @@ -221,7 +221,7 @@ struct GSet *BKE_pbvh_bmesh_node_faces(PBVHNode *node); void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node); void BKE_pbvh_bmesh_after_stroke(PBVH *bvh); -/* Update Normals/Bounding Box/Draw Buffers/Redraw and clear flags */ +/* Update Normals/Bounding Box/Redraw and clear flags */ void BKE_pbvh_update(PBVH *bvh, int flags, float (*face_nors)[3]); void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3]); @@ -369,6 +369,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 cc60df1b2d6..89f1aa5eadd 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; @@ -274,6 +277,7 @@ void BKE_ptcache_id_from_smoke(PTCacheID *pid, struct Object *ob, struct SmokeMo void BKE_ptcache_id_from_dynamicpaint(PTCacheID *pid, struct Object *ob, struct DynamicPaintSurface *surface); void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, struct Object *ob, struct RigidBodyWorld *rbw); +PTCacheID BKE_ptcache_id_find(struct Object *ob, struct Scene *scene, struct PointCache *cache); void BKE_ptcache_ids_from_object(struct ListBase *lb, struct Object *ob, struct Scene *scene, int duplis); /***************** Global funcs ****************************/ @@ -317,7 +321,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_property.h b/source/blender/blenkernel/BKE_property.h deleted file mode 100644 index c787e8e8ed1..00000000000 --- a/source/blender/blenkernel/BKE_property.h +++ /dev/null @@ -1,53 +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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#ifndef __BKE_PROPERTY_H__ -#define __BKE_PROPERTY_H__ - -/** \file BKE_property.h - * \ingroup bke - */ - -struct bProperty; -struct ListBase; -struct Object; - -void BKE_bproperty_free(struct bProperty *prop); -void BKE_bproperty_free_list(struct ListBase *lb); -struct bProperty *BKE_bproperty_copy(const struct bProperty *prop); -void BKE_bproperty_copy_list(struct ListBase *lbn, const struct ListBase *lbo); -void BKE_bproperty_init(struct bProperty *prop); -struct bProperty *BKE_bproperty_new(int type); -void BKE_bproperty_unique(struct bProperty *first, struct bProperty *prop, int force); -struct bProperty *BKE_bproperty_object_get(struct Object *ob, const char *name); -void BKE_bproperty_object_set(struct Object *ob, struct bProperty *propc); -// int BKE_bproperty_cmp(struct bProperty *prop, const char *str); -void BKE_bproperty_set(struct bProperty *prop, const char *str); -void BKE_bproperty_add(struct bProperty *prop, const char *str); -/* should really be called '_get_valstr()' or '_as_string()' */ -void BKE_bproperty_set_valstr(struct bProperty *prop, char str[MAX_PROPSTRING]); - -#endif diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h index 3c7274ca3c5..016a531db95 100644 --- a/source/blender/blenkernel/BKE_rigidbody.h +++ b/source/blender/blenkernel/BKE_rigidbody.h @@ -37,6 +37,7 @@ struct RigidBodyWorld; struct RigidBodyOb; +struct Depsgraph; 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(struct Depsgraph *depsgraph, struct Scene *scene, float ctime); +void BKE_rigidbody_do_simulation(struct Depsgraph *depsgraph, struct Scene *scene, float ctime); /* -------------------- */ /* Depsgraph evaluation */ -struct EvaluationContext; - -void BKE_rigidbody_rebuild_sim(struct EvaluationContext *eval_ctx, +void BKE_rigidbody_rebuild_sim(struct Depsgraph *depsgraph, struct Scene *scene); -void BKE_rigidbody_eval_simulation(struct EvaluationContext *eval_ctx, +void BKE_rigidbody_eval_simulation(struct Depsgraph *depsgraph, struct Scene *scene); -void BKE_rigidbody_object_sync_transforms(struct EvaluationContext *eval_ctx, +void BKE_rigidbody_object_sync_transforms(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob); diff --git a/source/blender/blenkernel/BKE_sca.h b/source/blender/blenkernel/BKE_sca.h deleted file mode 100644 index 35bcd91a9b1..00000000000 --- a/source/blender/blenkernel/BKE_sca.h +++ /dev/null @@ -1,92 +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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#ifndef __BKE_SCA_H__ -#define __BKE_SCA_H__ - -/** \file BKE_sca.h - * \ingroup bke - */ - -struct Main; -struct Object; -struct bSensor; -struct bController; -struct bActuator; - -void link_logicbricks(void **poin, void ***ppoin, short *tot, short size); -void unlink_logicbricks(void **poin, void ***ppoin, short *tot); - -void unlink_controller(struct bController *cont); -void unlink_controllers(struct ListBase *lb); -void free_controller(struct bController *cont); -void free_controllers(struct ListBase *lb); - -void unlink_actuator(struct bActuator *act); -void unlink_actuators(struct ListBase *lb); -void free_actuator(struct bActuator *act); -void free_actuators(struct ListBase *lb); - -void free_sensor(struct bSensor *sens); -void free_sensors(struct ListBase *lb); -struct bSensor *copy_sensor(struct bSensor *sens, const int flag); -void copy_sensors(struct ListBase *lbn, const struct ListBase *lbo, const int flag); -void init_sensor(struct bSensor *sens); -struct bSensor *new_sensor(int type); -struct bController *copy_controller(struct bController *cont, const int flag); -void copy_controllers(struct ListBase *lbn, const struct ListBase *lbo, const int flag); -void init_controller(struct bController *cont); -struct bController *new_controller(int type); -struct bActuator *copy_actuator(struct bActuator *act, const int flag); -void copy_actuators(struct ListBase *lbn, const struct ListBase *lbo, const int flag); -void init_actuator(struct bActuator *act); -struct bActuator *new_actuator(int type); -void clear_sca_new_poins_ob(struct Object *ob); -void clear_sca_new_poins(void); -void set_sca_new_poins_ob(struct Object *ob); -void set_sca_new_poins(void); - -void BKE_sca_logic_links_remap(struct Main *bmain, struct Object *ob_old, struct Object *ob_new); -void BKE_sca_logic_copy(struct Object *ob_new, const struct Object *ob, const int flag); - -void sca_move_sensor(struct bSensor *sens_to_move, struct Object *ob, int move_up); -void sca_move_controller(struct bController *cont_to_move, struct Object *ob, int move_up); -void sca_move_actuator(struct bActuator *act_to_move, struct Object *ob, int move_up); - -/* Callback format for performing operations on ID-pointers for sensors/controllers/actuators. */ -typedef void (*SCASensorIDFunc)(struct bSensor *sensor, struct ID **idpoin, void *userdata, int cb_flag); -typedef void (*SCAControllerIDFunc)(struct bController *controller, struct ID **idpoin, void *userdata, int cb_flag); -typedef void (*SCAActuatorIDFunc)(struct bActuator *actuator, struct ID **idpoin, void *userdata, int cb_flag); - -void BKE_sca_sensors_id_loop(struct ListBase *senslist, SCASensorIDFunc func, void *userdata); -void BKE_sca_controllers_id_loop(struct ListBase *contlist, SCAControllerIDFunc func, void *userdata); -void BKE_sca_actuators_id_loop(struct ListBase *atclist, SCAActuatorIDFunc func, void *userdata); - - -const char *sca_state_name_get(Object *ob, short bit); - -#endif - diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h index 0e1472b7062..44aa1b04569 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 EvaluationContext; +struct Depsgraph; struct Main; struct Object; struct RenderData; -struct SceneRenderLayer; struct Scene; +struct SceneCollection; +struct ViewLayer; struct UnitSettings; -struct Main; - -#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 +struct ViewRender; +struct WorkSpace; +struct TransformOrientation; + +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_context_active_PLACEHOLDER(_sce_basis), 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_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, NULL, _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( + struct Depsgraph *depsgraph, 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); @@ -105,7 +120,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 @@ -122,12 +138,12 @@ 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 Depsgraph *depsgraph, + struct Main *bmain); + +void BKE_scene_graph_update_for_newframe(struct Depsgraph *depsgraph, + struct Main *bmain); 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); @@ -135,16 +151,12 @@ bool BKE_scene_remove_render_view(struct Scene *scene, struct SceneRenderView *s /* render profile */ int get_render_subsurf_level(const struct RenderData *r, int level, bool for_render); int get_render_child_particle_number(const struct RenderData *r, int num, bool for_render); -int get_render_shadow_samples(const struct RenderData *r, int samples); -float get_render_aosss_error(const struct RenderData *r, float error); -bool BKE_scene_use_new_shading_nodes(const struct Scene *scene); bool BKE_scene_use_shading_nodes_custom(struct Scene *scene); -bool BKE_scene_use_world_space_shading(struct Scene *scene); 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); +bool BKE_scene_uses_cycles(const struct Scene *scene); void BKE_scene_disable_color_management(struct Scene *scene); bool BKE_scene_check_color_management_enabled(const struct Scene *scene); @@ -155,6 +167,8 @@ int BKE_render_num_threads(const struct RenderData *r); int BKE_render_preview_pixel_size(const struct RenderData *r); +/**********************************/ + double BKE_scene_unit_scale(const struct UnitSettings *unit, const int unit_type, double value); /* multiview */ @@ -174,6 +188,20 @@ 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); + +void BKE_scene_transform_orientation_remove( + struct Scene *scene, struct TransformOrientation *orientation); +struct TransformOrientation *BKE_scene_transform_orientation_find( + const struct Scene *scene, const int index); +int BKE_scene_transform_orientation_get_index( + const struct Scene *scene, const struct TransformOrientation *orientation); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h index 14e978b23f2..36708cb11a4 100644 --- a/source/blender/blenkernel/BKE_screen.h +++ b/source/blender/blenkernel/BKE_screen.h @@ -41,7 +41,9 @@ struct Menu; struct Panel; struct Scene; struct ScrArea; +struct ScrVert; struct SpaceType; +struct TransformOrientation; struct View3D; struct bContext; struct bContextDataResult; @@ -49,10 +51,14 @@ struct bScreen; struct uiLayout; struct uiList; struct wmKeyConfig; +struct wmManipulatorMap; struct wmNotifier; struct wmWindow; struct wmWindowManager; +struct WorkSpace; struct GPUFXSettings; +struct wmMsgBus; +struct ScrAreaMap; #include "BLI_compiler_attrs.h" @@ -71,8 +77,9 @@ typedef struct SpaceType { int spaceid; /* unique space identifier */ int iconid; /* icon lookup for menus */ - /* initial allocation, after this WM will call init() too */ - struct SpaceLink *(*new)(const struct bContext *C); + /* Initial allocation, after this WM will call init() too. Some editors need + * area and scene data (e.g. frame range) to set their initial scrolling. */ + struct SpaceLink *(*new)(const struct ScrArea *, const struct Scene *); /* not free spacelink itself */ void (*free)(struct SpaceLink *); @@ -81,7 +88,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 +105,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 *); @@ -128,9 +140,20 @@ typedef struct ARegionType { void (*exit)(struct wmWindowManager *, struct ARegion *); /* draw entirely, view changes should be handled here */ void (*draw)(const struct bContext *, struct ARegion *); + /* optional, compute button layout before drawing for dynamic size */ + void (*layout)(const struct bContext *, struct ARegion *); + /* snap the size of the region (can be NULL for no snapping). */ + int (*snap_size)(const struct ARegion *ar, int size, int axis); /* 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 */ @@ -178,6 +201,7 @@ typedef struct PanelType { char translation_context[BKE_ST_MAXNAME]; char context[BKE_ST_MAXNAME]; /* for buttons window */ char category[BKE_ST_MAXNAME]; /* for category tabs */ + char owner_id[BKE_ST_MAXNAME]; /* for work-spaces to selectively show. */ int space_type; int region_type; @@ -226,6 +250,7 @@ typedef struct HeaderType { char idname[BKE_ST_MAXNAME]; /* unique name */ int space_type; + int region_type; /* draw entirely, view changes should be handled here */ void (*draw)(const struct bContext *, struct Header *); @@ -248,6 +273,7 @@ typedef struct MenuType { char idname[BKE_ST_MAXNAME]; /* unique name */ char label[BKE_ST_MAXNAME]; /* for button text */ char translation_context[BKE_ST_MAXNAME]; + char owner_id[BKE_ST_MAXNAME]; /* optional, see: #wmOwnerID */ const char *description; /* verify if the menu should draw or not */ @@ -284,6 +310,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 +328,12 @@ 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_gpu_fx_validate(struct GPUFXSettings *fx_settings); +void BKE_screen_view3d_scene_sync(struct bScreen *sc, struct Scene *scene); +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); @@ -312,7 +341,15 @@ float BKE_screen_view3d_zoom_from_fac(float zoomfac); /* screen */ void BKE_screen_free(struct bScreen *sc); +void BKE_screen_area_map_free(struct ScrAreaMap *area_map) ATTR_NONNULL(); unsigned int BKE_screen_visible_layers(struct bScreen *screen, struct Scene *scene); +struct ScrEdge *BKE_screen_find_edge(struct bScreen *sc, struct ScrVert *v1, struct ScrVert *v2); +void BKE_screen_sort_scrvert(struct ScrVert **v1, struct ScrVert **v2); +void BKE_screen_remove_double_scrverts(struct bScreen *sc); +void BKE_screen_remove_double_scredges(struct bScreen *sc); +void BKE_screen_remove_unused_scredges(struct bScreen *sc); +void BKE_screen_remove_unused_scrverts(struct bScreen *sc); + #endif diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h index 3c2cebce3cf..cd173ef33ce 100644 --- a/source/blender/blenkernel/BKE_sequencer.h +++ b/source/blender/blenkernel/BKE_sequencer.h @@ -31,7 +31,7 @@ */ struct bContext; -struct EvaluationContext; +struct Depsgraph; struct StripColorBalance; struct Editing; struct GSet; @@ -40,6 +40,7 @@ struct GPUFX; struct ImBuf; struct Main; struct Mask; +struct RenderEngineType; struct Scene; struct Sequence; struct SequenceModifierData; @@ -92,12 +93,12 @@ void BKE_sequence_iterator_end(SeqIterator *iter); } typedef struct SeqRenderData { - struct EvaluationContext *eval_ctx; struct Main *bmain; struct Scene *scene; int rectx; int recty; int preview_render_size; + int for_render; int motion_blur_samples; float motion_blur_shutter; bool skip_cache; @@ -112,8 +113,9 @@ typedef struct SeqRenderData { } SeqRenderData; void BKE_sequencer_new_render_data( - struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *scene, + struct Main *bmain, struct Scene *scene, int rectx, int recty, int preview_render_size, + int for_render, SeqRenderData *r_context); int BKE_sequencer_cmp_time_startdisp(const void *a, const void *b); @@ -434,10 +436,12 @@ enum { }; typedef struct ImBuf *(*SequencerDrawView)( - struct Scene *scene, struct Object *camera, int width, int height, - unsigned int flag, unsigned int draw_flags, int drawtype, int alpha_mode, + struct Depsgraph *depsgraph, struct Scene *scene, + int drawtype, + struct Object *camera, int width, int height, + unsigned int flag, unsigned int draw_flags, int alpha_mode, int samples, const char *viewname, - struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]); + struct GPUOffScreen *ofs, char err_out[256]); extern SequencerDrawView sequencer_view3d_cb; /* copy/paste */ diff --git a/source/blender/blenkernel/BKE_sketch.h b/source/blender/blenkernel/BKE_sketch.h deleted file mode 100644 index 9b9c125fbe6..00000000000 --- a/source/blender/blenkernel/BKE_sketch.h +++ /dev/null @@ -1,149 +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. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ -#ifndef __BKE_SKETCH_H__ -#define __BKE_SKETCH_H__ - -/** \file BKE_sketch.h - * \ingroup bke - */ - -typedef enum SK_PType { - PT_CONTINUOUS, - PT_EXACT, -} SK_PType; - -typedef enum SK_PMode { - PT_SNAP, - PT_PROJECT, -} SK_PMode; - -typedef struct SK_Point { - float p[3]; - short p2d[2]; - float no[3]; - float size; - SK_PType type; - SK_PMode mode; -} SK_Point; - -typedef struct SK_Stroke { - struct SK_Stroke *next, *prev; - - SK_Point *points; - int nb_points; - int buf_size; - int selected; -} SK_Stroke; - -#define SK_OVERDRAW_LIMIT 5 - -typedef struct SK_Overdraw { - SK_Stroke *target; - int start, end; - int count; -} SK_Overdraw; - -#define SK_Stroke_BUFFER_INIT_SIZE 20 - -typedef struct SK_DrawData { - int mval[2]; - int previous_mval[2]; - SK_PType type; -} SK_DrawData; - -typedef struct SK_Intersection { - struct SK_Intersection *next, *prev; - SK_Stroke *stroke; - int before; - int after; - int gesture_index; - float p[3]; - float lambda; /* used for sorting intersection points */ -} SK_Intersection; - -typedef struct SK_Sketch { - ListBase strokes; - SK_Stroke *active_stroke; - SK_Stroke *gesture; - SK_Point next_point; - SK_Overdraw over; -} SK_Sketch; - - -typedef struct SK_Gesture { - SK_Stroke *stk; - SK_Stroke *segments; - - ListBase intersections; - ListBase self_intersections; - - int nb_self_intersections; - int nb_intersections; - int nb_segments; -} SK_Gesture; - - -/************************************************/ - -void freeSketch(SK_Sketch *sketch); -SK_Sketch *createSketch(void); - -void sk_removeStroke(SK_Sketch *sketch, SK_Stroke *stk); - -void sk_freeStroke(SK_Stroke *stk); -SK_Stroke *sk_createStroke(void); - -SK_Point *sk_lastStrokePoint(SK_Stroke *stk); - -void sk_allocStrokeBuffer(SK_Stroke *stk); -void sk_shrinkStrokeBuffer(SK_Stroke *stk); -void sk_growStrokeBuffer(SK_Stroke *stk); -void sk_growStrokeBufferN(SK_Stroke *stk, int n); - -void sk_replaceStrokePoint(SK_Stroke *stk, SK_Point *pt, int n); -void sk_insertStrokePoint(SK_Stroke *stk, SK_Point *pt, int n); -void sk_appendStrokePoint(SK_Stroke *stk, SK_Point *pt); -void sk_insertStrokePoints(SK_Stroke *stk, SK_Point *pts, int len, int start, int end); - -void sk_trimStroke(SK_Stroke *stk, int start, int end); -void sk_straightenStroke(SK_Stroke *stk, int start, int end, float p_start[3], float p_end[3]); -void sk_polygonizeStroke(SK_Stroke *stk, int start, int end); -void sk_flattenStroke(SK_Stroke *stk, int start, int end); -void sk_reverseStroke(SK_Stroke *stk); - -void sk_filterLastContinuousStroke(SK_Stroke *stk); -void sk_filterStroke(SK_Stroke *stk, int start, int end); - -void sk_initPoint(SK_Point *pt, SK_DrawData *dd, const float no[3]); -void sk_copyPoint(SK_Point *dst, SK_Point *src); - -int sk_stroke_filtermval(SK_DrawData *dd); -void sk_endContinuousStroke(SK_Stroke *stk); - -void sk_updateNextPoint(SK_Sketch *sketch, SK_Stroke *stk); - -void sk_initDrawData(SK_DrawData *dd, const int mval[2]); - -void sk_deleteSelectedStrokes(SK_Sketch *sketch); -void sk_selectAllSketch(SK_Sketch *sketch, int mode); - -#endif diff --git a/source/blender/blenkernel/BKE_smoke.h b/source/blender/blenkernel/BKE_smoke.h index 20366f00df6..82bfe56b0ab 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, struct Depsgraph *depsgraph, + 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..c7bf876a414 100644 --- a/source/blender/blenkernel/BKE_softbody.h +++ b/source/blender/blenkernel/BKE_softbody.h @@ -31,6 +31,7 @@ * \ingroup bke */ +struct Depsgraph; struct Object; struct Scene; struct SoftBody; @@ -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(struct Depsgraph *depsgraph, 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_texture.h b/source/blender/blenkernel/BKE_texture.h index 4e98852c995..ed6aa3f6af9 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -40,7 +40,6 @@ extern "C" { struct bNode; struct Brush; struct ColorBand; -struct EnvMap; struct FreestyleLineStyle; struct ImagePool; struct Lamp; @@ -53,7 +52,6 @@ struct PointDensity; struct Tex; struct TexMapping; struct TexResult; -struct VoxelData; struct World; /* in ColorBand struct */ @@ -76,27 +74,17 @@ struct MTex *BKE_texture_mtex_add_id(struct ID *id, int slot); // void autotexname(struct Tex *tex); struct Tex *give_current_object_texture(struct Object *ob); -struct Tex *give_current_material_texture(struct Material *ma); -struct Tex *give_current_lamp_texture(struct Lamp *la); struct Tex *give_current_linestyle_texture(struct FreestyleLineStyle *linestyle); -struct Tex *give_current_world_texture(struct World *world); struct Tex *give_current_brush_texture(struct Brush *br); struct Tex *give_current_particle_texture(struct ParticleSettings *part); -struct bNode *give_current_material_texture_node(struct Material *ma); - bool give_active_mtex(struct ID *id, struct MTex ***mtex_ar, short *act); void set_active_mtex(struct ID *id, short act); void set_current_brush_texture(struct Brush *br, struct Tex *tex); -void set_current_world_texture(struct World *wo, struct Tex *tex); -void set_current_material_texture(struct Material *ma, struct Tex *tex); -void set_current_lamp_texture(struct Lamp *la, struct Tex *tex); void set_current_linestyle_texture(struct FreestyleLineStyle *linestyle, struct Tex *tex); void set_current_particle_texture(struct ParticleSettings *part, struct Tex *tex); -bool has_current_material_texture(struct Material *ma); - struct TexMapping *BKE_texture_mapping_add(int type); void BKE_texture_mapping_default(struct TexMapping *texmap, int type); void BKE_texture_mapping_init(struct TexMapping *texmap); @@ -104,26 +92,12 @@ void BKE_texture_mapping_init(struct TexMapping *texmap); struct ColorMapping *BKE_texture_colormapping_add(void); void BKE_texture_colormapping_default(struct ColorMapping *colormap); -void BKE_texture_envmap_free_data(struct EnvMap *env); -void BKE_texture_envmap_free(struct EnvMap *env); -struct EnvMap *BKE_texture_envmap_add(void); -struct EnvMap *BKE_texture_envmap_copy(const struct EnvMap *env, const int flag); - void BKE_texture_pointdensity_init_data(struct PointDensity *pd); void BKE_texture_pointdensity_free_data(struct PointDensity *pd); void BKE_texture_pointdensity_free(struct PointDensity *pd); struct PointDensity *BKE_texture_pointdensity_add(void); struct PointDensity *BKE_texture_pointdensity_copy(const struct PointDensity *pd, const int flag); -void BKE_texture_voxeldata_free_data(struct VoxelData *vd); -void BKE_texture_voxeldata_free(struct VoxelData *vd); -struct VoxelData *BKE_texture_voxeldata_add(void); -struct VoxelData *BKE_texture_voxeldata_copy(struct VoxelData *vd); - -void BKE_texture_ocean_free(struct OceanTex *ot); -struct OceanTex *BKE_texture_ocean_add(void); -struct OceanTex *BKE_texture_ocean_copy(const struct OceanTex *ot, const int flag); - bool BKE_texture_dependsOnTime(const struct Tex *texture); bool BKE_texture_is_image_user(const struct Tex *tex); diff --git a/source/blender/blenkernel/BKE_workspace.h b/source/blender/blenkernel/BKE_workspace.h new file mode 100644 index 00000000000..5ee15a08f9b --- /dev/null +++ b/source/blender/blenkernel/BKE_workspace.h @@ -0,0 +1,123 @@ +/* + * ***** 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 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(); + +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 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(); + +/* Update / evaluate */ +void BKE_workspace_update_tagged(struct Main *bmain, + struct WorkSpace *workspace, + struct Scene *scene); + +bool BKE_workspace_owner_id_check( + const struct WorkSpace *workspace, const char *owner_id) ATTR_NONNULL(); + +#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..fe8aa8694af 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 Depsgraph; + +void BKE_world_eval(struct Depsgraph *depsgraph, struct World *world); + +#endif + diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index d789671ab24..fe79f74ef27 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 @@ -81,12 +82,12 @@ set(SRC intern/boids.c intern/bpath.c intern/brush.c - intern/bullet.c intern/bvhutils.c intern/cachefile.c intern/camera.c intern/cdderivedmesh.c intern/cloth.c + intern/collection.c intern/collision.c intern/colorband.c intern/colortools.c @@ -99,13 +100,13 @@ 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/editlattice.c intern/editmesh.c intern/editmesh_bvh.c + intern/editmesh_tangent.c intern/effect.c intern/fcurve.c intern/fluidsim.c @@ -115,6 +116,7 @@ set(SRC intern/gpencil.c intern/group.c intern/icons.c + intern/icons_rasterize.c intern/idcode.c intern/idprop.c intern/image.c @@ -125,6 +127,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 @@ -137,7 +140,9 @@ set(SRC intern/mesh.c intern/mesh_evaluate.c intern/mesh_mapping.c + intern/mesh_merge.c intern/mesh_remap.c + intern/mesh_tangent.c intern/mesh_validate.c intern/modifier.c intern/modifiers_bmesh.c @@ -146,6 +151,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 @@ -160,10 +166,11 @@ set(SRC intern/pbvh.c intern/pbvh_bmesh.c intern/pointcache.c - intern/property.c + intern/layer.c + intern/layer_utils.c + intern/lightprobe.c intern/report.c intern/rigidbody.c - intern/sca.c intern/scene.c intern/screen.c intern/seqcache.c @@ -171,7 +178,6 @@ set(SRC intern/seqmodifier.c intern/sequencer.c intern/shrinkwrap.c - intern/sketch.c intern/smoke.c intern/softbody.c intern/sound.c @@ -190,6 +196,7 @@ set(SRC intern/tracking_util.c intern/undo_system.c intern/unit.c + intern/workspace.c intern/world.c intern/writeavi.c intern/writeframeserver.c @@ -212,13 +219,13 @@ set(SRC BKE_boids.h BKE_bpath.h BKE_brush.h - BKE_bullet.h BKE_bvhutils.h BKE_cachefile.h BKE_camera.h BKE_ccg.h BKE_cdderivedmesh.h BKE_cloth.h + BKE_collection.h BKE_collision.h BKE_colorband.h BKE_colortools.h @@ -230,12 +237,12 @@ set(SRC BKE_customdata_file.h BKE_data_transfer.h BKE_deform.h - BKE_depsgraph.h BKE_displist.h BKE_dynamicpaint.h BKE_editlattice.h BKE_editmesh.h BKE_editmesh_bvh.h + BKE_editmesh_tangent.h BKE_effect.h BKE_fcurve.h BKE_fluidsim.h @@ -254,6 +261,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 @@ -265,12 +273,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 @@ -279,15 +289,14 @@ set(SRC BKE_particle.h BKE_pbvh.h BKE_pointcache.h - BKE_property.h + BKE_layer.h + BKE_lightprobe.h BKE_report.h BKE_rigidbody.h - BKE_sca.h BKE_scene.h BKE_screen.h BKE_sequencer.h BKE_shrinkwrap.h - BKE_sketch.h BKE_smoke.h BKE_softbody.h BKE_sound.h @@ -299,11 +308,11 @@ set(SRC BKE_tracking.h BKE_undo_system.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 particle_private.h @@ -330,7 +339,7 @@ if(WIN32) endif() if(WITH_AUDASPACE) - add_definitions(${AUDASPACE_DEFINITIONS}) + add_definitions(-DWITH_AUDASPACE) list(APPEND INC_SYS ${AUDASPACE_C_INCLUDE_DIRS} @@ -418,6 +427,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() @@ -470,18 +483,6 @@ if(WITH_LZMA) add_definitions(-DWITH_LZMA) endif() -if(WITH_GAMEENGINE) - list(APPEND INC_SYS - ../../../extern/recastnavigation - ) - list(APPEND SRC - intern/navmesh_conversion.c - BKE_navmesh_conversion.h - ) - - add_definitions(-DWITH_GAMEENGINE) -endif() - if(WITH_LIBMV) add_definitions(-DWITH_LIBMV) endif() @@ -534,8 +535,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..c1a4f8dba53 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 @@ -232,6 +232,9 @@ bool ccgSubSurf_prepareGLMesh(CCGSubSurf *ss, CHECK_COMPUTE_TYPE(CUDA) CHECK_COMPUTE_TYPE(GLSL_TRANSFORM_FEEDBACK) CHECK_COMPUTE_TYPE(GLSL_COMPUTE) + default: + compute_type = OPENSUBDIV_EVALUATOR_CPU; + break; #undef CHECK_COMPUTE_TYPE } @@ -739,7 +742,7 @@ static void opensubdiv_evaluateNGonFaceGrids(CCGSubSurf *ss, /* Evaluate edges. */ for (S = 0; S < face->numVerts; S++) { CCGEdge *edge = FACE_getEdges(face)[S]; - int x, S0, S1; + int x, S0 = 0, S1 = 0; bool flip; for (x = 0; x < face->numVerts; ++x) { @@ -995,7 +998,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 15469e3ae4b..dacc0c35e0f 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -55,11 +55,13 @@ #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" @@ -68,19 +70,12 @@ #include "BKE_deform.h" #include "BKE_global.h" /* For debug flag, DM_update_tessface_data() func. */ -#ifdef WITH_GAMEENGINE -#include "BKE_navmesh_conversion.h" -static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm); -#endif - #include "BLI_sys_types.h" /* for intptr_t support */ -#include "GPU_buffers.h" -#include "GPU_glew.h" -#include "GPU_shader.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #ifdef WITH_OPENSUBDIV -# include "BKE_depsgraph.h" # include "DNA_userdef_types.h" #endif @@ -349,7 +344,6 @@ void DM_init( DM_init_funcs(dm); dm->needsFree = 1; - dm->auto_bump_scale = -1.0f; dm->dirty = 0; /* don't use CustomData_reset(...); because we dont want to touch customdata */ @@ -406,7 +400,6 @@ 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 +545,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 +557,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 +589,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 +607,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 +623,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 +653,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,13 +1138,14 @@ DerivedMesh *mesh_create_derived(Mesh *me, float (*vertCos)[3]) } DerivedMesh *mesh_create_derived_for_modifier( - Scene *scene, Object *ob, + struct Depsgraph *depsgraph, Scene *scene, Object *ob, ModifierData *md, int build_shapekey_layers) { Mesh *me = ob->data; const ModifierTypeInfo *mti = modifierType_getInfo(md->type); DerivedMesh *dm; KeyBlock *kb; + ModifierEvalContext mectx = {depsgraph, ob, 0}; md->scene = scene; @@ -1171,9 +1163,12 @@ DerivedMesh *mesh_create_derived_for_modifier( if (mti->type == eModifierTypeType_OnlyDeform) { int numVerts; - float (*deformedVerts)[3] = BKE_mesh_vertexCos_get(me, &numVerts); + /* Always get the vertex coordinates from the original mesh. Otherwise + * there is the risk of deforming already-deformed coordinates. */ + Mesh *mesh_orig_id = (Mesh *)DEG_get_original_id(&me->id); + float (*deformedVerts)[3] = BKE_mesh_vertexCos_get(mesh_orig_id, &numVerts); - modwrap_deformVerts(md, ob, NULL, deformedVerts, numVerts, 0); + modwrap_deformVerts(md, &mectx, NULL, deformedVerts, numVerts); dm = mesh_create_derived(me, deformedVerts); if (build_shapekey_layers) @@ -1187,7 +1182,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, &mectx, tdm); ASSERT_IS_VALID_DM(dm); if (tdm != dm) tdm->release(tdm); @@ -1288,8 +1283,11 @@ static void add_orco_dm( else dm->getVertCos(dm, orco); } - else + else { + /* TODO(sybren): totvert should potentially change here, as ob->data + * or em may have a different number of vertices than dm. */ orco = get_orco_coords_dm(ob, em, layer, &free); + } if (orco) { if (layer == CD_ORCO) @@ -1744,15 +1742,8 @@ static void dm_ensure_display_normals(DerivedMesh *dm) } } -/** - * new value for useDeform -1 (hack for the gameengine): - * - * - apply only the modifier stack of the object, skipping the virtual modifiers, - * - don't apply the key - * - apply deform modifiers and input vertexco - */ static void mesh_calc_modifiers( - Scene *scene, Object *ob, float (*inputVertexCos)[3], + struct Depsgraph *depsgraph, 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, @@ -1761,6 +1752,9 @@ static void mesh_calc_modifiers( DerivedMesh **r_deform, DerivedMesh **r_final) { Mesh *me = ob->data; + /* Always get the vertex coordinates from the original mesh. Otherwise + * there is the risk of deforming already-deformed coordinates. */ + Mesh *mesh_orig_id = (Mesh *)DEG_get_original_id(&me->id); ModifierData *firstmd, *md, *previewmd = NULL; CDMaskLink *datamasks, *curr; /* XXX Always copying POLYINDEX, else tessellated data are no more valid! */ @@ -1770,7 +1764,6 @@ static void mesh_calc_modifiers( int numVerts = me->totvert; const int required_mode = useRenderParams ? eModifierMode_Render : eModifierMode_Realtime; bool isPrevDeform = false; - const bool skipVirtualArmature = (useDeform < 0); MultiresModifierData *mmd = get_multires_modifier(scene, ob, 0); const bool has_multires = (mmd && mmd->sculptlvl != 0); bool multires_applied = false; @@ -1804,17 +1797,13 @@ static void mesh_calc_modifiers( if (useDeform) deform_app_flags |= MOD_APPLY_USECACHE; - if (!skipVirtualArmature) { - firstmd = modifiers_getVirtualModifierList(ob, &virtualModifierData); - } - else { - /* game engine exception */ - firstmd = ob->modifiers.first; - if (firstmd && firstmd->type == eModifierType_Armature) - firstmd = firstmd->next; - } + /* TODO(sybren): do we really need three context objects? Or do we modify + * them on the fly to change the flags where needed? */ + const ModifierEvalContext mectx_deform = {depsgraph, ob, deform_app_flags}; + const ModifierEvalContext mectx_apply = {depsgraph, ob, app_flags}; + const ModifierEvalContext mectx_orco = {depsgraph, ob, (app_flags & ~MOD_APPLY_USECACHE) | MOD_APPLY_ORCO}; - md = firstmd; + md = firstmd = modifiers_getVirtualModifierList(ob, &virtualModifierData); modifiers_clearErrors(ob); @@ -1861,9 +1850,9 @@ static void mesh_calc_modifiers( if (mti->type == eModifierTypeType_OnlyDeform && !sculpt_dyntopo) { if (!deformedVerts) - deformedVerts = BKE_mesh_vertexCos_get(me, &numVerts); + deformedVerts = BKE_mesh_vertexCos_get(mesh_orig_id, &numVerts); - modwrap_deformVerts(md, ob, NULL, deformedVerts, numVerts, deform_app_flags); + modwrap_deformVerts(md, &mectx_deform, NULL, deformedVerts, numVerts); } else { break; @@ -1894,7 +1883,7 @@ static void mesh_calc_modifiers( if (inputVertexCos) deformedVerts = inputVertexCos; else - deformedVerts = BKE_mesh_vertexCos_get(me, &numVerts); + deformedVerts = BKE_mesh_vertexCos_get(mesh_orig_id, &numVerts); } @@ -1991,7 +1980,7 @@ static void mesh_calc_modifiers( dm->getVertCos(dm, deformedVerts); } else { - deformedVerts = BKE_mesh_vertexCos_get(me, &numVerts); + deformedVerts = BKE_mesh_vertexCos_get(mesh_orig_id, &numVerts); } } @@ -2004,7 +1993,7 @@ static void mesh_calc_modifiers( } } - modwrap_deformVerts(md, ob, dm, deformedVerts, numVerts, deform_app_flags); + modwrap_deformVerts(md, &mectx_deform, dm, deformedVerts, numVerts); } else { DerivedMesh *ndm; @@ -2079,7 +2068,7 @@ static void mesh_calc_modifiers( } } - ndm = modwrap_applyModifier(md, ob, dm, app_flags); + ndm = modwrap_applyModifier(md, &mectx_apply, dm); ASSERT_IS_VALID_DM(ndm); if (ndm) { @@ -2106,7 +2095,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, &mectx_orco, orcodm); ASSERT_IS_VALID_DM(ndm); if (ndm) { @@ -2124,7 +2113,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, &mectx_orco, clothorcodm); ASSERT_IS_VALID_DM(ndm); if (ndm) { @@ -2244,20 +2233,6 @@ static void mesh_calc_modifiers( CustomData_free_layers(&finaldm->loopData, CD_NORMAL, finaldm->numLoopData); } -#ifdef WITH_GAMEENGINE - /* NavMesh - this is a hack but saves having a NavMesh modifier */ - if ((ob->gameflag & OB_NAVMESH) && (finaldm->type == DM_TYPE_CDDM)) { - DerivedMesh *tdm; - tdm = navmesh_dm_createNavMeshForVisualization(finaldm); - if (finaldm != tdm) { - finaldm->release(finaldm); - finaldm = tdm; - } - - DM_ensure_tessface(finaldm); - } -#endif /* WITH_GAMEENGINE */ - *r_final = finaldm; if (orcodm) @@ -2307,8 +2282,8 @@ bool editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh * } static void editbmesh_calc_modifiers( - Scene *scene, Object *ob, BMEditMesh *em, - CustomDataMask dataMask, + struct Depsgraph *depsgraph, Scene *scene, Object *ob, + BMEditMesh *em, CustomDataMask dataMask, /* return args */ DerivedMesh **r_cage, DerivedMesh **r_final) { @@ -2332,6 +2307,11 @@ static void editbmesh_calc_modifiers( const bool do_mod_wmcol = do_init_wmcol; VirtualModifierData virtualModifierData; + /* TODO(sybren): do we really need multiple objects, or shall we change the flags where needed? */ + const ModifierEvalContext mectx = {depsgraph, ob, 0}; + const ModifierEvalContext mectx_orco = {depsgraph, ob, MOD_APPLY_ORCO}; + const ModifierEvalContext mectx_cache_gpu = {depsgraph, ob, MOD_APPLY_USECACHE | MOD_APPLY_ALLOW_GPU}; + const bool do_loop_normals = (((Mesh *)(ob->data))->flag & ME_AUTOSMOOTH) != 0; const float loop_normals_split_angle = ((Mesh *)(ob->data))->smoothresh; @@ -2394,10 +2374,10 @@ static void editbmesh_calc_modifiers( } } - if (mti->deformVertsEM) - modwrap_deformVertsEM(md, ob, em, dm, deformedVerts, numVerts); + if (mti->deformVertsEM || mti->deformVertsEM_DM) + modwrap_deformVertsEM(md, &mectx, em, dm, deformedVerts, numVerts); else - modwrap_deformVerts(md, ob, dm, deformedVerts, numVerts, 0); + modwrap_deformVerts(md, &mectx, dm, deformedVerts, numVerts); } else { DerivedMesh *ndm; @@ -2441,11 +2421,11 @@ static void editbmesh_calc_modifiers( mask &= ~CD_MASK_ORCO; DM_set_only_copy(orcodm, mask | CD_MASK_ORIGINDEX); - if (mti->applyModifierEM) { - ndm = modwrap_applyModifierEM(md, ob, em, orcodm, MOD_APPLY_ORCO); + if (mti->applyModifierEM || mti->applyModifierEM_DM) { + ndm = modwrap_applyModifierEM(md, &mectx_orco, em, orcodm); } else { - ndm = modwrap_applyModifier(md, ob, orcodm, MOD_APPLY_ORCO); + ndm = modwrap_applyModifier(md, &mectx_orco, orcodm); } ASSERT_IS_VALID_DM(ndm); @@ -2469,10 +2449,10 @@ static void editbmesh_calc_modifiers( } } - if (mti->applyModifierEM) - ndm = modwrap_applyModifierEM(md, ob, em, dm, MOD_APPLY_USECACHE | MOD_APPLY_ALLOW_GPU); + if (mti->applyModifierEM || mti->applyModifierEM_DM) + ndm = modwrap_applyModifierEM(md, &mectx_cache_gpu, em, dm); else - ndm = modwrap_applyModifier(md, ob, dm, MOD_APPLY_USECACHE | MOD_APPLY_ALLOW_GPU); + ndm = modwrap_applyModifier(md, &mectx_cache_gpu, dm); ASSERT_IS_VALID_DM(ndm); if (ndm) { @@ -2505,6 +2485,11 @@ static void editbmesh_calc_modifiers( *r_cage = dm; } else { + struct Mesh *mesh = ob->data; + if (mesh->id.tag & LIB_TAG_COPY_ON_WRITE) { + BKE_mesh_ensure_edit_data(mesh); + mesh->runtime.edit_data->vertexCos = MEM_dupallocN(deformedVerts); + } *r_cage = getEditDerivedBMesh( em, ob, mask, deformedVerts ? MEM_dupallocN(deformedVerts) : NULL); @@ -2542,6 +2527,13 @@ static void editbmesh_calc_modifiers( } else { /* this is just a copy of the editmesh, no need to calc normals */ + struct Mesh *mesh = ob->data; + if (mesh->id.tag & LIB_TAG_COPY_ON_WRITE) { + BKE_mesh_ensure_edit_data(mesh); + if (mesh->runtime.edit_data->vertexCos != NULL) + MEM_freeN((void *)mesh->runtime.edit_data->vertexCos); + mesh->runtime.edit_data->vertexCos = MEM_dupallocN(deformedVerts); + } *r_final = getEditDerivedBMesh(em, ob, dataMask, deformedVerts); deformedVerts = NULL; @@ -2608,7 +2600,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(Depsgraph *depsgraph, + Scene *scene, Object *ob, bool use_render_params) { @@ -2624,7 +2617,7 @@ static bool calc_modifiers_skip_orco(Scene *scene, else if ((ob->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(depsgraph, &ob->id) & DAG_EVAL_NEED_CPU) != 0) { return false; } SubsurfModifierData *smd = (SubsurfModifierData *)last_md; @@ -2636,7 +2629,7 @@ static bool calc_modifiers_skip_orco(Scene *scene, #endif static void mesh_build_data( - Scene *scene, Object *ob, CustomDataMask dataMask, + struct Depsgraph *depsgraph, Scene *scene, Object *ob, CustomDataMask dataMask, const bool build_shapekey_layers, const bool need_mapping) { BLI_assert(ob->type == OB_MESH); @@ -2645,13 +2638,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(depsgraph, 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, + depsgraph, scene, ob, NULL, false, 1, need_mapping, dataMask, -1, true, build_shapekey_layers, true, &ob->derivedDeform, &ob->derivedFinal); @@ -2666,13 +2659,15 @@ static void mesh_build_data( /* 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(depsgraph, 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( + struct Depsgraph *depsgraph, Scene *scene, + Object *obedit, BMEditMesh *em, CustomDataMask dataMask) { BKE_object_free_derived_caches(obedit); BKE_object_sculpt_modifiers_changed(obedit); @@ -2680,13 +2675,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(depsgraph, scene, obedit, false)) { dataMask &= ~(CD_MASK_ORCO | CD_MASK_PREVIEW_MCOL); } #endif editbmesh_calc_modifiers( - scene, obedit, em, dataMask, + depsgraph, scene, obedit, em, dataMask, &em->derivedCage, &em->derivedFinal); DM_set_object_boundbox(obedit, em->derivedFinal); @@ -2698,9 +2693,10 @@ 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 Depsgraph *depsgraph, Object *ob, bool *r_need_mapping) { - Object *actob = scene->basact ? scene->basact->object : NULL; + ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); + Object *actob = view_layer->basact ? view_layer->basact->object : NULL; CustomDataMask mask = ob->customdata_mask; if (r_need_mapping) { @@ -2737,85 +2733,86 @@ static CustomDataMask object_get_datamask(const Scene *scene, Object *ob, bool * } void makeDerivedMesh( - Scene *scene, Object *ob, BMEditMesh *em, + struct Depsgraph *depsgraph, 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(depsgraph, ob, &need_mapping); if (em) { - editbmesh_build_data(scene, ob, em, dataMask); + editbmesh_build_data(depsgraph, scene, ob, em, dataMask); } else { - mesh_build_data(scene, ob, dataMask, build_shapekey_layers, need_mapping); + mesh_build_data(depsgraph, scene, ob, dataMask, build_shapekey_layers, need_mapping); } } /***/ -DerivedMesh *mesh_get_derived_final(Scene *scene, Object *ob, CustomDataMask dataMask) +DerivedMesh *mesh_get_derived_final( + struct Depsgraph *depsgraph, 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(depsgraph, 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(depsgraph, 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(struct Depsgraph *depsgraph, 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(depsgraph, 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(depsgraph, 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(struct Depsgraph *depsgraph, Scene *scene, Object *ob, CustomDataMask dataMask) { DerivedMesh *final; mesh_calc_modifiers( - scene, ob, NULL, true, 1, false, dataMask, -1, false, false, false, + depsgraph, 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(struct Depsgraph *depsgraph, Scene *scene, Object *ob, CustomDataMask dataMask, int index) { DerivedMesh *final; mesh_calc_modifiers( - scene, ob, NULL, true, 1, false, dataMask, index, false, false, false, + depsgraph, 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) + struct Depsgraph *depsgraph, Scene *scene, + Object *ob, CustomDataMask dataMask) { DerivedMesh *final; @@ -2826,7 +2823,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, + depsgraph, scene, ob, NULL, false, 1, false, dataMask, -1, false, false, false, NULL, &final); ob->transflag &= ~OB_NO_PSYS_UPDATE; @@ -2835,53 +2832,27 @@ DerivedMesh *mesh_create_derived_view( } DerivedMesh *mesh_create_derived_no_deform( - Scene *scene, Object *ob, float (*vertCos)[3], - CustomDataMask dataMask) + struct Depsgraph *depsgraph, 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, - NULL, &final); - - return final; -} - -DerivedMesh *mesh_create_derived_no_virtual( - 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, - NULL, &final); - - return final; -} - -DerivedMesh *mesh_create_derived_physics( - 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, + depsgraph, scene, ob, vertCos, false, 0, false, dataMask, -1, false, false, false, NULL, &final); return final; } DerivedMesh *mesh_create_derived_no_deform_render( - Scene *scene, Object *ob, - float (*vertCos)[3], + struct Depsgraph *depsgraph, 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, + depsgraph, scene, ob, vertCos, true, 0, false, dataMask, -1, false, false, false, NULL, &final); return final; @@ -2890,7 +2861,7 @@ DerivedMesh *mesh_create_derived_no_deform_render( /***/ DerivedMesh *editbmesh_get_derived_cage_and_final( - Scene *scene, Object *obedit, BMEditMesh *em, + struct Depsgraph *depsgraph, Scene *scene, Object *obedit, BMEditMesh *em, CustomDataMask dataMask, /* return args */ DerivedMesh **r_final) @@ -2898,12 +2869,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(depsgraph, obedit, NULL); if (!em->derivedCage || (em->lastDataMask & dataMask) != dataMask) { - editbmesh_build_data(scene, obedit, em, dataMask); + editbmesh_build_data(depsgraph, scene, obedit, em, dataMask); } *r_final = em->derivedFinal; @@ -2911,17 +2882,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( + struct Depsgraph *depsgraph, 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(depsgraph, obedit, NULL); if (!em->derivedCage || (em->lastDataMask & dataMask) != dataMask) { - editbmesh_build_data(scene, obedit, em, dataMask); + editbmesh_build_data(depsgraph, scene, obedit, em, dataMask); } return em->derivedCage; @@ -3056,271 +3029,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) -{ - int count = 0; - for (int b = 0; b < gattribs->totlayer; b++) { - if (gattribs->layer[b].type == CD_TANGENT) { - strcpy(tangent_names[count++], gattribs->layer[b].name); - } - } - *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,602 +3042,24 @@ 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 */ - } -} - -/** \} */ - - -void DM_calc_auto_bump_scale(DerivedMesh *dm) + const char (*tangent_names)[MAX_NAME], int tangent_names_len) { - /* int totvert = dm->getNumVerts(dm); */ /* UNUSED */ - int totface = dm->getNumTessFaces(dm); - - MVert *mvert = dm->getVertArray(dm); - MFace *mface = dm->getTessFaceArray(dm); - MTFace *mtface = dm->getTessFaceDataArray(dm, CD_MTFACE); - - if (mtface) { - double dsum = 0.0; - int nr_accumulated = 0; - int f; - - for (f = 0; f < totface; f++) { - { - float *verts[4], *tex_coords[4]; - const int nr_verts = mface[f].v4 != 0 ? 4 : 3; - bool is_degenerate; - int i; - - verts[0] = mvert[mface[f].v1].co; verts[1] = mvert[mface[f].v2].co; verts[2] = mvert[mface[f].v3].co; - tex_coords[0] = mtface[f].uv[0]; tex_coords[1] = mtface[f].uv[1]; tex_coords[2] = mtface[f].uv[2]; - if (nr_verts == 4) { - verts[3] = mvert[mface[f].v4].co; - tex_coords[3] = mtface[f].uv[3]; - } - - /* discard degenerate faces */ - is_degenerate = 0; - if (equals_v3v3(verts[0], verts[1]) || - equals_v3v3(verts[0], verts[2]) || - equals_v3v3(verts[1], verts[2]) || - equals_v2v2(tex_coords[0], tex_coords[1]) || - equals_v2v2(tex_coords[0], tex_coords[2]) || - equals_v2v2(tex_coords[1], tex_coords[2])) - { - is_degenerate = 1; - } - - /* verify last vertex as well if this is a quad */ - if (is_degenerate == 0 && nr_verts == 4) { - if (equals_v3v3(verts[3], verts[0]) || - equals_v3v3(verts[3], verts[1]) || - equals_v3v3(verts[3], verts[2]) || - equals_v2v2(tex_coords[3], tex_coords[0]) || - equals_v2v2(tex_coords[3], tex_coords[1]) || - equals_v2v2(tex_coords[3], tex_coords[2])) - { - is_degenerate = 1; - } - - /* verify the winding is consistent */ - if (is_degenerate == 0) { - float prev_edge[2]; - bool is_signed = 0; - sub_v2_v2v2(prev_edge, tex_coords[0], tex_coords[3]); - - i = 0; - while (is_degenerate == 0 && i < 4) { - float cur_edge[2], signed_area; - sub_v2_v2v2(cur_edge, tex_coords[(i + 1) & 0x3], tex_coords[i]); - signed_area = cross_v2v2(prev_edge, cur_edge); - - if (i == 0) { - is_signed = (signed_area < 0.0f) ? 1 : 0; - } - else if ((is_signed != 0) != (signed_area < 0.0f)) { - is_degenerate = 1; - } - - if (is_degenerate == 0) { - copy_v2_v2(prev_edge, cur_edge); - i++; - } - } - } - } - - /* proceed if not a degenerate face */ - if (is_degenerate == 0) { - int nr_tris_to_pile = 0; - /* quads split at shortest diagonal */ - int offs = 0; /* initial triangulation is 0,1,2 and 0, 2, 3 */ - if (nr_verts == 4) { - float pos_len_diag0, pos_len_diag1; - - pos_len_diag0 = len_squared_v3v3(verts[2], verts[0]); - pos_len_diag1 = len_squared_v3v3(verts[3], verts[1]); - - if (pos_len_diag1 < pos_len_diag0) { - offs = 1; // alter split - } - else if (pos_len_diag0 == pos_len_diag1) { /* do UV check instead */ - float tex_len_diag0, tex_len_diag1; - - tex_len_diag0 = len_squared_v2v2(tex_coords[2], tex_coords[0]); - tex_len_diag1 = len_squared_v2v2(tex_coords[3], tex_coords[1]); - - if (tex_len_diag1 < tex_len_diag0) { - offs = 1; /* alter split */ - } - } - } - nr_tris_to_pile = nr_verts - 2; - if (nr_tris_to_pile == 1 || nr_tris_to_pile == 2) { - const int indices[6] = {offs + 0, offs + 1, offs + 2, offs + 0, offs + 2, (offs + 3) & 0x3 }; - int t; - for (t = 0; t < nr_tris_to_pile; t++) { - float f2x_area_uv; - const float *p0 = verts[indices[t * 3 + 0]]; - const float *p1 = verts[indices[t * 3 + 1]]; - const float *p2 = verts[indices[t * 3 + 2]]; - - float edge_t0[2], edge_t1[2]; - sub_v2_v2v2(edge_t0, tex_coords[indices[t * 3 + 1]], tex_coords[indices[t * 3 + 0]]); - sub_v2_v2v2(edge_t1, tex_coords[indices[t * 3 + 2]], tex_coords[indices[t * 3 + 0]]); - - f2x_area_uv = fabsf(cross_v2v2(edge_t0, edge_t1)); - if (f2x_area_uv > FLT_EPSILON) { - float norm[3], v0[3], v1[3], f2x_surf_area, fsurf_ratio; - sub_v3_v3v3(v0, p1, p0); - sub_v3_v3v3(v1, p2, p0); - cross_v3_v3v3(norm, v0, v1); - - f2x_surf_area = len_v3(norm); - fsurf_ratio = f2x_surf_area / f2x_area_uv; /* tri area divided by texture area */ - - nr_accumulated++; - dsum += (double)(fsurf_ratio); - } - } - } - } - } - } - - /* finalize */ - { - const float avg_area_ratio = (nr_accumulated > 0) ? ((float)(dsum / nr_accumulated)) : 1.0f; - const float use_as_render_bump_scale = sqrtf(avg_area_ratio); // use width of average surface ratio as your bump scale - dm->auto_bump_scale = use_as_render_bump_scale; - } - } - else { - dm->auto_bump_scale = 1.0f; - } -} - -void DM_vertex_attributes_from_gpu(DerivedMesh *dm, GPUVertexAttribs *gattribs, DMVertexAttribs *attribs) -{ - CustomData *vdata, *ldata; - int a, b, layer; - const bool is_editmesh = (dm->type == DM_TYPE_EDITBMESH); - - /* From the layers requested by the GLSL shader, figure out which ones are - * actually available for this derivedmesh, and retrieve the pointers */ - - memset(attribs, 0, sizeof(DMVertexAttribs)); - - vdata = &dm->vertData; - ldata = dm->getLoopDataLayout(dm); - - /* calc auto bump scale if necessary */ - if (dm->auto_bump_scale <= 0.0f) - DM_calc_auto_bump_scale(dm); - - char tangent_names[MAX_MTFACE][MAX_NAME]; - int tangent_names_count; - /* Add a tangent layer/layers. */ - DM_calc_tangents_names_from_gpu(gattribs, tangent_names, &tangent_names_count); - - if (tangent_names_count) - dm->calcLoopTangents(dm, false, (const char (*)[MAX_NAME])tangent_names, tangent_names_count); - - for (b = 0; b < gattribs->totlayer; b++) { - int type = gattribs->layer[b].type; - layer = -1; - if (type == CD_AUTO_FROM_NAME) { - /* We need to deduct what exact layer is used. - * - * We do it based on the specified name. - */ - if (gattribs->layer[b].name[0]) { - layer = CustomData_get_named_layer_index(ldata, CD_MLOOPUV, gattribs->layer[b].name); - type = CD_MTFACE; - if (layer == -1) { - layer = CustomData_get_named_layer_index(ldata, CD_MLOOPCOL, gattribs->layer[b].name); - type = CD_MCOL; - } - if (layer == -1) { - layer = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, gattribs->layer[b].name); - type = CD_TANGENT; - } - if (layer == -1) { - continue; - } - } - else { - /* Fall back to the UV layer, which matches old behavior. */ - type = CD_MTFACE; - } - } - if (type == CD_MTFACE) { - /* uv coordinates */ - if (layer == -1) { - if (gattribs->layer[b].name[0]) - layer = CustomData_get_named_layer_index(ldata, CD_MLOOPUV, gattribs->layer[b].name); - else - layer = CustomData_get_active_layer_index(ldata, CD_MLOOPUV); - } - - a = attribs->tottface++; - - if (layer != -1) { - attribs->tface[a].array = is_editmesh ? NULL : ldata->layers[layer].data; - attribs->tface[a].em_offset = ldata->layers[layer].offset; - } - else { - attribs->tface[a].array = NULL; - attribs->tface[a].em_offset = -1; - } - - attribs->tface[a].gl_index = gattribs->layer[b].glindex; - attribs->tface[a].gl_info_index = gattribs->layer[b].glinfoindoex; - attribs->tface[a].gl_texco = gattribs->layer[b].gltexco; - } - else if (type == CD_MCOL) { - if (layer == -1) { - if (gattribs->layer[b].name[0]) - layer = CustomData_get_named_layer_index(ldata, CD_MLOOPCOL, gattribs->layer[b].name); - else - layer = CustomData_get_active_layer_index(ldata, CD_MLOOPCOL); - } - - a = attribs->totmcol++; - - if (layer != -1) { - attribs->mcol[a].array = is_editmesh ? NULL : ldata->layers[layer].data; - /* odd, store the offset for a different layer type here, but editmode draw code expects it */ - attribs->mcol[a].em_offset = ldata->layers[layer].offset; - } - else { - attribs->mcol[a].array = NULL; - attribs->mcol[a].em_offset = -1; - } - - attribs->mcol[a].gl_index = gattribs->layer[b].glindex; - attribs->mcol[a].gl_info_index = gattribs->layer[b].glinfoindoex; - } - else if (type == CD_TANGENT) { - /* note, even with 'is_editmesh' this uses the derived-meshes loop data */ - if (layer == -1) { - if (gattribs->layer[b].name[0]) - layer = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, gattribs->layer[b].name); - else - layer = CustomData_get_active_layer_index(&dm->loopData, CD_TANGENT); - } - - a = attribs->tottang++; - - if (layer != -1) { - attribs->tang[a].array = dm->loopData.layers[layer].data; - attribs->tang[a].em_offset = dm->loopData.layers[layer].offset; - } - else { - attribs->tang[a].array = NULL; - attribs->tang[a].em_offset = -1; - } - - attribs->tang[a].gl_index = gattribs->layer[b].glindex; - attribs->tang[a].gl_info_index = gattribs->layer[b].glinfoindoex; - } - else if (type == CD_ORCO) { - /* original coordinates */ - if (layer == -1) { - layer = CustomData_get_layer_index(vdata, CD_ORCO); - } - attribs->totorco = 1; - - if (layer != -1) { - attribs->orco.array = vdata->layers[layer].data; - attribs->orco.em_offset = vdata->layers[layer].offset; - } - else { - attribs->orco.array = NULL; - attribs->orco.em_offset = -1; - } - - attribs->orco.gl_index = gattribs->layer[b].glindex; - attribs->orco.gl_texco = gattribs->layer[b].gltexco; - attribs->orco.gl_info_index = gattribs->layer[b].glinfoindoex; - } - } -} - -/** - * Set vertex shader attribute inputs for a particular tessface vert - * - * \param a: tessface index - * \param index: vertex index - * \param vert: corner index (0, 1, 2, 3) - * \param loop: absolute loop corner index - */ -void DM_draw_attrib_vertex(DMVertexAttribs *attribs, int a, int index, int vert, int loop) -{ - const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - int b; - - UNUSED_VARS(a, vert); - - /* orco texture coordinates */ - if (attribs->totorco) { - /*const*/ float (*array)[3] = attribs->orco.array; - const float *orco = (array) ? array[index] : zero; - - if (attribs->orco.gl_texco) - glTexCoord3fv(orco); - else - glVertexAttrib3fv(attribs->orco.gl_index, orco); - } - - /* uv texture coordinates */ - for (b = 0; b < attribs->tottface; b++) { - const float *uv; - - if (attribs->tface[b].array) { - const MLoopUV *mloopuv = &attribs->tface[b].array[loop]; - uv = mloopuv->uv; - } - else { - uv = zero; - } - - if (attribs->tface[b].gl_texco) - glTexCoord2fv(uv); - else - glVertexAttrib2fv(attribs->tface[b].gl_index, uv); - } - - /* vertex colors */ - for (b = 0; b < attribs->totmcol; b++) { - GLfloat col[4]; - - if (attribs->mcol[b].array) { - const MLoopCol *cp = &attribs->mcol[b].array[loop]; - rgba_uchar_to_float(col, &cp->r); - } - else { - zero_v4(col); - } - - glVertexAttrib4fv(attribs->mcol[b].gl_index, col); - } - - /* tangent for normal mapping */ - for (b = 0; b < attribs->tottang; b++) { - if (attribs->tang[b].array) { - /*const*/ float (*array)[4] = attribs->tang[b].array; - const float *tang = (array) ? array[loop] : zero; - glVertexAttrib4fv(attribs->tang[b].gl_index, tang); - } - } -} - -void DM_draw_attrib_vertex_uniforms(const DMVertexAttribs *attribs) -{ - int i; - if (attribs->totorco) { - if (attribs->orco.gl_info_index != -1) { - glUniform1i(attribs->orco.gl_info_index, 0); - } - } - for (i = 0; i < attribs->tottface; i++) { - if (attribs->tface[i].gl_info_index != -1) { - glUniform1i(attribs->tface[i].gl_info_index, 0); - } - } - for (i = 0; i < attribs->totmcol; i++) { - if (attribs->mcol[i].gl_info_index != -1) { - glUniform1i(attribs->mcol[i].gl_info_index, GPU_ATTR_INFO_SRGB); - } - } - - for (i = 0; i < attribs->tottang; i++) { - if (attribs->tang[i].gl_info_index != -1) { - glUniform1i(attribs->tang[i].gl_info_index, 0); - } - } + 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); } /* Set object's bounding box based on DerivedMesh min/max data */ @@ -3948,181 +3078,6 @@ void DM_set_object_boundbox(Object *ob, DerivedMesh *dm) ob->bb->flag &= ~BOUNDBOX_DIRTY; } -/* --- NAVMESH (begin) --- */ -#ifdef WITH_GAMEENGINE - -/* BMESH_TODO, navmesh is not working right currently - * All tools set this as MPoly data, but derived mesh currently draws from MFace (tessface) - * - * Proposed solution, rather then copy CD_RECAST into the MFace array, - * use ORIGINDEX to get the original poly index and then get the CD_RECAST - * data from the original me->mpoly layer. - campbell - */ - - -BLI_INLINE int navmesh_bit(int a, int b) -{ - return (a & (1 << b)) >> b; -} - -BLI_INLINE void navmesh_intToCol(int i, float col[3]) -{ - int r = navmesh_bit(i, 0) + navmesh_bit(i, 3) * 2 + 1; - int g = navmesh_bit(i, 1) + navmesh_bit(i, 4) * 2 + 1; - int b = navmesh_bit(i, 2) + navmesh_bit(i, 5) * 2 + 1; - col[0] = 1 - r * 63.0f / 255.0f; - col[1] = 1 - g * 63.0f / 255.0f; - col[2] = 1 - b * 63.0f / 255.0f; -} - -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); - float col[3]; - - if (!polygonIdx) - return; - -#if 0 - //UI_ThemeColor(TH_WIRE); - glLineWidth(2.0); - 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); - } - - 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); - } - } - glEnd(); - } -} - -static void navmesh_DM_drawFacesTex( - DerivedMesh *dm, - DMSetDrawOptionsTex UNUSED(setDrawOptions), - DMCompareDrawOptions UNUSED(compareDrawOptions), - void *UNUSED(userData), DMDrawFlag UNUSED(flag)) -{ - navmesh_drawColored(dm); -} - -static void navmesh_DM_drawFacesSolid( - DerivedMesh *dm, - float (*partial_redraw_planes)[4], - bool UNUSED(fast), DMSetMaterial UNUSED(setMaterial)) -{ - UNUSED_VARS(partial_redraw_planes); - - //drawFacesSolid_original(dm, partial_redraw_planes, fast, setMaterial); - navmesh_drawColored(dm); -} - -static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm) -{ - DerivedMesh *result; - int maxFaces = dm->getNumPolys(dm); - int *recastData; - int vertsPerPoly = 0, nverts = 0, ndtris = 0, npolys = 0; - float *verts = NULL; - unsigned short *dtris = NULL, *dmeshes = NULL, *polys = NULL; - int *dtrisToPolysMap = NULL, *dtrisToTrisMap = NULL, *trisToFacesMap = NULL; - int res; - - result = CDDM_copy(dm); - if (!CustomData_has_layer(&result->polyData, CD_RECAST)) { - int *sourceRecastData = (int *)CustomData_get_layer(&dm->polyData, CD_RECAST); - if (sourceRecastData) { - CustomData_add_layer_named(&result->polyData, CD_RECAST, CD_DUPLICATE, - sourceRecastData, maxFaces, "recastData"); - } - } - 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; - - - /* process mesh */ - res = buildNavMeshDataByDerivedMesh(dm, &vertsPerPoly, &nverts, &verts, &ndtris, &dtris, - &npolys, &dmeshes, &polys, &dtrisToPolysMap, &dtrisToTrisMap, - &trisToFacesMap); - if (res) { - size_t polyIdx; - - /* invalidate concave polygon */ - for (polyIdx = 0; polyIdx < (size_t)npolys; polyIdx++) { - unsigned short *poly = &polys[polyIdx * 2 * vertsPerPoly]; - if (!polyIsConvex(poly, vertsPerPoly, verts)) { - /* set negative polygon idx to all faces */ - unsigned short *dmesh = &dmeshes[4 * polyIdx]; - unsigned short tbase = dmesh[2]; - unsigned short tnum = dmesh[3]; - unsigned short ti; - - for (ti = 0; ti < tnum; ti++) { - unsigned short triidx = dtrisToTrisMap[tbase + ti]; - unsigned short faceidx = trisToFacesMap[triidx]; - if (recastData[faceidx] > 0) { - recastData[faceidx] = -recastData[faceidx]; - } - } - } - } - } - else { - printf("Navmesh: Unable to generate valid Navmesh"); - } - - /* clean up */ - if (verts != NULL) - MEM_freeN(verts); - if (dtris != NULL) - MEM_freeN(dtris); - if (dmeshes != NULL) - MEM_freeN(dmeshes); - if (polys != NULL) - MEM_freeN(polys); - if (dtrisToPolysMap != NULL) - MEM_freeN(dtrisToPolysMap); - if (dtrisToTrisMap != NULL) - MEM_freeN(dtrisToTrisMap); - if (trisToFacesMap != NULL) - MEM_freeN(trisToFacesMap); - - return result; -} - -#endif /* WITH_GAMEENGINE */ - -/* --- NAVMESH (end) --- */ - - void DM_init_origspace(DerivedMesh *dm) { const float default_osf[4][2] = {{0, 0}, {1, 0}, {1, 1}, {0, 1}}; diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index c06a1a8106c..7cceec2c08f 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) @@ -849,39 +855,6 @@ void BKE_pose_free(bPose *pose) BKE_pose_free_ex(pose, true); } -static void copy_pose_channel_data(bPoseChannel *pchan, const bPoseChannel *chan) -{ - bConstraint *pcon, *con; - - copy_v3_v3(pchan->loc, chan->loc); - copy_v3_v3(pchan->size, chan->size); - copy_v3_v3(pchan->eul, chan->eul); - copy_v3_v3(pchan->rotAxis, chan->rotAxis); - pchan->rotAngle = chan->rotAngle; - copy_qt_qt(pchan->quat, chan->quat); - pchan->rotmode = chan->rotmode; - copy_m4_m4(pchan->chan_mat, (float(*)[4])chan->chan_mat); - copy_m4_m4(pchan->pose_mat, (float(*)[4])chan->pose_mat); - pchan->flag = chan->flag; - - pchan->roll1 = chan->roll1; - pchan->roll2 = chan->roll2; - pchan->curveInX = chan->curveInX; - pchan->curveInY = chan->curveInY; - pchan->curveOutX = chan->curveOutX; - pchan->curveOutY = chan->curveOutY; - pchan->ease1 = chan->ease1; - pchan->ease2 = chan->ease2; - pchan->scaleIn = chan->scaleIn; - pchan->scaleOut = chan->scaleOut; - - con = chan->constraints.first; - for (pcon = pchan->constraints.first; pcon && con; pcon = pcon->next, con = con->next) { - pcon->enforce = con->enforce; - pcon->headtail = con->headtail; - } -} - /** * Copy the internal members of each pose channel including constraints * and ID-Props, used when duplicating bones in editmode. @@ -1323,25 +1296,6 @@ short action_get_item_transforms(bAction *act, Object *ob, bPoseChannel *pchan, /* ************** Pose Management Tools ****************** */ -/* Copy the data from the action-pose (src) into the pose */ -/* both args are assumed to be valid */ -/* exported to game engine */ -/* Note! this assumes both poses are aligned, this isn't always true when dealing with user poses */ -void extract_pose_from_pose(bPose *pose, const bPose *src) -{ - const bPoseChannel *schan; - bPoseChannel *pchan = pose->chanbase.first; - - if (pose == src) { - printf("extract_pose_from_pose source and target are the same\n"); - return; - } - - for (schan = src->chanbase.first; (schan && pchan); schan = schan->next, pchan = pchan->next) { - copy_pose_channel_data(pchan, schan); - } -} - /* for do_all_pose_actions, clears the pose. Now also exported for proxy and tools */ void BKE_pose_rest(bPose *pose) { @@ -1428,7 +1382,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..1541d39938d 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,21 @@ 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, + 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(depsgraph, bmain); } /* ........ */ @@ -404,7 +340,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(Depsgraph *depsgraph, Main *bmain, Scene *scene, ListBase *targets) { MPathTarget *mpt; int sfra, efra; @@ -428,14 +364,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, depsgraph); /* perform baking for targets */ motionpaths_calc_bake_targets(scene, targets); @@ -443,7 +375,7 @@ void animviz_calc_motionpaths(Scene *scene, ListBase *targets) /* reset original environment */ CFRA = cfra; - motionpaths_calc_update_scene(scene); + motionpaths_calc_update_scene(bmain, 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 e2c371348e5..4eeabd7a4da 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,14 +69,15 @@ #include "BKE_report.h" #include "BKE_texture.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + #include "RNA_access.h" #include "nla_private.h" #include "atomic_ops.h" -#include "DEG_depsgraph.h" - /* ***************************************** */ /* AnimData API */ @@ -97,6 +97,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: @@ -263,7 +264,7 @@ void BKE_animdata_free(ID *id, const bool do_id_user) /* Copying -------------------------------------------- */ /* Make a copy of the given AnimData - to be used when copying datablocks */ -AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const bool do_action) +AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const bool do_action, const bool do_id_user) { AnimData *dadt; @@ -278,7 +279,7 @@ AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const bool do_action) BKE_id_copy_ex(bmain, (ID *)dadt->action, (ID **)&dadt->action, 0, false); BKE_id_copy_ex(bmain, (ID *)dadt->tmpact, (ID **)&dadt->tmpact, 0, false); } - else { + else if (do_id_user) { id_us_plus((ID *)dadt->action); id_us_plus((ID *)dadt->tmpact); } @@ -296,19 +297,19 @@ AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const bool do_action) return dadt; } -bool BKE_animdata_copy_id(Main *bmain, ID *id_to, ID *id_from, const bool do_action) +bool BKE_animdata_copy_id(Main *bmain, ID *id_to, ID *id_from, const bool do_action, const bool do_id_user) { AnimData *adt; if ((id_to && id_from) && (GS(id_to->name) != GS(id_from->name))) return false; - BKE_animdata_free(id_to, true); + BKE_animdata_free(id_to, do_id_user); adt = BKE_animdata_from_id(id_from); if (adt) { IdAdtTemplate *iat = (IdAdtTemplate *)id_to; - iat->adt = BKE_animdata_copy(bmain, adt, do_action); + iat->adt = BKE_animdata_copy(bmain, adt, do_action, do_id_user); } return true; @@ -601,36 +602,8 @@ char *BKE_animdata_driver_path_hack(bContext *C, PointerRNA *ptr, PropertyRNA *p Object *ob = CTX_data_active_object(C); if (ob && id) { - /* only id-types which can be remapped to go through objects should be considered */ - switch (GS(id->name)) { - case ID_TE: /* textures */ - { - Material *ma = give_current_material(ob, ob->actcol); - Tex *tex = give_current_material_texture(ma); - - /* assumes: texture will only be shown if it is active material's active texture it's ok */ - if ((ID *)tex == id) { - char name_esc_ma[(sizeof(ma->id.name) - 2) * 2]; - char name_esc_tex[(sizeof(tex->id.name) - 2) * 2]; - - BLI_strescape(name_esc_ma, ma->id.name + 2, sizeof(name_esc_ma)); - BLI_strescape(name_esc_tex, tex->id.name + 2, sizeof(name_esc_tex)); - - /* create new path */ - // TODO: use RNA path functions to construct step by step instead? - // FIXME: maybe this isn't even needed anymore... - path = BLI_sprintfN("material_slots[\"%s\"].material.texture_slots[\"%s\"].texture.%s", - name_esc_ma, name_esc_tex, basepath); - - /* free old one */ - if (basepath != base_path) - MEM_freeN(basepath); - } - break; - } - default: - break; - } + /* TODO: after material textures were removed, this function serves + * no purpose anymore, but could be used again so was not removed. */ /* fix RNA pointer, as we've now changed the ID root by changing the paths */ if (basepath != path) { @@ -1555,37 +1528,100 @@ static bool animsys_store_rna_setting( /* less than 1.0 evaluates to false, use epsilon to avoid float error */ #define ANIMSYS_FLOAT_AS_BOOL(value) ((value) > ((1.0f - FLT_EPSILON))) +static bool animsys_read_rna_setting(PathResolvedRNA *anim_rna, float *r_value) +{ + PropertyRNA *prop = anim_rna->prop; + PointerRNA *ptr = &anim_rna->ptr; + int array_index = anim_rna->prop_index; + float orig_value; + + /* caller must ensure this is animatable */ + BLI_assert(RNA_property_animateable(ptr, prop) || ptr->id.data == NULL); + + switch (RNA_property_type(prop)) { + case PROP_BOOLEAN: + { + if (array_index != -1) { + const int orig_value_coerce = RNA_property_boolean_get_index(ptr, prop, array_index); + orig_value = (float)orig_value_coerce; + } + else { + const int orig_value_coerce = RNA_property_boolean_get(ptr, prop); + orig_value = (float)orig_value_coerce; + } + break; + } + case PROP_INT: + { + if (array_index != -1) { + const int orig_value_coerce = RNA_property_int_get_index(ptr, prop, array_index); + orig_value = (float)orig_value_coerce; + } + else { + const int orig_value_coerce = RNA_property_int_get(ptr, prop); + orig_value = (float)orig_value_coerce; + } + break; + } + case PROP_FLOAT: + { + if (array_index != -1) { + const float orig_value_coerce = RNA_property_float_get_index(ptr, prop, array_index); + orig_value = (float)orig_value_coerce; + } + else { + const float orig_value_coerce = RNA_property_float_get(ptr, prop); + orig_value = (float)orig_value_coerce; + } + break; + } + case PROP_ENUM: + { + const int orig_value_coerce = RNA_property_enum_get(ptr, prop); + orig_value = (float)orig_value_coerce; + break; + } + default: + /* nothing can be done here... so it is unsuccessful? */ + return false; + } + + if (r_value != NULL) { + *r_value = orig_value; + } + + /* successful */ + return true; +} + /* Write the given value to a setting using RNA, and return success */ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float value) { PropertyRNA *prop = anim_rna->prop; PointerRNA *ptr = &anim_rna->ptr; int array_index = anim_rna->prop_index; - + /* 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; + /* Check whether value is new. Otherwise we skip all the updates. */ + float old_value; + if (!animsys_read_rna_setting(anim_rna, &old_value)) { + return false; + } + if (old_value == value) { + return true; + } switch (RNA_property_type(prop)) { case PROP_BOOLEAN: { const int value_coerce = ANIMSYS_FLOAT_AS_BOOL(value); 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; - } + RNA_property_boolean_set_index(ptr, prop, array_index, value_coerce); } else { - if (RNA_property_boolean_get(ptr, prop) != value_coerce) { - RNA_property_boolean_set(ptr, prop, value_coerce); - written = true; - } + RNA_property_boolean_set(ptr, prop, value_coerce); } break; } @@ -1594,16 +1630,10 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val int value_coerce = (int)value; RNA_property_int_clamp(ptr, prop, &value_coerce); 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; - } + RNA_property_int_set_index(ptr, prop, array_index, value_coerce); } else { - if (RNA_property_int_get(ptr, prop) != value_coerce) { - RNA_property_int_set(ptr, prop, value_coerce); - written = true; - } + RNA_property_int_set(ptr, prop, value_coerce); } break; } @@ -1612,26 +1642,17 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val float value_coerce = value; RNA_property_float_clamp(ptr, prop, &value_coerce); 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; - } + RNA_property_float_set_index(ptr, prop, array_index, value_coerce); } else { - if (RNA_property_float_get(ptr, prop) != value_coerce) { - RNA_property_float_set(ptr, prop, value_coerce); - written = true; - } + RNA_property_float_set(ptr, prop, value_coerce); } break; } case PROP_ENUM: { 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; - } + RNA_property_enum_set(ptr, prop, value_coerce); break; } default: @@ -1659,23 +1680,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; } @@ -1697,10 +1701,15 @@ bool BKE_animsys_execute_fcurve(PointerRNA *ptr, AnimMapper *remap, FCurve *fcu, /* Evaluate all the F-Curves in the given list * This performs a set of standard checks. If extra checks are required, separate code should be used */ -static void animsys_evaluate_fcurves(PointerRNA *ptr, ListBase *list, AnimMapper *remap, float ctime) +static void animsys_evaluate_fcurves(PointerRNA *ptr, ListBase *list, AnimMapper *remap, float ctime, short recalc) { FCurve *fcu; - + + /* Pointer is expected to be an ID pointer, if it's not -- we are doomed. */ + PointerRNA orig_ptr = *ptr; + orig_ptr.id.data = ((ID *)orig_ptr.id.data)->orig_id; + orig_ptr.data = orig_ptr.id.data; + /* calculate then execute each curve */ for (fcu = list->first; fcu; fcu = fcu->next) { /* check if this F-Curve doesn't belong to a muted group */ @@ -1708,9 +1717,28 @@ static void animsys_evaluate_fcurves(PointerRNA *ptr, ListBase *list, AnimMapper /* check if this curve should be skipped */ if ((fcu->flag & (FCURVE_MUTED | FCURVE_DISABLED)) == 0) { PathResolvedRNA anim_rna; + /* Read current value from original datablock. */ + float dna_val; + if (animsys_store_rna_setting(&orig_ptr, remap, fcu->rna_path, fcu->array_index, &anim_rna)) { + if (!animsys_read_rna_setting(&anim_rna, &dna_val)) { + continue; + } + } + else { + continue; + } if (animsys_store_rna_setting(ptr, remap, fcu->rna_path, fcu->array_index, &anim_rna)) { + const bool check_orig_dna = ((recalc & ADT_RECALC_CHECK_ORIG_DNA) != 0); + /* If we are tweaking DNA without changing frame, we don't write f-curves, + * since otherwise we will not be able to change properties which has animation. + */ + if (check_orig_dna && fcu->orig_dna_val != dna_val) { + continue; + } const float curval = calculate_fcurve(&anim_rna, fcu, ctime); animsys_write_rna_setting(&anim_rna, curval); + /* Store original DNA value f-curve was written for. */ + fcu->orig_dna_val = dna_val; } } } @@ -1823,7 +1851,7 @@ void animsys_evaluate_action_group(PointerRNA *ptr, bAction *act, bActionGroup * } /* Evaluate Action (F-Curve Bag) */ -void animsys_evaluate_action(PointerRNA *ptr, bAction *act, AnimMapper *remap, float ctime) +static void animsys_evaluate_action_ex(PointerRNA *ptr, bAction *act, AnimMapper *remap, float ctime, short recalc) { /* check if mapper is appropriate for use here (we set to NULL if it's inappropriate) */ if (act == NULL) return; @@ -1832,7 +1860,12 @@ void animsys_evaluate_action(PointerRNA *ptr, bAction *act, AnimMapper *remap, f action_idcode_patch_check(ptr->id.data, act); /* calculate then execute each curve */ - animsys_evaluate_fcurves(ptr, &act->curves, remap, ctime); + animsys_evaluate_fcurves(ptr, &act->curves, remap, ctime, recalc); +} + +void animsys_evaluate_action(PointerRNA *ptr, bAction *act, AnimMapper *remap, float ctime) +{ + animsys_evaluate_action_ex(ptr, act, remap, ctime, 0); } /* ***************************************** */ @@ -1871,7 +1904,7 @@ static void nlastrip_evaluate_controls(NlaStrip *strip, float ctime) RNA_pointer_create(NULL, &RNA_NlaStrip, strip, &strip_ptr); /* execute these settings as per normal */ - animsys_evaluate_fcurves(&strip_ptr, &strip->fcurves, NULL, ctime); + animsys_evaluate_fcurves(&strip_ptr, &strip->fcurves, NULL, ctime, 0); } /* analytically generate values for influence and time (if applicable) @@ -2619,17 +2652,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) @@ -2749,7 +2771,7 @@ void BKE_animsys_evaluate_animdata(Scene *scene, ID *id, AnimData *adt, float ct } /* evaluate Active Action only */ else if (adt->action) - animsys_evaluate_action(&id_ptr, adt->action, adt->remap, ctime); + animsys_evaluate_action_ex(&id_ptr, adt->action, adt->remap, ctime, recalc); /* reset tag */ adt->recalc &= ~ADT_RECALC_ANIM; @@ -2920,17 +2942,44 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime) /* ************** */ /* Evaluation API */ -void BKE_animsys_eval_animdata(EvaluationContext *eval_ctx, ID *id) +void BKE_animsys_eval_animdata(Depsgraph *depsgraph, ID *id) { + float ctime = DEG_get_ctime(depsgraph); AnimData *adt = BKE_animdata_from_id(id); Scene *scene = NULL; /* XXX: this is only needed for flushing RNA updates, * which should get handled as part of the dependency graph instead... */ - DEG_debug_print_eval_time(__func__, id->name, id, eval_ctx->ctime); - BKE_animsys_evaluate_animdata(scene, id, adt, eval_ctx->ctime, ADT_RECALC_ANIM); + DEG_debug_print_eval_time(depsgraph, __func__, id->name, id, ctime); + short recalc = ADT_RECALC_ANIM; + const Scene *scene_eval = DEG_get_evaluated_scene(depsgraph); + /* If animation component is directly tagged for update, we always apply f-curves. */ + if (((scene_eval->id.recalc & ID_RECALC_TIME) == 0) && + (id->recalc & ID_RECALC_TIME) == 0) + { + recalc |= ADT_RECALC_CHECK_ORIG_DNA; + } + BKE_animsys_evaluate_animdata(scene, id, adt, ctime, recalc); +} + +/* TODO(sergey): This is slow lookup of driver from CoW datablock. + * Keep this for until we've got something smarter for depsgraph + * building.\ + */ +static FCurve *find_driver_from_evaluated_id(ID *id, FCurve *fcu) +{ + /* We've got non-CoW datablock, can use f-curve as-is. */ + if (id->orig_id == NULL) { + return fcu; + } + /*const*/ ID *id_orig = id->orig_id; + const AnimData *adt_orig = BKE_animdata_from_id(id_orig); + const AnimData *adt_cow = BKE_animdata_from_id(id); + const int fcu_index = BLI_findindex(&adt_orig->drivers, fcu); + BLI_assert(fcu_index != -1); + return BLI_findlink(&adt_cow->drivers, fcu_index); } -void BKE_animsys_eval_driver(EvaluationContext *eval_ctx, +void BKE_animsys_eval_driver(Depsgraph *depsgraph, ID *id, FCurve *fcu) { @@ -2939,8 +2988,10 @@ void BKE_animsys_eval_driver(EvaluationContext *eval_ctx, PointerRNA id_ptr; bool ok = false; + fcu = find_driver_from_evaluated_id(id, fcu); + DEG_debug_print_eval_subdata_index( - __func__, id->name, id, "fcu", fcu->rna_path, fcu, fcu->array_index); + depsgraph, __func__, id->name, id, "fcu", fcu->rna_path, fcu, fcu->array_index); RNA_id_pointer_create(id, &id_ptr); @@ -2956,7 +3007,8 @@ void BKE_animsys_eval_driver(EvaluationContext *eval_ctx, PathResolvedRNA anim_rna; if (animsys_store_rna_setting(&id_ptr, NULL, fcu->rna_path, fcu->array_index, &anim_rna)) { - const float curval = calculate_fcurve(&anim_rna, fcu, eval_ctx->ctime); + const float ctime = DEG_get_ctime(depsgraph); + const float curval = calculate_fcurve(&anim_rna, fcu, ctime); ok = animsys_write_rna_setting(&anim_rna, curval); } diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 70a3772f388..63846b31c33 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" @@ -74,7 +73,6 @@ #include "BKE_scene.h" #include "BIK_api.h" -#include "BKE_sketch.h" /* **************** Generic Functions, data level *************** */ @@ -136,12 +134,6 @@ void BKE_armature_free(bArmature *arm) MEM_freeN(arm->edbo); arm->edbo = NULL; } - - /* free sketch */ - if (arm->sketch) { - freeSketch(arm->sketch); - arm->sketch = NULL; - } } void BKE_armature_make_local(Main *bmain, bArmature *arm, const bool lib_local) @@ -205,7 +197,6 @@ void BKE_armature_copy_data(Main *UNUSED(bmain), bArmature *arm_dst, const bArma arm_dst->edbo = NULL; arm_dst->act_edbone = NULL; - arm_dst->sketch = NULL; } bArmature *BKE_armature_copy(Main *bmain, const bArmature *arm) @@ -972,7 +963,7 @@ static void armature_bbone_defmats_cb(void *userdata, Link *iter, int index) } } -void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3], +void armature_deform_verts(Object *armOb, Object *target, const Mesh * mesh, float (*vertexCos)[3], float (*defMats)[3][3], int numVerts, int deformflag, float (*prevCos)[3], const char *defgrp_name) { @@ -1048,9 +1039,9 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float /* get a vertex-deform-index to posechannel array */ if (deformflag & ARM_DEF_VGROUP) { if (ELEM(target->type, OB_MESH, OB_LATTICE)) { - /* if we have a DerivedMesh, only use dverts if it has them */ - if (dm) { - use_dverts = (dm->getVertDataArray(dm, CD_MDEFORMVERT) != NULL); + /* if we have a Mesh, only use dverts if it has them */ + if (mesh) { + use_dverts = (mesh->dvert != NULL); } else if (dverts) { use_dverts = true; @@ -1112,8 +1103,10 @@ void armature_deform_verts(Object *armOb, Object *target, DerivedMesh *dm, float } if (use_dverts || armature_def_nr != -1) { - if (dm) - dvert = dm->getVertData(dm, i, CD_MDEFORMVERT); + if (mesh) { + BLI_assert(i < mesh->totvert); + dvert = mesh->dvert + i; + } else if (dverts && i < target_totvert) dvert = dverts + i; else @@ -1463,13 +1456,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(struct Depsgraph *depsgraph, 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(depsgraph, 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 @@ -1950,9 +1943,18 @@ void BKE_pose_clear_pointers(bPose *pose) } } +void BKE_pose_remap_bone_pointers(bArmature *armature, bPose *pose) +{ + GHash *bone_hash = BKE_armature_bone_from_name_map(armature); + for (bPoseChannel *pchan = pose->chanbase.first; pchan; pchan = pchan->next) { + pchan->bone = BLI_ghash_lookup(bone_hash, pchan->name); + } + BLI_ghash_free(bone_hash, NULL, NULL); +} + /* 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; @@ -1996,27 +1998,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 */ @@ -2127,7 +2114,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); @@ -2211,7 +2198,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( + struct Depsgraph *depsgraph, Scene *scene, + Object *ob, bPoseChannel *pchan, float ctime, bool do_extra) { /* This gives a chan_mat with actions (ipos) results. */ if (do_extra) @@ -2250,7 +2239,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(depsgraph, &pchan->constraints, cob, ctime); /* ctime doesnt alter objects */ /* cleanup after Constraint Solving * - applies matrix back to pchan, and frees temporary struct used @@ -2272,7 +2261,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(struct Depsgraph *depsgraph, Scene *scene, Object *ob) { bArmature *arm; Bone *bone; @@ -2311,7 +2300,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(depsgraph, scene, ob, ctime); /* 2b. construct the Spline IK trees * - this is not integrated as an IK plugin, since it should be able @@ -2323,15 +2312,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(depsgraph, 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(depsgraph, 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(depsgraph, 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 ee63e618b18..bf21019a948 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" @@ -113,9 +112,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(depsgraph, 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)) { @@ -123,6 +124,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 @@ -261,15 +265,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( + struct Depsgraph *depsgraph, 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(depsgraph, scene, ob, pchan, ctime, 1); copy_v3_v3(poseHead, pchan->pose_head); copy_v3_v3(poseTail, pchan->pose_tail); @@ -511,7 +516,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(struct Depsgraph *depsgraph, Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime) { tSplineIK_Tree *tree; @@ -525,7 +530,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(depsgraph, tree, scene, ob, pchan, i, ctime); } /* free the tree info specific to SplineIK trees now */ @@ -544,9 +549,11 @@ 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( + struct Depsgraph *depsgraph, Scene *scene, + Object *ob, bPoseChannel *pchan_root, float ctime) { - splineik_execute_tree(scene, ob, pchan_root, ctime); + splineik_execute_tree(depsgraph, scene, ob, pchan_root, ctime); } /* *************** Depsgraph evaluation callbacks ************ */ @@ -560,14 +567,14 @@ BLI_INLINE bPoseChannel *pose_pchan_get_indexed(Object *ob, int pchan_index) return pose->chan_array[pchan_index]; } -void BKE_pose_eval_init(EvaluationContext *UNUSED(eval_ctx), +void BKE_pose_eval_init(struct Depsgraph *depsgraph, Scene *UNUSED(scene), Object *ob) { bPose *pose = ob->pose; BLI_assert(pose != NULL); - DEG_debug_print_eval(__func__, ob->id.name, ob); + DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob); BLI_assert(ob->type == OB_ARMATURE); @@ -590,11 +597,11 @@ 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(struct Depsgraph *depsgraph, Scene *scene, Object *ob) { - DEG_debug_print_eval(__func__, ob->id.name, ob); + DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob); BLI_assert(ob->type == OB_ARMATURE); const float ctime = BKE_scene_frame_get(scene); /* not accurate... */ bArmature *arm = (bArmature *)ob->data; @@ -602,7 +609,7 @@ void BKE_pose_eval_init_ik(EvaluationContext *UNUSED(eval_ctx), return; } /* construct the IK tree (standard IK) */ - BIK_initialize_tree(scene, ob, ctime); + BIK_initialize_tree(depsgraph, scene, ob, ctime); /* 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 @@ -610,14 +617,14 @@ 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(struct Depsgraph *depsgraph, Scene *scene, Object *ob, int pchan_index) { bPoseChannel *pchan = pose_pchan_get_indexed(ob, pchan_index); DEG_debug_print_eval_subdata( - __func__, ob->id.name, ob, "pchan", pchan->name, pchan); + depsgraph, __func__, ob->id.name, ob, "pchan", pchan->name, pchan); BLI_assert(ob->type == OB_ARMATURE); bArmature *arm = (bArmature *)ob->data; if (arm->edbo || (arm->flag & ARM_RESTPOS)) { @@ -640,21 +647,21 @@ 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(depsgraph, scene, ob, pchan, ctime, 1); } } } } } -void BKE_pose_constraints_evaluate(EvaluationContext *UNUSED(eval_ctx), +void BKE_pose_constraints_evaluate(struct Depsgraph *depsgraph, Scene *scene, Object *ob, int pchan_index) { bPoseChannel *pchan = pose_pchan_get_indexed(ob, pchan_index); DEG_debug_print_eval_subdata( - __func__, ob->id.name, ob, "pchan", pchan->name, pchan); + depsgraph, __func__, ob->id.name, ob, "pchan", pchan->name, pchan); bArmature *arm = (bArmature *)ob->data; if (arm->flag & ARM_RESTPOS) { return; @@ -665,42 +672,42 @@ 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(depsgraph, scene, ob, pchan, ctime, 1); } } } -void BKE_pose_bone_done(EvaluationContext *UNUSED(eval_ctx), +void BKE_pose_bone_done(struct Depsgraph *depsgraph, struct Object *ob, int pchan_index) { bPoseChannel *pchan = pose_pchan_get_indexed(ob, pchan_index); float imat[4][4]; - DEG_debug_print_eval(__func__, pchan->name, pchan); + DEG_debug_print_eval(depsgraph, __func__, pchan->name, pchan); if (pchan->bone) { invert_m4_m4(imat, pchan->bone->arm_mat); mul_m4_m4m4(pchan->chan_mat, pchan->pose_mat, imat); } } -void BKE_pose_iktree_evaluate(EvaluationContext *UNUSED(eval_ctx), +void BKE_pose_iktree_evaluate(struct Depsgraph *depsgraph, Scene *scene, Object *ob, int rootchan_index) { bPoseChannel *rootchan = pose_pchan_get_indexed(ob, rootchan_index); DEG_debug_print_eval_subdata( - __func__, ob->id.name, ob, "rootchan", rootchan->name, rootchan); + depsgraph, __func__, ob->id.name, ob, "rootchan", rootchan->name, rootchan); BLI_assert(ob->type == OB_ARMATURE); const float ctime = BKE_scene_frame_get(scene); /* not accurate... */ bArmature *arm = (bArmature *)ob->data; if (arm->flag & ARM_RESTPOS) { return; } - BIK_execute_tree(scene, ob, rootchan, ctime); + BIK_execute_tree(depsgraph, scene, ob, rootchan, ctime); } -void BKE_pose_splineik_evaluate(EvaluationContext *UNUSED(eval_ctx), +void BKE_pose_splineik_evaluate(struct Depsgraph *depsgraph, Scene *scene, Object *ob, int rootchan_index) @@ -708,17 +715,17 @@ void BKE_pose_splineik_evaluate(EvaluationContext *UNUSED(eval_ctx), { bPoseChannel *rootchan = pose_pchan_get_indexed(ob, rootchan_index); DEG_debug_print_eval_subdata( - __func__, ob->id.name, ob, "rootchan", rootchan->name, rootchan); + depsgraph, __func__, ob->id.name, ob, "rootchan", rootchan->name, rootchan); BLI_assert(ob->type == OB_ARMATURE); const float ctime = BKE_scene_frame_get(scene); /* not accurate... */ bArmature *arm = (bArmature *)ob->data; if (arm->flag & ARM_RESTPOS) { return; } - BKE_splineik_execute_tree(scene, ob, rootchan, ctime); + BKE_splineik_execute_tree(depsgraph, scene, ob, rootchan, ctime); } -void BKE_pose_eval_flush(EvaluationContext *UNUSED(eval_ctx), +void BKE_pose_eval_flush(struct Depsgraph *depsgraph, Scene *scene, Object *ob) { @@ -726,29 +733,23 @@ void BKE_pose_eval_flush(EvaluationContext *UNUSED(eval_ctx), BLI_assert(pose != NULL); float ctime = BKE_scene_frame_get(scene); /* not accurate... */ - DEG_debug_print_eval(__func__, ob->id.name, ob); + DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob); BLI_assert(ob->type == OB_ARMATURE); /* release the IK tree */ BIK_release_tree(scene, ob, ctime); - ob->recalc &= ~OB_RECALC_ALL; - BLI_assert(pose->chan_array != NULL); MEM_freeN(pose->chan_array); pose->chan_array = NULL; } -void BKE_pose_eval_proxy_copy(EvaluationContext *UNUSED(eval_ctx), Object *ob) +void BKE_pose_eval_proxy_copy(struct Depsgraph *depsgraph, Object *ob) { BLI_assert(ID_IS_LINKED(ob) && ob->proxy_from != NULL); - DEG_debug_print_eval(__func__, ob->id.name, ob); + DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob); if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) { printf("Proxy copy error, lib Object: %s proxy Object: %s\n", ob->id.name + 2, ob->proxy_from->id.name + 2); } - /* 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 55b2d5b9c0d..236b965ec34 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" @@ -92,7 +94,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(); @@ -101,6 +103,8 @@ void BKE_blender_free(void) BKE_sequencer_cache_destruct(); IMB_moviecache_destruct(); + + BKE_layer_exit(); free_nodesystem(); } @@ -283,11 +287,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 6b31c8c96f9..98482bcc8b1 100644 --- a/source/blender/blenkernel/intern/blender_undo.c +++ b/source/blender/blenkernel/intern/blender_undo.c @@ -50,13 +50,14 @@ #include "BKE_blendfile.h" #include "BKE_appdir.h" #include "BKE_context.h" -#include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_main.h" #include "BLO_undofile.h" #include "BLO_writefile.h" +#include "DEG_depsgraph.h" + /* -------------------------------------------------------------------- */ /** \name Global Undo @@ -87,7 +88,7 @@ bool BKE_memfile_undo_decode(MemFileUndoData *mfu, bContext *C) 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..34079d778f7 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_default_view(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_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 024c0aeb23f..eb5cdd02fe5 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.depsgraph = bbd->sim->depsgraph; temp_eff.scene = bbd->sim->scene; eff = &temp_eff; get_effector_data(eff, &efd, &epoint, 0); diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c index e9a8de4469d..259c5189896 100644 --- a/source/blender/blenkernel/intern/bpath.c +++ b/source/blender/blenkernel/intern/bpath.c @@ -580,14 +580,6 @@ void BKE_bpath_traverse_id(Main *bmain, ID *id, BPathVisitor visit_cb, const int } break; } - case ID_TE: - { - Tex *tex = (Tex *)id; - if (tex->type == TEX_VOXELDATA && TEX_VD_IS_SOURCE_PATH(tex->vd->file_format)) { - rewrite_path_fixed(tex->vd->source_path, visit_cb, absbase, bpath_user_data); - } - break; - } case ID_SCE: { Scene *scene = (Scene *)id; diff --git a/source/blender/blenkernel/intern/bullet.c b/source/blender/blenkernel/intern/bullet.c deleted file mode 100644 index c16c0f7af31..00000000000 --- a/source/blender/blenkernel/intern/bullet.c +++ /dev/null @@ -1,99 +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) 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/bullet.c - * \ingroup bke - */ - - -#include "MEM_guardedalloc.h" - -/* types */ -#include "DNA_object_force_types.h" /* here is the softbody struct */ - -#include "BKE_bullet.h" - - -/* ************ Object level, exported functions *************** */ - -/* allocates and initializes general main data */ -BulletSoftBody *bsbNew(void) -{ - BulletSoftBody *bsb; - - bsb = MEM_callocN(sizeof(BulletSoftBody), "bulletsoftbody"); - - bsb->flag = OB_BSB_BENDING_CONSTRAINTS | OB_BSB_SHAPE_MATCHING | OB_BSB_AERO_VPOINT; - bsb->linStiff = 0.5f; - bsb->angStiff = 1.0f; - bsb->volume = 1.0f; - - - bsb->viterations = 0; - bsb->piterations = 2; - bsb->diterations = 0; - bsb->citerations = 4; - - bsb->kSRHR_CL = 0.1f; - bsb->kSKHR_CL = 1.f; - bsb->kSSHR_CL = 0.5f; - bsb->kSR_SPLT_CL = 0.5f; - - bsb->kSK_SPLT_CL = 0.5f; - bsb->kSS_SPLT_CL = 0.5f; - bsb->kVCF = 1; - bsb->kDP = 0; - - bsb->kDG = 0; - bsb->kLF = 0; - bsb->kPR = 0; - bsb->kVC = 0; - - bsb->kDF = 0.2f; - bsb->kMT = 0.05; - bsb->kCHR = 1.0f; - bsb->kKHR = 0.1f; - - bsb->kSHR = 1.0f; - bsb->kAHR = 0.7f; - - bsb->collisionflags = 0; - //bsb->collisionflags = OB_BSB_COL_CL_RS + OB_BSB_COL_CL_SS; - bsb->numclusteriterations = 64; - bsb->welding = 0.f; - - return bsb; -} - -/* frees all */ -void bsbFree(BulletSoftBody *bsb) -{ - /* no internal data yet */ - MEM_freeN(bsb); -} - - diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c index 058394fc1b1..8f156e8f267 100644 --- a/source/blender/blenkernel/intern/cachefile.c +++ b/source/blender/blenkernel/intern/cachefile.c @@ -175,7 +175,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); @@ -215,11 +215,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 132cbd07ac3..2c5cdc39ebc 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" @@ -47,6 +48,7 @@ #include "BKE_animsys.h" #include "BKE_camera.h" #include "BKE_object.h" +#include "BKE_layer.h" #include "BKE_library.h" #include "BKE_library_query.h" #include "BKE_library_remap.h" @@ -54,7 +56,9 @@ #include "BKE_scene.h" #include "BKE_screen.h" -#include "GPU_compositing.h" +#include "DEG_depsgraph_query.h" + +#include "MEM_guardedalloc.h" /****************************** Camera Datablock *****************************/ @@ -72,8 +76,6 @@ void BKE_camera_init(Camera *cam) cam->flag |= CAM_SHOWPASSEPARTOUT; cam->passepartalpha = 0.5f; - GPU_fx_compositor_init_dof_settings(&cam->gpu_dof); - /* stereoscopy 3d */ cam->stereo.interocular_distance = 0.065f; cam->stereo.convergence_distance = 30.f * 0.065f; @@ -100,9 +102,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) @@ -120,6 +132,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); } @@ -237,7 +259,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, Depsgraph *depsgraph, const View3D *v3d, const RegionView3D *rv3d) { /* common */ params->lens = v3d->lens; @@ -246,7 +268,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); @@ -281,10 +304,7 @@ void BKE_camera_params_compute_viewplane(CameraParams *params, int winx, int win float pixsize, viewfac, sensor_size, dx, dy; int sensor_fit; - /* fields rendering */ params->ycor = yasp / xasp; - if (params->use_fields) - params->ycor *= 2.0f; if (params->is_ortho) { /* orthographic camera */ @@ -326,18 +346,6 @@ void BKE_camera_params_compute_viewplane(CameraParams *params, int winx, int win viewplane.xmax += dx; viewplane.ymax += dy; - /* fields offset */ - if (params->field_second) { - if (params->field_odd) { - viewplane.ymin -= 0.5f * params->ycor; - viewplane.ymax -= 0.5f * params->ycor; - } - else { - viewplane.ymin += 0.5f * params->ycor; - viewplane.ymax += 0.5f * params->ycor; - } - } - /* the window matrix is used for clipping, and not changed during OSA steps */ /* using an offset of +0.5 here would give clip errors on edges */ viewplane.xmin *= pixsize; @@ -641,7 +649,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) + Depsgraph *depsgraph, Scene *scene, ViewLayer *view_layer, Object *camera_ob, float r_co[3], float *r_scale) { CameraParams params; CameraViewFrameData data_cb; @@ -652,7 +660,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(depsgraph, scene, view_layer, camera_to_frame_view_cb, &data_cb); return camera_frame_fit_calc_from_data(¶ms, &data_cb, r_co, r_scale); } @@ -861,9 +869,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; } } @@ -960,3 +968,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 1a34b71643f..4d91d99b022 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -57,12 +57,6 @@ #include "MEM_guardedalloc.h" -#include "GPU_buffers.h" -#include "GPU_draw.h" -#include "GPU_glew.h" -#include "GPU_shader.h" -#include "GPU_basic_shader.h" - #include <string.h> #include <limits.h> #include <math.h> @@ -338,1450 +332,6 @@ static PBVH *cdDM_getPBVH(Object *ob, DerivedMesh *dm) return cddm->pbvh; } -/* update vertex normals so that drawing smooth faces works during sculpt - * TODO: proper fix is to support the pbvh in all drawing modes */ -static void cdDM_update_normals_from_pbvh(DerivedMesh *dm) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *) dm; - float (*face_nors)[3]; - - /* Some callbacks do not use optimal PBVH draw, so needs all the - * possible data (like normals) to be copied from PBVH back to DM. - * - * This is safe to do if PBVH and DM are representing the same mesh, - * which could be wrong when modifiers are enabled for sculpt. - * So here we only doing update when there's no modifiers applied - * during sculpt. - * - * It's safe to do nothing if there are modifiers, because in this - * case modifier stack is re-constructed from scratch on every - * update. - */ - if (!cddm->pbvh_draw) { - return; - } - - face_nors = CustomData_get_layer(&dm->polyData, CD_NORMAL); - - BKE_pbvh_update(cddm->pbvh, PBVH_UpdateNormals, face_nors); -} - -static void cdDM_drawVerts(DerivedMesh *dm) -{ - GPU_vertex_setup(dm); - if (dm->drawObject->tot_loop_verts) - glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_loop_verts); - else - glDrawArrays(GL_POINTS, 0, dm->drawObject->tot_loose_point); - GPU_buffers_unbind(); -} - -static void cdDM_drawUVEdges(DerivedMesh *dm) -{ - 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) - { - BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, true, false); - - 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); - } - } - GPU_buffers_unbind(); -} - -static void cdDM_drawLooseEdges(DerivedMesh *dm) -{ - int start; - int count; - - GPU_edge_setup(dm); - - start = (dm->drawObject->loose_edge_offset * 2); - count = (dm->drawObject->totedge - dm->drawObject->loose_edge_offset) * 2; - - if (count) { - GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, start, count); - } - - GPU_buffers_unbind(); -} - -static void cdDM_drawFacesSolid( - DerivedMesh *dm, - float (*partial_redraw_planes)[4], - bool UNUSED(fast), DMSetMaterial setMaterial) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *) dm; - int a; - - if (cddm->pbvh) { - if (cddm->pbvh_draw && BKE_pbvh_has_faces(cddm->pbvh)) { - float (*face_nors)[3] = CustomData_get_layer(&dm->polyData, CD_NORMAL); - - BKE_pbvh_draw(cddm->pbvh, partial_redraw_planes, face_nors, - setMaterial, false, false); - 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 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); - } - } - - 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); - } - } - - 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); - } - - /* 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 actualFace = bufmat->polys[i]; - DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL; - int flush = 0; - int tot_tri_verts; - - if (i != totpoly - 1) - next_actualFace = bufmat->polys[i + 1]; - - 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); - } - } - else if (drawParamsMapped) { - draw_option = drawParamsMapped(userData, actualFace, mpoly[actualFace].mat_nr); - } - } - - /* 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 { - tot_drawn += tot_tri_verts; - } - } - } - - 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); -} - -static void cdDM_drawMappedFaces( - DerivedMesh *dm, - DMSetDrawOptions setDrawOptions, - DMSetMaterial setMaterial, - DMCompareDrawOptions compareDrawOptions, - void *userData, DMDrawFlag flag) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *) dm; - const MPoly *mpoly = cddm->mpoly; - const MLoopCol *mloopcol = NULL; - const bool use_colors = (flag & DM_DRAW_USE_COLORS) != 0; - const bool use_hide = (flag & DM_DRAW_SKIP_HIDDEN) != 0; - int colType; - int i, j; - int start_element = 0, tot_element, tot_drawn; - int totpoly; - int tot_tri_elem; - int mat_index; - GPUBuffer *findex_buffer = NULL; - - const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); - - if (cddm->pbvh) { - if (G.debug_value == 14) - BKE_pbvh_draw_BB(cddm->pbvh); - } - - /* fist, setup common buffers */ - GPU_vertex_setup(dm); - GPU_triangle_setup(dm); - - totpoly = dm->getNumPolys(dm); - - /* if we do selection, fill the selection buffer color */ - if (G.f & G_BACKBUFSEL) { - if (!(flag & DM_DRAW_SKIP_SELECT)) { - Mesh *me = NULL; - BMesh *bm = NULL; - unsigned int *fi_map; - - if (flag & DM_DRAW_SELECT_USE_EDITMODE) - bm = userData; - else - me = userData; - - findex_buffer = GPU_buffer_alloc(dm->drawObject->tot_loop_verts * sizeof(int)); - fi_map = GPU_buffer_lock(findex_buffer, GPU_BINDING_ARRAY); - - if (fi_map) { - for (i = 0; i < totpoly; i++, mpoly++) { - int selcol = 0xFFFFFFFF; - const int orig = (index_mp_to_orig) ? index_mp_to_orig[i] : i; - bool is_hidden; - - if (orig != ORIGINDEX_NONE) { - if (use_hide) { - if (flag & DM_DRAW_SELECT_USE_EDITMODE) { - BMFace *efa = BM_face_at_index(bm, orig); - is_hidden = BM_elem_flag_test(efa, BM_ELEM_HIDDEN) != 0; - } - else { - is_hidden = (me->mpoly[orig].flag & ME_HIDE) != 0; - } - - if (!is_hidden) { - GPU_select_index_get(orig + 1, &selcol); - } - } - else { - GPU_select_index_get(orig + 1, &selcol); - } - } - - for (j = 0; j < mpoly->totloop; j++) - fi_map[start_element++] = selcol; - } - - start_element = 0; - mpoly = cddm->mpoly; - - GPU_buffer_unlock(findex_buffer, GPU_BINDING_ARRAY); - GPU_buffer_bind_as_color(findex_buffer); - } - } - } - else { - GPU_normal_setup(dm); - - if (use_colors) { - colType = CD_TEXTURE_MLOOPCOL; - mloopcol = DM_get_loop_data_layer(dm, colType); - if (!mloopcol) { - colType = CD_PREVIEW_MLOOPCOL; - mloopcol = DM_get_loop_data_layer(dm, colType); - } - if (!mloopcol) { - colType = CD_MLOOPCOL; - mloopcol = DM_get_loop_data_layer(dm, colType); - } - - if (use_colors && mloopcol) { - GPU_color_setup(dm, colType); - } - } - } - - tot_tri_elem = dm->drawObject->tot_triangle_point; - - if (tot_tri_elem == 0) { - /* avoid buffer problems in following code */ - } - else if (setDrawOptions == NULL) { - /* just draw the entire face array */ - GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, 0, tot_tri_elem); - } - else { - for (mat_index = 0; mat_index < dm->drawObject->totmaterial; mat_index++) { - GPUBufferMaterial *bufmat = dm->drawObject->materials + mat_index; - DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL; - int next_actualFace = bufmat->polys[0]; - totpoly = use_hide ? bufmat->totvisiblepolys : bufmat->totpolys; - - tot_element = 0; - start_element = 0; - tot_drawn = 0; - - if (setMaterial) - draw_option = setMaterial(bufmat->mat_nr + 1, NULL); - - if (draw_option != DM_DRAW_OPTION_SKIP) { - DMDrawOption last_draw_option = DM_DRAW_OPTION_NORMAL; - - for (i = 0; i < totpoly; i++) { - int actualFace = next_actualFace; - int flush = 0; - int tot_tri_verts; - - draw_option = DM_DRAW_OPTION_NORMAL; - - if (i != totpoly - 1) - next_actualFace = bufmat->polys[i + 1]; - - if (setDrawOptions) { - const int orig = (index_mp_to_orig) ? index_mp_to_orig[actualFace] : actualFace; - - if (orig != ORIGINDEX_NONE) { - draw_option = setDrawOptions(userData, orig); - } - } - - /* Goal is to draw as long of a contiguous triangle - * array as possible, so draw when we hit either an - * invisible triangle or at the end of the array */ - - /* flush buffer if current triangle isn't drawable or it's last triangle... */ - flush = (draw_option != last_draw_option) || (i == totpoly - 1); - - if (!flush && compareDrawOptions) { - 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 (last_draw_option != draw_option) { - if (draw_option == DM_DRAW_OPTION_STIPPLE) { - GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR); - GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_QUARTTONE); - } - else { - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - } - } - } - - if (tot_drawn) { - GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, bufmat->start + start_element, tot_drawn); - tot_drawn = 0; - } - - last_draw_option = draw_option; - start_element = tot_element; - } - else { - if (draw_option != DM_DRAW_OPTION_SKIP) { - tot_drawn += tot_tri_verts; - } - else { - start_element = tot_element; - } - } - } - } - } - } - - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - - GPU_buffers_unbind(); - - if (findex_buffer) - GPU_buffer_free(findex_buffer); - -} - -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) -{ - DM_draw_attrib_vertex(attribs, a, index, vert, loop); - - /* vertex normal */ - if (lnor) { - glNormal3fv(lnor); - } - else if (smoothnormal) { - glNormal3sv(mvert[index].no); - } - - /* vertex coordinate */ - glVertex3fv(mvert[index].co); -} - -typedef struct { - DMVertexAttribs attribs; - int numdata; - - GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/ -} GPUMaterialConv; - -static void cdDM_drawMappedFacesGLSL( - DerivedMesh *dm, - DMSetMaterial setMaterial, - DMSetDrawOptions setDrawOptions, - void *userData) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *) dm; - GPUVertexAttribs gattribs; - const MVert *mvert = cddm->mvert; - const MPoly *mpoly = cddm->mpoly; - const MLoop *mloop = cddm->mloop; - const MLoopTri *lt = dm->getLoopTriArray(dm); - const int tottri = dm->getNumLoopTri(dm); - /* MTFace *tf = dm->getTessFaceDataArray(dm, CD_MTFACE); */ /* UNUSED */ - const float (*nors)[3] = dm->getPolyDataArray(dm, CD_NORMAL); - const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL); - const int totpoly = dm->getNumPolys(dm); - const short dm_totmat = dm->totmat; - int a, b, matnr, new_matnr; - bool do_draw; - int orig; - - const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); - - /* TODO: same as for solid draw, not entirely correct, but works fine for now, - * will skip using textures (dyntopo currently destroys UV anyway) and - * works fine for matcap - */ - if (cddm->pbvh) { - if (cddm->pbvh_draw && - BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH && - BKE_pbvh_has_faces(cddm->pbvh)) - { - setMaterial(1, &gattribs); - BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false, false); - return; - } - else { - cdDM_update_normals_from_pbvh(dm); - } - } - - matnr = -1; - do_draw = false; - - if (setDrawOptions != NULL) { - DMVertexAttribs attribs; - DEBUG_VBO("Using legacy code. cdDM_drawMappedFacesGLSL\n"); - memset(&attribs, 0, sizeof(attribs)); - - glBegin(GL_TRIANGLES); - - for (a = 0; a < tottri; a++, lt++) { - const MPoly *mp = &mpoly[lt->poly]; - const unsigned int vtri[3] = {mloop[lt->tri[0]].v, mloop[lt->tri[1]].v, mloop[lt->tri[2]].v}; - const unsigned int *ltri = lt->tri; - const float *ln1 = NULL, *ln2 = NULL, *ln3 = NULL; - const bool smoothnormal = lnors || (mp->flag & ME_SMOOTH); - new_matnr = mp->mat_nr; - - if (new_matnr != matnr) { - glEnd(); - - matnr = new_matnr; - do_draw = setMaterial(matnr + 1, &gattribs); - if (do_draw) { - DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); - DM_draw_attrib_vertex_uniforms(&attribs); - } - - glBegin(GL_TRIANGLES); - } - - if (!do_draw) { - continue; - } - else /* if (setDrawOptions) */ { - orig = (index_mp_to_orig) ? index_mp_to_orig[lt->poly] : lt->poly; - - if (orig == ORIGINDEX_NONE) { - /* since the material is set by setMaterial(), faces with no - * origin can be assumed to be generated by a modifier */ - - /* continue */ - } - else if (setDrawOptions(userData, orig) == DM_DRAW_OPTION_SKIP) - continue; - } - - if (!smoothnormal) { - if (nors) { - glNormal3fv(nors[lt->poly]); - } - else { - /* TODO ideally a normal layer should always be available */ - float nor[3]; - normal_tri_v3(nor, mvert[vtri[0]].co, mvert[vtri[1]].co, mvert[vtri[2]].co); - glNormal3fv(nor); - } - } - else if (lnors) { - ln1 = lnors[ltri[0]]; - ln2 = lnors[ltri[1]]; - ln3 = lnors[ltri[2]]; - } - - cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[0], ltri[0], 0, ln1, smoothnormal); - cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[1], ltri[1], 1, ln2, smoothnormal); - cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[2], ltri[2], 2, ln3, smoothnormal); - } - glEnd(); - } - else { - GPUMaterialConv *matconv; - int offset; - int *mat_orig_to_new; - int tot_active_mat; - GPUBuffer *buffer = NULL; - unsigned char *varray; - size_t max_element_size = 0; - int tot_loops = 0; - - GPU_vertex_setup(dm); - GPU_normal_setup(dm); - GPU_triangle_setup(dm); - - tot_active_mat = dm->drawObject->totmaterial; - - matconv = MEM_calloc_arrayN(tot_active_mat, sizeof(*matconv), - "cdDM_drawMappedFacesGLSL.matconv"); - mat_orig_to_new = MEM_malloc_arrayN(dm->totmat, sizeof(*mat_orig_to_new), - "cdDM_drawMappedFacesGLSL.mat_orig_to_new"); - - /* part one, check what attributes are needed per material */ - for (a = 0; a < tot_active_mat; a++) { - new_matnr = dm->drawObject->materials[a].mat_nr; - - /* map from original material index to new - * GPUBufferMaterial index */ - mat_orig_to_new[new_matnr] = a; - do_draw = setMaterial(new_matnr + 1, &gattribs); - - if (do_draw) { - int numdata = 0; - DM_vertex_attributes_from_gpu(dm, &gattribs, &matconv[a].attribs); - - if (matconv[a].attribs.totorco && matconv[a].attribs.orco.array) { - matconv[a].datatypes[numdata].index = matconv[a].attribs.orco.gl_index; - matconv[a].datatypes[numdata].info_index = matconv[a].attribs.orco.gl_info_index; - matconv[a].datatypes[numdata].size = 3; - matconv[a].datatypes[numdata].type = GL_FLOAT; - numdata++; - } - for (b = 0; b < matconv[a].attribs.tottface; b++) { - if (matconv[a].attribs.tface[b].array) { - matconv[a].datatypes[numdata].index = matconv[a].attribs.tface[b].gl_index; - matconv[a].datatypes[numdata].info_index = matconv[a].attribs.tface[b].gl_info_index; - matconv[a].datatypes[numdata].size = 2; - matconv[a].datatypes[numdata].type = GL_FLOAT; - numdata++; - } - } - for (b = 0; b < matconv[a].attribs.totmcol; b++) { - if (matconv[a].attribs.mcol[b].array) { - matconv[a].datatypes[numdata].index = matconv[a].attribs.mcol[b].gl_index; - matconv[a].datatypes[numdata].info_index = matconv[a].attribs.mcol[b].gl_info_index; - matconv[a].datatypes[numdata].size = 4; - matconv[a].datatypes[numdata].type = GL_UNSIGNED_BYTE; - numdata++; - } - } - for (b = 0; b < matconv[a].attribs.tottang; b++) { - if (matconv[a].attribs.tang[b].array) { - matconv[a].datatypes[numdata].index = matconv[a].attribs.tang[b].gl_index; - matconv[a].datatypes[numdata].info_index = matconv[a].attribs.tang[b].gl_info_index; - matconv[a].datatypes[numdata].size = 4; - matconv[a].datatypes[numdata].type = GL_FLOAT; - numdata++; - } - } - if (numdata != 0) { - matconv[a].numdata = numdata; - max_element_size = max_ii(GPU_attrib_element_size(matconv[a].datatypes, numdata), max_element_size); - } - } - } - - /* part two, generate and fill the arrays with the data */ - if (max_element_size > 0) { - buffer = GPU_buffer_alloc(max_element_size * dm->drawObject->tot_loop_verts); - - varray = GPU_buffer_lock_stream(buffer, GPU_BINDING_ARRAY); - if (varray == NULL) { - GPU_buffers_unbind(); - GPU_buffer_free(buffer); - MEM_freeN(mat_orig_to_new); - MEM_freeN(matconv); - fprintf(stderr, "Out of memory, can't draw object\n"); - return; - } - - for (a = 0; a < totpoly; a++, mpoly++) { - const short mat_nr = ME_MAT_NR_TEST(mpoly->mat_nr, dm_totmat); - int j; - int i = mat_orig_to_new[mat_nr]; - offset = tot_loops * max_element_size; - - if (matconv[i].numdata != 0) { - if (matconv[i].attribs.totorco && matconv[i].attribs.orco.array) { - for (j = 0; j < mpoly->totloop; j++) - copy_v3_v3((float *)&varray[offset + j * max_element_size], - (float *)matconv[i].attribs.orco.array[mloop[mpoly->loopstart + j].v]); - offset += sizeof(float) * 3; - } - for (b = 0; b < matconv[i].attribs.tottface; b++) { - if (matconv[i].attribs.tface[b].array) { - const MLoopUV *mloopuv = matconv[i].attribs.tface[b].array; - for (j = 0; j < mpoly->totloop; j++) - copy_v2_v2((float *)&varray[offset + j * max_element_size], mloopuv[mpoly->loopstart + j].uv); - offset += sizeof(float) * 2; - } - } - for (b = 0; b < matconv[i].attribs.totmcol; b++) { - if (matconv[i].attribs.mcol[b].array) { - const MLoopCol *mloopcol = matconv[i].attribs.mcol[b].array; - for (j = 0; j < mpoly->totloop; j++) - copy_v4_v4_uchar(&varray[offset + j * max_element_size], &mloopcol[mpoly->loopstart + j].r); - offset += sizeof(unsigned char) * 4; - } - } - for (b = 0; b < matconv[i].attribs.tottang; b++) { - if (matconv[i].attribs.tottang && matconv[i].attribs.tang[b].array) { - const float (*looptang)[4] = (const float (*)[4])matconv[i].attribs.tang[b].array; - for (j = 0; j < mpoly->totloop; j++) - copy_v4_v4((float *)&varray[offset + j * max_element_size], looptang[mpoly->loopstart + j]); - offset += sizeof(float) * 4; - } - } - } - - tot_loops += mpoly->totloop; - } - GPU_buffer_unlock(buffer, GPU_BINDING_ARRAY); - } - - for (a = 0; a < tot_active_mat; a++) { - new_matnr = dm->drawObject->materials[a].mat_nr; - - do_draw = setMaterial(new_matnr + 1, &gattribs); - - if (do_draw) { - if (matconv[a].numdata) { - GPU_interleaved_attrib_setup(buffer, matconv[a].datatypes, matconv[a].numdata, max_element_size); - } - GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, - dm->drawObject->materials[a].start, dm->drawObject->materials[a].totelements); - if (matconv[a].numdata) { - GPU_interleaved_attrib_unbind(); - } - } - } - - GPU_buffers_unbind(); - if (buffer) - GPU_buffer_free(buffer); - - MEM_freeN(mat_orig_to_new); - MEM_freeN(matconv); - } -} - -static void cdDM_drawFacesGLSL(DerivedMesh *dm, DMSetMaterial setMaterial) -{ - dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL); -} - -static void cdDM_drawMappedFacesMat( - DerivedMesh *dm, - void (*setMaterial)(void *userData, int matnr, void *attribs), - bool (*setFace)(void *userData, int index), void *userData) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *) dm; - GPUVertexAttribs gattribs; - DMVertexAttribs attribs; - MVert *mvert = cddm->mvert; - const MPoly *mpoly = cddm->mpoly; - const MLoop *mloop = cddm->mloop; - const MLoopTri *lt = dm->getLoopTriArray(dm); - const int tottri = dm->getNumLoopTri(dm); - const float (*nors)[3] = dm->getPolyDataArray(dm, CD_NORMAL); - const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL); - int a, matnr, new_matnr; - int orig; - - const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); - - /* TODO: same as for solid draw, not entirely correct, but works fine for now, - * will skip using textures (dyntopo currently destroys UV anyway) and - * works fine for matcap - */ - - if (cddm->pbvh) { - if (cddm->pbvh_draw && - BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH && - BKE_pbvh_has_faces(cddm->pbvh)) - { - setMaterial(userData, 1, &gattribs); - BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false, false); - return; - } - else { - cdDM_update_normals_from_pbvh(dm); - } - } - - matnr = -1; - - memset(&attribs, 0, sizeof(attribs)); - - glBegin(GL_TRIANGLES); - - for (a = 0; a < tottri; a++, lt++) { - const MPoly *mp = &mpoly[lt->poly]; - const unsigned int vtri[3] = {mloop[lt->tri[0]].v, mloop[lt->tri[1]].v, mloop[lt->tri[2]].v}; - const unsigned int *ltri = lt->tri; - const bool smoothnormal = lnors || (mp->flag & ME_SMOOTH); - const float *ln1 = NULL, *ln2 = NULL, *ln3 = NULL; - - /* material */ - new_matnr = mp->mat_nr + 1; - - if (new_matnr != matnr) { - glEnd(); - - setMaterial(userData, matnr = new_matnr, &gattribs); - DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); - DM_draw_attrib_vertex_uniforms(&attribs); - - glBegin(GL_TRIANGLES); - } - - /* skipping faces */ - if (setFace) { - orig = (index_mp_to_orig) ? index_mp_to_orig[lt->poly] : lt->poly; - - if (orig != ORIGINDEX_NONE && !setFace(userData, orig)) - continue; - } - - /* smooth normal */ - if (!smoothnormal) { - if (nors) { - glNormal3fv(nors[lt->poly]); - } - else { - /* TODO ideally a normal layer should always be available */ - float nor[3]; - normal_tri_v3(nor, mvert[vtri[0]].co, mvert[vtri[1]].co, mvert[vtri[2]].co); - glNormal3fv(nor); - } - } - else if (lnors) { - ln1 = lnors[ltri[0]]; - ln2 = lnors[ltri[1]]; - ln3 = lnors[ltri[2]]; - } - - /* vertices */ - cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[0], ltri[0], 0, ln1, smoothnormal); - cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[1], ltri[1], 1, ln2, smoothnormal); - cddm_draw_attrib_vertex(&attribs, mvert, a, vtri[2], ltri[2], 2, ln3, smoothnormal); - } - glEnd(); -} - -static void cdDM_drawMappedEdges(DerivedMesh *dm, DMSetDrawOptions setDrawOptions, void *userData) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *) dm; - MVert *vert = cddm->mvert; - MEdge *edge = cddm->medge; - int i, orig, *index = DM_get_edge_data_layer(dm, CD_ORIGINDEX); - - glBegin(GL_LINES); - for (i = 0; i < dm->numEdgeData; i++, edge++) { - if (index) { - orig = *index++; - if (setDrawOptions && orig == ORIGINDEX_NONE) continue; - } - else - orig = i; - - if (!setDrawOptions || (setDrawOptions(userData, orig) != DM_DRAW_OPTION_SKIP)) { - glVertex3fv(vert[edge->v1].co); - glVertex3fv(vert[edge->v2].co); - } - } - glEnd(); -} - -typedef struct FaceCount { - unsigned int i_visible; - unsigned int i_hidden; - unsigned int i_tri_visible; - unsigned int i_tri_hidden; -} FaceCount; - -static void cdDM_buffer_copy_triangles( - DerivedMesh *dm, unsigned int *varray, - const int *mat_orig_to_new) -{ - GPUBufferMaterial *gpumat, *gpumaterials = dm->drawObject->materials; - int i, j, start; - - const int gpu_totmat = dm->drawObject->totmaterial; - const short dm_totmat = dm->totmat; - const MPoly *mpoly = dm->getPolyArray(dm); - const MLoopTri *lt = dm->getLoopTriArray(dm); - const int totpoly = dm->getNumPolys(dm); - - FaceCount *fc = MEM_malloc_arrayN(gpu_totmat, sizeof(*fc), "gpumaterial.facecount"); - - for (i = 0; i < gpu_totmat; i++) { - fc[i].i_visible = 0; - fc[i].i_tri_visible = 0; - fc[i].i_hidden = gpumaterials[i].totpolys - 1; - fc[i].i_tri_hidden = gpumaterials[i].totelements - 1; - } - - for (i = 0; i < totpoly; i++) { - const short mat_nr = ME_MAT_NR_TEST(mpoly[i].mat_nr, dm_totmat); - int tottri = ME_POLY_TRI_TOT(&mpoly[i]); - int mati = mat_orig_to_new[mat_nr]; - gpumat = gpumaterials + mati; - - if (mpoly[i].flag & ME_HIDE) { - for (j = 0; j < tottri; j++, lt++) { - start = gpumat->start + fc[mati].i_tri_hidden; - /* v1 v2 v3 */ - varray[start--] = lt->tri[2]; - varray[start--] = lt->tri[1]; - varray[start--] = lt->tri[0]; - fc[mati].i_tri_hidden -= 3; - } - gpumat->polys[fc[mati].i_hidden--] = i; - } - else { - for (j = 0; j < tottri; j++, lt++) { - start = gpumat->start + fc[mati].i_tri_visible; - /* v1 v2 v3 */ - varray[start++] = lt->tri[0]; - varray[start++] = lt->tri[1]; - varray[start++] = lt->tri[2]; - fc[mati].i_tri_visible += 3; - } - gpumat->polys[fc[mati].i_visible++] = i; - } - } - - /* set the visible polygons */ - for (i = 0; i < gpu_totmat; i++) { - gpumaterials[i].totvisiblepolys = fc[i].i_visible; - } - - MEM_freeN(fc); -} - -static void cdDM_buffer_copy_vertex( - DerivedMesh *dm, float *varray) -{ - const MVert *mvert; - const MPoly *mpoly; - const MLoop *mloop; - - int i, j, start, totpoly; - - mvert = dm->getVertArray(dm); - mpoly = dm->getPolyArray(dm); - mloop = dm->getLoopArray(dm); - totpoly = dm->getNumPolys(dm); - - start = 0; - - for (i = 0; i < totpoly; i++, mpoly++) { - for (j = 0; j < mpoly->totloop; j++) { - copy_v3_v3(&varray[start], mvert[mloop[mpoly->loopstart + j].v].co); - start += 3; - } - } - - /* copy loose points */ - j = dm->drawObject->tot_loop_verts * 3; - for (i = 0; i < dm->drawObject->totvert; i++) { - if (dm->drawObject->vert_points[i].point_index >= dm->drawObject->tot_loop_verts) { - copy_v3_v3(&varray[j], mvert[i].co); - j += 3; - } - } -} - -static void cdDM_buffer_copy_normal( - DerivedMesh *dm, short *varray) -{ - CDDerivedMesh *cddm = (CDDerivedMesh *)dm; - int i, j, totpoly; - int start; - - const float (*nors)[3] = dm->getPolyDataArray(dm, CD_NORMAL); - const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL); - - const MVert *mvert; - const MPoly *mpoly; - const MLoop *mloop; - - mvert = dm->getVertArray(dm); - mpoly = dm->getPolyArray(dm); - mloop = dm->getLoopArray(dm); - totpoly = dm->getNumPolys(dm); - - /* we are in sculpt mode, disable loop normals (since they won't get updated) */ - if (cddm->pbvh) - lnors = NULL; - - start = 0; - for (i = 0; i < totpoly; i++, mpoly++) { - const bool smoothnormal = (mpoly->flag & ME_SMOOTH) != 0; - - if (lnors) { - /* Copy loop normals */ - for (j = 0; j < mpoly->totloop; j++, start += 4) { - normal_float_to_short_v3(&varray[start], lnors[mpoly->loopstart + j]); - } - } - else if (smoothnormal) { - /* Copy vertex normal */ - for (j = 0; j < mpoly->totloop; j++, start += 4) { - copy_v3_v3_short(&varray[start], mvert[mloop[mpoly->loopstart + j].v].no); - } - } - else { - /* Copy cached OR calculated face normal */ - short f_no_s[3]; - - if (nors) { - normal_float_to_short_v3(f_no_s, nors[i]); - } - else { - float f_no[3]; - BKE_mesh_calc_poly_normal(mpoly, &mloop[mpoly->loopstart], mvert, f_no); - normal_float_to_short_v3(f_no_s, f_no); - } - - for (j = 0; j < mpoly->totloop; j++, start += 4) { - copy_v3_v3_short(&varray[start], f_no_s); - } - } - } -} - -static void cdDM_buffer_copy_uv( - DerivedMesh *dm, float *varray) -{ - int i, j, totpoly; - int start; - - const MPoly *mpoly; - const MLoopUV *mloopuv; - - if ((mloopuv = DM_get_loop_data_layer(dm, CD_MLOOPUV)) == NULL) { - return; - } - - mpoly = dm->getPolyArray(dm); - totpoly = dm->getNumPolys(dm); - - start = 0; - for (i = 0; i < totpoly; i++, mpoly++) { - for (j = 0; j < mpoly->totloop; j++) { - copy_v2_v2(&varray[start], mloopuv[mpoly->loopstart + j].uv); - start += 2; - } - } -} - -static void cdDM_buffer_copy_uv_texpaint( - DerivedMesh *dm, float *varray) -{ - int i, j, totpoly; - int start; - - const MPoly *mpoly; - - int totmaterial = dm->totmat; - const MLoopUV **uv_base; - const MLoopUV *uv_stencil_base; - int stencil; - - totpoly = dm->getNumPolys(dm); - - /* should have been checked for before, reassert */ - BLI_assert(DM_get_loop_data_layer(dm, CD_MLOOPUV)); - uv_base = MEM_malloc_arrayN(totmaterial, sizeof(*uv_base), "texslots"); - - for (i = 0; i < totmaterial; i++) { - uv_base[i] = DM_paint_uvlayer_active_get(dm, i); - } - - stencil = CustomData_get_stencil_layer(&dm->loopData, CD_MLOOPUV); - uv_stencil_base = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, stencil); - - mpoly = dm->getPolyArray(dm); - start = 0; - - for (i = 0; i < totpoly; i++, mpoly++) { - int mat_i = mpoly->mat_nr; - - for (j = 0; j < mpoly->totloop; j++) { - copy_v2_v2(&varray[start], uv_base[mat_i][mpoly->loopstart + j].uv); - copy_v2_v2(&varray[start + 2], uv_stencil_base[mpoly->loopstart + j].uv); - start += 4; - } - } - - MEM_freeN((void *)uv_base); -} - -/* treat varray_ as an array of MCol, four MCol's per face */ -static void cdDM_buffer_copy_mcol( - DerivedMesh *dm, unsigned char *varray, - const void *user_data) -{ - int i, j, totpoly; - int start; - - const MLoopCol *mloopcol = user_data; - const MPoly *mpoly = dm->getPolyArray(dm); - - totpoly = dm->getNumPolys(dm); - - start = 0; - - for (i = 0; i < totpoly; i++, mpoly++) { - for (j = 0; j < mpoly->totloop; j++) { - copy_v4_v4_uchar(&varray[start], &mloopcol[mpoly->loopstart + j].r); - start += 4; - } - } -} - -static void cdDM_buffer_copy_edge( - DerivedMesh *dm, unsigned int *varray) -{ - MEdge *medge, *medge_base; - int i, totedge, iloose, inorm, iloosehidden, inormhidden; - int tot_loose_hidden = 0, tot_loose = 0; - int tot_hidden = 0, tot = 0; - - medge_base = medge = dm->getEdgeArray(dm); - totedge = dm->getNumEdges(dm); - - for (i = 0; i < totedge; i++, medge++) { - if (medge->flag & ME_EDGEDRAW) { - if (medge->flag & ME_LOOSEEDGE) tot_loose++; - else tot++; - } - else { - if (medge->flag & ME_LOOSEEDGE) tot_loose_hidden++; - else tot_hidden++; - } - } - - inorm = 0; - inormhidden = tot; - iloose = tot + tot_hidden; - iloosehidden = iloose + tot_loose; - - medge = medge_base; - for (i = 0; i < totedge; i++, medge++) { - if (medge->flag & ME_EDGEDRAW) { - if (medge->flag & ME_LOOSEEDGE) { - varray[iloose * 2] = dm->drawObject->vert_points[medge->v1].point_index; - varray[iloose * 2 + 1] = dm->drawObject->vert_points[medge->v2].point_index; - iloose++; - } - else { - varray[inorm * 2] = dm->drawObject->vert_points[medge->v1].point_index; - varray[inorm * 2 + 1] = dm->drawObject->vert_points[medge->v2].point_index; - inorm++; - } - } - else { - if (medge->flag & ME_LOOSEEDGE) { - varray[iloosehidden * 2] = dm->drawObject->vert_points[medge->v1].point_index; - varray[iloosehidden * 2 + 1] = dm->drawObject->vert_points[medge->v2].point_index; - iloosehidden++; - } - else { - varray[inormhidden * 2] = dm->drawObject->vert_points[medge->v1].point_index; - varray[inormhidden * 2 + 1] = dm->drawObject->vert_points[medge->v2].point_index; - inormhidden++; - } - } - } - - dm->drawObject->tot_loose_edge_drawn = tot_loose; - dm->drawObject->loose_edge_offset = tot + tot_hidden; - dm->drawObject->tot_edge_drawn = tot; -} - -static void cdDM_buffer_copy_uvedge( - DerivedMesh *dm, float *varray) -{ - int i, j, totpoly; - int start; - const MLoopUV *mloopuv; - const MPoly *mpoly = dm->getPolyArray(dm); - - if ((mloopuv = DM_get_loop_data_layer(dm, CD_MLOOPUV)) == NULL) { - return; - } - - totpoly = dm->getNumPolys(dm); - start = 0; - - for (i = 0; i < totpoly; i++, mpoly++) { - for (j = 0; j < mpoly->totloop; j++) { - copy_v2_v2(&varray[start], mloopuv[mpoly->loopstart + j].uv); - copy_v2_v2(&varray[start + 2], mloopuv[mpoly->loopstart + (j + 1) % mpoly->totloop].uv); - start += 4; - } - } -} - -static void cdDM_copy_gpu_data( - DerivedMesh *dm, int type, void *varray_p, - const int *mat_orig_to_new, const void *user_data) -{ - /* 'varray_p' cast is redundant but include for self-documentation */ - switch (type) { - case GPU_BUFFER_VERTEX: - cdDM_buffer_copy_vertex(dm, (float *)varray_p); - break; - case GPU_BUFFER_NORMAL: - cdDM_buffer_copy_normal(dm, (short *)varray_p); - break; - case GPU_BUFFER_COLOR: - cdDM_buffer_copy_mcol(dm, (unsigned char *)varray_p, user_data); - break; - case GPU_BUFFER_UV: - cdDM_buffer_copy_uv(dm, (float *)varray_p); - break; - case GPU_BUFFER_UV_TEXPAINT: - cdDM_buffer_copy_uv_texpaint(dm, (float *)varray_p); - break; - case GPU_BUFFER_EDGE: - cdDM_buffer_copy_edge(dm, (unsigned int *)varray_p); - break; - case GPU_BUFFER_UVEDGE: - cdDM_buffer_copy_uvedge(dm, (float *)varray_p); - break; - case GPU_BUFFER_TRIANGLES: - cdDM_buffer_copy_triangles(dm, (unsigned int *)varray_p, mat_orig_to_new); - break; - default: - break; - } -} - -/* add a new point to the list of points related to a particular - * vertex */ -#ifdef USE_GPU_POINT_LINK - -static void cdDM_drawobject_add_vert_point(GPUDrawObject *gdo, int vert_index, int point_index) -{ - GPUVertPointLink *lnk; - - lnk = &gdo->vert_points[vert_index]; - - /* if first link is in use, add a new link at the end */ - if (lnk->point_index != -1) { - /* get last link */ - for (; lnk->next; lnk = lnk->next) ; - - /* add a new link from the pool */ - lnk = lnk->next = &gdo->vert_points_mem[gdo->vert_points_usage]; - gdo->vert_points_usage++; - } - - lnk->point_index = point_index; -} - -#else - -static void cdDM_drawobject_add_vert_point(GPUDrawObject *gdo, int vert_index, int point_index) -{ - GPUVertPointLink *lnk; - lnk = &gdo->vert_points[vert_index]; - if (lnk->point_index == -1) { - lnk->point_index = point_index; - } -} - -#endif /* USE_GPU_POINT_LINK */ - -/* for each vertex, build a list of points related to it; these lists - * are stored in an array sized to the number of vertices */ -static void cdDM_drawobject_init_vert_points( - GPUDrawObject *gdo, - const MPoly *mpoly, const MLoop *mloop, - int tot_poly) -{ - int i; - int tot_loops = 0; - - /* allocate the array and space for links */ - gdo->vert_points = MEM_malloc_arrayN(gdo->totvert, sizeof(GPUVertPointLink), - "GPUDrawObject.vert_points"); -#ifdef USE_GPU_POINT_LINK - gdo->vert_points_mem = MEM_calloc_arrayN(gdo->totvert, sizeof(GPUVertPointLink), - "GPUDrawObject.vert_points_mem"); - gdo->vert_points_usage = 0; -#endif - - /* -1 indicates the link is not yet used */ - for (i = 0; i < gdo->totvert; i++) { -#ifdef USE_GPU_POINT_LINK - gdo->vert_points[i].link = NULL; -#endif - gdo->vert_points[i].point_index = -1; - } - - for (i = 0; i < tot_poly; i++) { - int j; - const MPoly *mp = &mpoly[i]; - - /* assign unique indices to vertices of the mesh */ - for (j = 0; j < mp->totloop; j++) { - cdDM_drawobject_add_vert_point(gdo, mloop[mp->loopstart + j].v, tot_loops + j); - } - tot_loops += mp->totloop; - } - - /* map any unused vertices to loose points */ - for (i = 0; i < gdo->totvert; i++) { - if (gdo->vert_points[i].point_index == -1) { - gdo->vert_points[i].point_index = gdo->tot_loop_verts + gdo->tot_loose_point; - gdo->tot_loose_point++; - } - } -} - -/* see GPUDrawObject's structure definition for a description of the - * data being initialized here */ -static GPUDrawObject *cdDM_GPUobject_new(DerivedMesh *dm) -{ - GPUDrawObject *gdo; - const MPoly *mpoly; - const MLoop *mloop; - const short dm_totmat = dm->totmat; - GPUBufferMaterial *mat_info; - int i, totloops, totpolys; - - /* object contains at least one material (default included) so zero means uninitialized dm */ - BLI_assert(dm_totmat != 0); - - mpoly = dm->getPolyArray(dm); - mloop = dm->getLoopArray(dm); - - totpolys = dm->getNumPolys(dm); - totloops = dm->getNumLoops(dm); - - /* get the number of points used by each material, treating - * each quad as two triangles */ - mat_info = MEM_calloc_arrayN(dm_totmat, sizeof(*mat_info), "GPU_drawobject_new.mat_orig_to_new"); - - for (i = 0; i < totpolys; i++) { - const short mat_nr = ME_MAT_NR_TEST(mpoly[i].mat_nr, dm_totmat); - mat_info[mat_nr].totpolys++; - mat_info[mat_nr].totelements += 3 * ME_POLY_TRI_TOT(&mpoly[i]); - mat_info[mat_nr].totloops += mpoly[i].totloop; - } - /* create the GPUDrawObject */ - gdo = MEM_callocN(sizeof(GPUDrawObject), "GPUDrawObject"); - gdo->totvert = dm->getNumVerts(dm); - gdo->totedge = dm->getNumEdges(dm); - - GPU_buffer_material_finalize(gdo, mat_info, dm_totmat); - - gdo->tot_loop_verts = totloops; - - /* store total number of points used for triangles */ - gdo->tot_triangle_point = poly_to_tri_count(totpolys, totloops) * 3; - - cdDM_drawobject_init_vert_points(gdo, mpoly, mloop, totpolys); - - return gdo; -} - static void cdDM_foreachMappedVert( DerivedMesh *dm, void (*func)(void *userData, int index, const float co[3], const float no_f[3], const short no_s[3]), @@ -1913,7 +463,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) @@ -2005,24 +555,6 @@ static CDDerivedMesh *cdDM_create(const char *desc) dm->getPBVH = cdDM_getPBVH; dm->getPolyMap = cdDM_getPolyMap; - 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; - - dm->gpuObjectNew = cdDM_GPUobject_new; - dm->copy_gpu_data = cdDM_copy_gpu_data; - dm->foreachMappedVert = cdDM_foreachMappedVert; dm->foreachMappedEdge = cdDM_foreachMappedEdge; dm->foreachMappedLoop = cdDM_foreachMappedLoop; @@ -2062,10 +594,14 @@ DerivedMesh *CDDM_new(int numVerts, int numEdges, int numTessFaces, int numLoops DerivedMesh *CDDM_from_mesh(Mesh *mesh) { + return CDDM_from_mesh_ex(mesh, CD_REFERENCE); +} + +DerivedMesh *CDDM_from_mesh_ex(Mesh *mesh, int alloctype) +{ CDDerivedMesh *cddm = cdDM_create(__func__); DerivedMesh *dm = &cddm->dm; CustomDataMask mask = CD_MASK_MESH & (~CD_MASK_MDISPS); - int alloctype; /* this does a referenced copy, with an exception for fluidsim */ @@ -2075,8 +611,6 @@ DerivedMesh *CDDM_from_mesh(Mesh *mesh) dm->deformedOnly = 1; dm->cd_flag = mesh->cd_flag; - alloctype = CD_REFERENCE; - CustomData_merge(&mesh->vdata, &dm->vertData, mask, alloctype, mesh->totvert); CustomData_merge(&mesh->edata, &dm->edgeData, mask, alloctype, @@ -2153,7 +687,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 +701,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 +766,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 +796,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 +868,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); } } @@ -2772,7 +1301,8 @@ void CDDM_calc_normals_tessface(DerivedMesh *dm) } #if 1 - +/* TODO(sybren): Delete everything in this #if block after we have ported the modifiers + * to use Mesh instead of DerivedMesh. The code has been copied to mesh_merge.c and ported. */ /** * Poly compare with vtargetmap * Function used by #CDDM_merge_verts. @@ -2950,7 +1480,7 @@ static bool poly_gset_compare_fn(const void *k1, const void *k2) * \param vtargetmap The table that maps vertices to target vertices. a value of -1 * indicates a vertex is a target, and is to be kept. * This array is aligned with 'dm->numVertData' - * \warning \a vtergatmap must **not** contain any chained mapping (v1 -> v2 -> v3 etc.), this is not supported + * \warning \a vtargetmap must **not** contain any chained mapping (v1 -> v2 -> v3 etc.), this is not supported * and will likely generate corrupted geometry. * * \param tot_vtargetmap The number of non '-1' values in vtargetmap. (not the size) @@ -2974,6 +1504,7 @@ static bool poly_gset_compare_fn(const void *k1, const void *k2) */ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap, const int tot_vtargetmap, const int merge_mode) { +// This was commented out back in 2013, see commit f45d8827bafe6b9eaf9de42f4054e9d84a21955d. // #define USE_LOOPS CDDerivedMesh *cddm = (CDDerivedMesh *)dm; CDDerivedMesh *cddm2 = NULL; diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c index 9ae295e2e3b..976b8965fa2 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" @@ -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(struct Depsgraph *depsgraph, 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(depsgraph, 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, struct Depsgraph *depsgraph, Scene *scene, Object *ob, DerivedMesh *dm, float (*vertexCos)[3]) { PointCache *cache; PTCacheID pid; @@ -479,9 +481,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 */ if (cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0)) BKE_ptcache_write(&pid, startframe); @@ -491,7 +490,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(depsgraph, ob, clmd, dm, framenr)) { BKE_ptcache_invalidate(cache); } else @@ -923,7 +922,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) @@ -1505,6 +1504,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..15fda8a9786 --- /dev/null +++ b/source/blender/blenkernel/intern/collection.c @@ -0,0 +1,1014 @@ +/* + * ***** 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; + } +} + +/** + * The automatic/fallback name of a new collection. + */ +void BKE_collection_new_name_get(ID *owner_id, SceneCollection *sc_parent, char *rname) +{ + SceneCollection *sc_master = collection_master_from_id(owner_id); + char *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_strncpy(rname, name, MAX_NAME); + MEM_freeN(name); +} + +/** + * 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; + char name[MAX_NAME]; + + if (!sc_parent) { + sc_parent = sc_master; + } + + if (name_custom != NULL) { + BLI_strncpy(name, name_custom, MAX_NAME); + } + else { + BKE_collection_new_name_get(owner_id, sc_parent, name); + } + + BLI_addtail(&sc_parent->scene_collections, sc); + BKE_collection_rename(owner_id, sc, 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_BEGIN(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 ID *owner_id, SceneCollection *sc, const char *name) +{ + collection_rename(owner_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 (BKE_collection_object_exists(sc, ob)) { + /* 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_BEGIN(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; +} + +/** + * Remove object from all collections of scene + * \param scene_collection_skip: Don't remove base from this collection. + */ +static bool collections_object_remove_ex(Main *bmain, ID *owner_id, Object *ob, const bool free_us, + SceneCollection *scene_collection_skip) +{ + 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_BEGIN(owner_id, sc) + { + if (sc != scene_collection_skip) { + removed |= BKE_collection_object_remove(bmain, owner_id, sc, ob, free_us); + } + } + FOREACH_SCENE_COLLECTION_END; + return removed; +} + +/** + * Remove object from all collections of scene + */ +bool BKE_collections_object_remove(Main *bmain, ID *owner_id, Object *ob, const bool free_us) +{ + return collections_object_remove_ex(bmain, owner_id, ob, free_us, NULL); +} + +/** + * Move object from a collection into another + * + * If source collection is NULL move it from all the existing collections. + */ +void BKE_collection_object_move(ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src, Object *ob) +{ + /* In both cases we first add the object, then remove it from the other collections. + * Otherwise we lose the original base and whether it was active and selected. */ + if (sc_src != NULL) { + if (BKE_collection_object_add(owner_id, sc_dst, ob)) { + BKE_collection_object_remove(NULL, owner_id, sc_src, ob, false); + } + } + else { + /* Adding will fail if object is already in collection. + * However we still need to remove it from the other collections. */ + BKE_collection_object_add(owner_id, sc_dst, ob); + collections_object_remove_ex(NULL, owner_id, ob, false, sc_dst); + } +} + +/** + * Whether the object is directly inside the collection. + */ +bool BKE_collection_object_exists(struct SceneCollection *scene_collection, struct Object *ob) +{ + if (BLI_findptr(&scene_collection->objects, ob, offsetof(LinkData, data))) { + return true; + } + return false; +} + +static SceneCollection *scene_collection_from_index_recursive(SceneCollection *scene_collection, const int index, int *index_current) +{ + if (index == (*index_current)) { + return scene_collection; + } + + (*index_current)++; + + for (SceneCollection *scene_collection_iter = scene_collection->scene_collections.first; + scene_collection_iter != NULL; + scene_collection_iter = scene_collection_iter->next) + { + SceneCollection *nested = scene_collection_from_index_recursive(scene_collection_iter, index, index_current); + if (nested != NULL) { + return nested; + } + } + return NULL; +} + +/** + * Return Scene Collection for a given index. + * + * The index is calculated from top to bottom counting the children before the siblings. + */ +SceneCollection *BKE_collection_from_index(Scene *scene, const int index) +{ + int index_current = 0; + SceneCollection *master_collection = BKE_collection_master(&scene->id); + return scene_collection_from_index_recursive(master_collection, index, &index_current); +} + +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); + } +} + +/** + * Select all the objects in this SceneCollection (and its nested collections) for this ViewLayer. + * Return true if any object was selected. + */ +bool BKE_collection_objects_select(ViewLayer *view_layer, SceneCollection *scene_collection) +{ + LayerCollection *layer_collection = BKE_layer_collection_first_from_scene_collection(view_layer, scene_collection); + if (layer_collection != NULL) { + BKE_layer_collection_objects_select(layer_collection); + return true; + } + else { + /* Slower approach, we need to iterate over all the objects and for each one we see if there is a base. */ + bool changed = false; + for (LinkData *link = scene_collection->objects.first; link; link = link->next) { + Base *base = BKE_view_layer_base_find(view_layer, link->data); + if (base != NULL) { + if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) { + base->flag |= BASE_SELECTED; + changed = true; + } + } + } + return changed; + } +} + +/** + * 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_BEGIN(&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 65742df754e..ee3c38b9282 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_BEGIN(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_BEGIN(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_BEGIN(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_BEGIN(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 4689de825b2..b192cb7cef2 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(struct Depsgraph *UNUSED(depsgraph), 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(struct Depsgraph *UNUSED(depsgraph), 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(struct Depsgraph *UNUSED(depsgraph), + 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 */ @@ -2028,21 +2019,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(struct Depsgraph *UNUSED(depsgraph), + 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 @@ -2146,7 +2135,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(struct Depsgraph *UNUSED(depsgraph), bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) { bActionConstraint *data = con->data; @@ -3039,66 +3028,6 @@ static bConstraintTypeInfo CTI_MINMAX = { minmax_evaluate /* evaluate */ }; -/* ------- RigidBody Joint ---------- */ - -static void rbj_new_data(void *cdata) -{ - bRigidBodyJointConstraint *data = (bRigidBodyJointConstraint *)cdata; - - /* removed code which set target of this constraint */ - data->type = 1; -} - -static void rbj_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata) -{ - bRigidBodyJointConstraint *data = con->data; - - /* target only */ - func(con, (ID **)&data->tar, false, userdata); - func(con, (ID **)&data->child, false, userdata); -} - -static int rbj_get_tars(bConstraint *con, ListBase *list) -{ - if (con && list) { - bRigidBodyJointConstraint *data = con->data; - bConstraintTarget *ct; - - /* standard target-getting macro for single-target constraints without subtargets */ - SINGLETARGETNS_GET_TARS(con, data->tar, ct, list); - - return 1; - } - - return 0; -} - -static void rbj_flush_tars(bConstraint *con, ListBase *list, bool no_copy) -{ - if (con && list) { - bRigidBodyJointConstraint *data = con->data; - bConstraintTarget *ct = list->first; - - /* the following macro is used for all standard single-target constraints */ - SINGLETARGETNS_FLUSH_TARS(con, data->tar, ct, list, no_copy); - } -} - -static bConstraintTypeInfo CTI_RIGIDBODYJOINT = { - CONSTRAINT_TYPE_RIGIDBODYJOINT, /* type */ - sizeof(bRigidBodyJointConstraint), /* size */ - "Rigid Body Joint", /* name */ - "bRigidBodyJointConstraint", /* struct name */ - NULL, /* free data */ - rbj_id_looper, /* id looper */ - NULL, /* copy data */ - rbj_new_data, /* new data */ - rbj_get_tars, /* get constraint targets */ - rbj_flush_tars, /* flush constraint targets */ - default_get_tarmat, /* get target matrix */ - NULL /* evaluate - this is not solved here... is just an interface for game-engine */ -}; - /* -------- Clamp To ---------- */ static void clampto_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata) @@ -3135,16 +3064,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(struct Depsgraph *UNUSED(depsgraph), + 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... */ @@ -3478,7 +3401,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(struct Depsgraph *UNUSED(depsgraph), bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime)) { bShrinkwrapConstraint *scon = (bShrinkwrapConstraint *) con->data; @@ -3810,16 +3733,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(struct Depsgraph *UNUSED(depsgraph), + 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... */ @@ -4461,7 +4378,7 @@ static void constraints_init_typeinfo(void) constraintsTypeInfo[14] = &CTI_DISTLIMIT; /* Limit Distance Constraint */ constraintsTypeInfo[15] = &CTI_STRETCHTO; /* StretchTo Constaint */ constraintsTypeInfo[16] = &CTI_MINMAX; /* Floor Constraint */ - constraintsTypeInfo[17] = &CTI_RIGIDBODYJOINT; /* RigidBody Constraint */ + /* constraintsTypeInfo[17] = &CTI_RIGIDBODYJOINT; */ /* RigidBody Constraint - Deprecated */ constraintsTypeInfo[18] = &CTI_CLAMPTO; /* ClampTo Constraint */ constraintsTypeInfo[19] = &CTI_TRANSFORM; /* Transformation Constraint */ constraintsTypeInfo[20] = &CTI_SHRINKWRAP; /* Shrinkwrap Constraint */ @@ -4868,7 +4785,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(struct Depsgraph *depsgraph, 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}; @@ -4919,7 +4836,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(depsgraph, con, cob, ct, ctime); copy_m4_m4(mat, ct->matrix); } @@ -4935,7 +4852,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(struct Depsgraph *depsgraph, bConstraint *con, bConstraintOb *cob, ListBase *targets, float ctime) { const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con); @@ -4953,7 +4870,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(depsgraph, con, cob, ct, ctime); } else { for (ct = targets->first; ct; ct = ct->next) @@ -4970,7 +4887,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(struct Depsgraph *depsgraph, ListBase *conlist, bConstraintOb *cob, float ctime) { bConstraint *con; float oldmat[4][4]; @@ -5005,7 +4922,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(depsgraph, 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..f420fd974cd 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) @@ -750,14 +775,6 @@ struct SpaceNla *CTX_wm_space_nla(const bContext *C) return NULL; } -struct SpaceTime *CTX_wm_space_time(const bContext *C) -{ - ScrArea *sa = CTX_wm_area(C); - if (sa && sa->spacetype == SPACE_TIME) - return sa->spacedata.first; - return NULL; -} - struct SpaceNode *CTX_wm_space_node(const bContext *C) { ScrArea *sa = CTX_wm_area(C); @@ -766,14 +783,6 @@ struct SpaceNode *CTX_wm_space_node(const bContext *C) return NULL; } -struct SpaceLogic *CTX_wm_space_logic(const bContext *C) -{ - ScrArea *sa = CTX_wm_area(C); - if (sa && sa->spacetype == SPACE_LOGIC) - return sa->spacedata.first; - return NULL; -} - struct SpaceIpo *CTX_wm_space_graph(const bContext *C) { ScrArea *sa = CTX_wm_area(C); @@ -814,6 +823,14 @@ struct SpaceClip *CTX_wm_space_clip(const bContext *C) return NULL; } +struct SpaceTopBar *CTX_wm_space_topbar(const bContext *C) +{ + ScrArea *sa = CTX_wm_area(C); + if (sa && sa->spacetype == SPACE_TOPBAR) + return sa->spacedata.first; + return NULL; +} + void CTX_wm_manager_set(bContext *C, wmWindowManager *wm) { C->wm.manager = wm; @@ -826,9 +843,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 +855,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 +875,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 +918,66 @@ 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)); + } +} + +RenderEngineType *CTX_data_engine_type(const bContext *C) +{ + Scene *scene = CTX_data_scene(C); + return RE_engines_find(scene->r.engine); +} + +/** + * 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 +997,26 @@ 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) +{ + Object *obedit = CTX_data_edit_object(C); + Object *obact = obedit ? NULL : CTX_data_active_object(C); + return CTX_data_mode_enum_ex(obedit, obact, obact ? obact->mode : OB_MODE_OBJECT); +} /* would prefer if we can use the enum version below over this one - Campbell */ /* must be aligned with above enum */ @@ -954,6 +1037,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 +1238,16 @@ 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); +} + +Depsgraph *CTX_data_depsgraph_on_load(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, false); +} diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c index 56df8e51eba..0a31411d638 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( + struct Depsgraph *depsgraph, 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(depsgraph, 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(depsgraph, 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( + struct Depsgraph *depsgraph, Scene *scene, Object *ob, BMEditMesh *em, + float (**deformmats)[3][3], float (**deformcos)[3]) { ModifierData *md; DerivedMesh *dm; @@ -259,6 +261,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(Scene *scene, Object *ob, int cageIndex = modifiers_getCageIndex(scene, ob, NULL, 1); float (*defmats)[3][3] = NULL, (*deformedVerts)[3] = NULL; VirtualModifierData virtualModifierData; + ModifierEvalContext mectx = {depsgraph, ob, 0}; modifiers_clearErrors(ob); @@ -274,7 +277,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(Scene *scene, Object *ob, if (!editbmesh_modifier_is_enabled(scene, md, dm)) continue; - if (mti->type == eModifierTypeType_OnlyDeform && mti->deformMatricesEM) { + if (mti->type == eModifierTypeType_OnlyDeform && (mti->deformMatricesEM || mti->deformMatricesEM_DM)) { if (!defmats) { const int required_mode = eModifierMode_Realtime | eModifierMode_Editmode; CustomDataMask data_mask = CD_MASK_BAREMESH; @@ -290,8 +293,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, - numVerts); + modifier_deformMatricesEM_DM_deprecated(md, &mectx, em, dm, deformedVerts, defmats, numVerts); } else break; @@ -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( + struct Depsgraph *depsgraph, Scene *scene, + Object *ob, float (**deformmats)[3][3], float (**deformcos)[3]) { ModifierData *md; DerivedMesh *dm; @@ -320,6 +324,7 @@ int BKE_sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**defo const bool has_multires = mmd != NULL && mmd->sculptlvl > 0; int numleft = 0; VirtualModifierData virtualModifierData; + ModifierEvalContext mectx = {depsgraph, ob, 0}; if (has_multires) { *deformmats = NULL; @@ -346,7 +351,9 @@ 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_DM) { + modifier_deformMatrices_DM_deprecated(md, &mectx, dm, deformedVerts, defmats, numVerts); + } else break; } } @@ -369,9 +376,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(struct Depsgraph *depsgraph, 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(depsgraph, scene, ob, deformmats, deformcos); if (totleft) { /* there are deformation modifier which doesn't support deformation matrices @@ -383,6 +390,7 @@ void BKE_crazyspace_build_sculpt(Scene *scene, Object *ob, float (**deformmats)[ int i, deformed = 0; VirtualModifierData virtualModifierData; ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); + ModifierEvalContext mectx = {depsgraph, ob, 0}; Mesh *me = (Mesh *)ob->data; for (; md; md = md->next) { @@ -393,10 +401,10 @@ void BKE_crazyspace_build_sculpt(Scene *scene, Object *ob, float (**deformmats)[ if (mti->type == eModifierTypeType_OnlyDeform) { /* skip leading modifiers which have been already * handled in sculpt_get_first_deform_matrices */ - if (mti->deformMatrices && !deformed) + if ((mti->deformMatrices || mti->deformMatrices_DM) && !deformed) continue; - mti->deformVerts(md, ob, NULL, deformedVerts, me->totvert, 0); + modifier_deformVerts_DM_deprecated(md, &mectx, NULL, deformedVerts, me->totvert); deformed = 1; } } diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 943cab0a9fc..cea5685a7a1 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" @@ -129,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); @@ -209,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); @@ -1622,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(Depsgraph *depsgraph, Scene *scene, Object *ob, int *r_numVerts) { Curve *cu = ob->data; DispList *dl; @@ -1630,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(depsgraph, scene, ob, &disp); numVerts = 0; for (dl = disp.first; dl; dl = dl->next) { @@ -1721,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( + Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *disp, + const bool for_render, const bool use_render_resolution) { DispList *dl, *dlnew; Curve *bevcu, *cu; @@ -1746,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(depsgraph, scene, cu->bevobj, &bevdisp, NULL, false, use_render_resolution); dl = bevdisp.first; } else if (cu->bevobj->curve_cache) { @@ -5185,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 { @@ -5252,11 +5255,28 @@ 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(Depsgraph *depsgraph, Curve *curve) { - DEG_debug_print_eval(__func__, curve->id.name, curve); + DEG_debug_print_eval(depsgraph, __func__, curve->id.name, curve); if (curve->bb == NULL || (curve->bb->flag & BOUNDBOX_DIRTY)) { 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 38340575e74..0451031c5b8 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, + struct Depsgraph *depsgraph, 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(depsgraph, 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, + struct Depsgraph *depsgraph, 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(depsgraph, 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, + struct Depsgraph *depsgraph, 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, + depsgraph, 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 c29dc6c9311..00000000000 --- a/source/blender/blenkernel/intern/depsgraph.c +++ /dev/null @@ -1,3745 +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, 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; - ModifierUpdateDepsgraphContext ctx = { - .scene = scene, - .object = ob, - - .forest = dag, - .obNode = node, - }; - for (md = ob->modifiers.first; md; md = md->next) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); - - if (mti->updateDepgraph) mti->updateDepgraph(md, &ctx); - } - } - 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, 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, sce, ob, mask); - if (ob->proxy) - build_dag_object(dag, scenenode, 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, sce, ob, mask); - if (ob->proxy) - build_dag_object(dag, scenenode, 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_TAG) { - 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 8433634f749..fa996b8f73e 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) @@ -679,7 +681,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(Depsgraph *depsgraph, Scene *scene, Object *taperobj, float fac) { DispList *dl; @@ -688,7 +690,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(depsgraph, scene, taperobj, 0); dl = taperobj->curve_cache->disp.first; } if (dl) { @@ -719,14 +721,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(Depsgraph *depsgraph, 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(depsgraph, scene, taperobj, fac); } -void BKE_displist_make_mball(EvaluationContext *eval_ctx, Scene *scene, Object *ob) +void BKE_displist_make_mball(Depsgraph *depsgraph, Scene *scene, Object *ob) { if (!ob || ob->type != OB_MBALL) return; @@ -739,7 +741,7 @@ void BKE_displist_make_mball(EvaluationContext *eval_ctx, Scene *scene, Object * ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for MBall"); } - BKE_mball_polygonize(eval_ctx, scene, ob, &ob->curve_cache->disp); + BKE_mball_polygonize(depsgraph, scene, ob, &ob->curve_cache->disp); BKE_mball_texspace_calc(ob); object_deform_mball(ob, &ob->curve_cache->disp); @@ -749,9 +751,9 @@ 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(Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *dispbase) { - BKE_mball_polygonize(eval_ctx, scene, ob, dispbase); + BKE_mball_polygonize(depsgraph, scene, ob, dispbase); BKE_mball_texspace_calc(ob); object_deform_mball(ob, dispbase); @@ -799,8 +801,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( + Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *nurb, + const bool for_render, const bool use_render_resolution) { VirtualModifierData virtualModifierData; ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); @@ -824,6 +827,8 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, ListBase *nurb, else required_mode = eModifierMode_Realtime; + const ModifierEvalContext mectx = {depsgraph, ob, app_flag}; + pretessellatePoint = curve_get_tessellate_point(scene, ob, use_render_resolution, editmode); if (editmode) @@ -857,7 +862,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); + modifier_deformVerts_DM_deprecated(md, &mectx, NULL, deformedVerts, numVerts); if (md == pretessellatePoint) break; @@ -909,9 +914,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( + Depsgraph *depsgraph, 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); @@ -931,6 +937,11 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *nurb, else required_mode = eModifierMode_Realtime; + const ModifierEvalContext mectx_deform = {depsgraph, ob, + editmode ? app_flag | MOD_APPLY_USECACHE : app_flag}; + const ModifierEvalContext mectx_apply = {depsgraph, ob, + useCache ? app_flag | MOD_APPLY_USECACHE : app_flag}; + pretessellatePoint = curve_get_tessellate_point(scene, ob, use_render_resolution, editmode); if (editmode) @@ -946,8 +957,6 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *nurb, for (; md; md = md->next) { const ModifierTypeInfo *mti = modifierType_getInfo(md->type); - ModifierApplyFlag appf = app_flag; - md->scene = scene; if (!modifier_isEnabled(scene, md, required_mode)) @@ -956,8 +965,6 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *nurb, if (mti->type == eModifierTypeType_OnlyDeform || (mti->type == eModifierTypeType_DeformOrConstruct && !dm)) { - if (editmode) - appf |= MOD_APPLY_USECACHE; if (dm) { if (!vertCos) { totvert = dm->getNumVerts(dm); @@ -965,14 +972,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); + modifier_deformVerts_DM_deprecated(md, &mectx_deform, dm, vertCos, totvert); } else { if (!vertCos) { vertCos = displist_get_allverts(dispbase, &totvert); } - mti->deformVerts(md, ob, NULL, vertCos, totvert, appf); + modifier_deformVerts_DM_deprecated(md, &mectx_deform, NULL, vertCos, totvert); } } else { @@ -1011,10 +1018,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *nurb, vertCos = NULL; } - if (useCache) - appf |= MOD_APPLY_USECACHE; - - ndm = modwrap_applyModifier(md, ob, dm, appf); + ndm = modwrap_applyModifier(md, &mectx_apply, dm); if (ndm) { /* Modifier returned a new derived mesh */ @@ -1091,13 +1095,13 @@ static void displist_surf_indices(DispList *dl) } } -static DerivedMesh *create_orco_dm(Scene *scene, Object *ob) +static DerivedMesh *create_orco_dm(Depsgraph *depsgraph, 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(depsgraph, scene, ob, &disp); dm = CDDM_from_curve_displist(ob, &disp); BKE_displist_free(&disp); @@ -1135,8 +1139,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( + Depsgraph *depsgraph, 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 @@ -1157,6 +1162,8 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *dm_final, else required_mode = eModifierMode_Realtime; + const ModifierEvalContext mectx = {depsgraph, ob, app_flag}; + pretessellatePoint = curve_get_tessellate_point(scene, ob, use_render_resolution, editmode); if (editmode) @@ -1173,7 +1180,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(depsgraph, scene, ob); for (; md; md = md->next) { const ModifierTypeInfo *mti = modifierType_getInfo(md->type); @@ -1185,7 +1192,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, &mectx, orcodm); if (ndm) { /* if the modifier returned a new dm, release the old one */ @@ -1202,9 +1209,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( + Depsgraph *depsgraph, 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; @@ -1221,7 +1229,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(depsgraph, 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)) { @@ -1288,7 +1296,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(depsgraph, scene, ob, &nubase, dispbase, r_dm_final, for_render, use_render_resolution); } @@ -1514,9 +1522,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( + Depsgraph *depsgraph, 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; @@ -1524,7 +1533,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(depsgraph, scene, ob, dispbase, r_dm_final, for_render, for_orco, use_render_resolution); } else if (ELEM(ob->type, OB_CURVE, OB_FONT)) { ListBase dlbev; @@ -1549,12 +1558,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(depsgraph, 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(depsgraph, scene, ob, &dlbev, for_render, use_render_resolution); /* no bevel or extrude, and no width correction? */ if (!dlbev.first && cu->width == 1.0f) { @@ -1689,7 +1698,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(depsgraph, scene, cu->taperobj, taper_fac); } if (bevp->split_tag) { @@ -1742,7 +1751,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(depsgraph, &ob->id) & DAG_EVAL_NEED_CURVE_PATH) { calc_curvepath(ob, &nubase); } @@ -1750,7 +1759,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(depsgraph, scene, ob, &nubase, dispbase, r_dm_final, for_render, use_render_resolution); } if (cu->flag & CU_DEFORM_FILL && !ob->derivedFinal) { @@ -1761,7 +1770,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(Depsgraph *depsgraph, Scene *scene, Object *ob, const bool for_orco) { ListBase *dispbase; @@ -1779,35 +1788,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(depsgraph, 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( + Depsgraph *depsgraph, 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(depsgraph, 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( + Depsgraph *depsgraph, 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(depsgraph, 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( + Depsgraph *depsgraph, Scene *scene, Object *ob, DerivedMesh *dm_final, + const bool for_render, + const bool use_render_resolution) { float *orco; @@ -1815,7 +1827,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(depsgraph, 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 3a70a4233b8..187edd5b4a5 100644 --- a/source/blender/blenkernel/intern/dynamicpaint.c +++ b/source/blender/blenkernel/intern/dynamicpaint.c @@ -74,6 +74,9 @@ #include "BKE_pointcache.h" #include "BKE_scene.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + /* for image output */ #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -486,36 +489,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; @@ -537,11 +531,6 @@ static int surface_getBrushFlags(DynamicPaintSurface *surface, const Scene *scen return flags; } -static int brush_usesMaterial(const DynamicPaintBrushSettings *brush, const Scene *scene) -{ - return ((brush->flags & MOD_DPAINT_USE_MATERIAL) && (!BKE_scene_use_new_shading_nodes(scene))); -} - /* check whether two bounds intersect */ static bool boundsIntersect(Bounds3D *b1, Bounds3D *b2) { @@ -1102,7 +1091,6 @@ bool dynamicPaint_createType(struct DynamicPaintModifierData *pmd, int type, str brush->flags = MOD_DPAINT_ABS_ALPHA | MOD_DPAINT_RAMP_ALPHA; brush->collision = MOD_DPAINT_COL_VOLUME; - brush->mat = NULL; brush->r = 0.15f; brush->g = 0.4f; brush->b = 0.8f; @@ -1242,7 +1230,6 @@ void dynamicPaint_Modifier_copy(struct DynamicPaintModifierData *pmd, struct Dyn t_brush->flags = brush->flags; t_brush->collision = brush->collision; - t_brush->mat = brush->mat; t_brush->r = brush->r; t_brush->g = brush->g; t_brush->b = brush->b; @@ -2071,7 +2058,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, struct Depsgraph *depsgraph, Scene *scene, + Object *ob, DerivedMesh *dm) { if (pmd->canvas) { DynamicPaintCanvasSettings *canvas = pmd->canvas; @@ -2134,7 +2123,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, depsgraph, scene, ob, current_frame); canvas->flags &= ~MOD_DPAINT_BAKING; /* restore canvas derivedmesh if required */ @@ -2153,13 +2142,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, struct Depsgraph *depsgraph, 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, depsgraph, scene, ob, dm); /* Return output mesh */ ret = dynamicPaint_Modifier_apply(pmd, ob, dm); @@ -2168,7 +2159,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, depsgraph, scene, ob, dm); /* Return output mesh */ return dynamicPaint_Modifier_apply(pmd, ob, dm); @@ -3338,91 +3329,6 @@ void dynamicPaint_outputSurfaceImage(DynamicPaintSurface *surface, char *filenam } -/***************************** Material / Texture Sampling ******************************/ - -/* stores a copy of required materials to allow doing adjustments - * without interfering the render/preview */ -typedef struct BrushMaterials { - Material *mat; - Material **ob_mats; - int tot; -} BrushMaterials; - -/* Initialize materials for brush object: - * Calculates inverse matrices for linked objects, updates - * volume caches etc. */ -static void dynamicPaint_updateBrushMaterials(Object *brushOb, Material *ui_mat, Scene *scene, BrushMaterials *bMats) -{ - /* Calculate inverse transformation matrix - * for this object */ - invert_m4_m4(brushOb->imat, brushOb->obmat); - copy_m4_m4(brushOb->imat_ren, brushOb->imat); - - /* Now process every material linked to this brush object */ - if ((ui_mat == NULL) && brushOb->mat && brushOb->totcol) { - int i, tot = (*give_totcolp(brushOb)); - - /* allocate material pointer array */ - if (tot) { - bMats->ob_mats = MEM_callocN(sizeof(Material *) * (tot), "BrushMaterials"); - for (i = 0; i < tot; i++) { - bMats->ob_mats[i] = RE_sample_material_init(give_current_material(brushOb, (i + 1)), scene); - } - } - bMats->tot = tot; - } - else { - bMats->mat = RE_sample_material_init(ui_mat, scene); - } -} - -/* free all data allocated by dynamicPaint_updateBrushMaterials() */ -static void dynamicPaint_freeBrushMaterials(BrushMaterials *bMats) -{ - /* Now process every material linked to this brush object */ - if (bMats->ob_mats) { - int i; - for (i = 0; i < bMats->tot; i++) { - RE_sample_material_free(bMats->ob_mats[i]); - } - MEM_freeN(bMats->ob_mats); - } - else if (bMats->mat) { - RE_sample_material_free(bMats->mat); - } -} - -/* - * Get material diffuse color and alpha (including linked textures) in given coordinates - */ -static void dynamicPaint_doMaterialTex( - const BrushMaterials *bMats, float color[3], float *alpha, Object *brushOb, - const float volume_co[3], const float surface_co[3], - int triIndex, DerivedMesh *orcoDm) -{ - Material *mat = bMats->mat; - - const MLoopTri *mlooptri = orcoDm->getLoopTriArray(orcoDm); - const MPoly *mpoly = orcoDm->getPolyArray(orcoDm); - - /* If no material defined, use the one assigned to the mesh face */ - if (mat == NULL) { - if (bMats->ob_mats) { - int mat_nr = mpoly[mlooptri[triIndex].poly].mat_nr; - if (mat_nr >= (*give_totcolp(brushOb))) - return; - mat = bMats->ob_mats[mat_nr]; - if (mat == NULL) - return; /* No material assigned */ - } - else { - return; - } - } - RE_sample_material_color(mat, color, alpha, volume_co, surface_co, triIndex, orcoDm, brushOb); -} - - /***************************** Ray / Nearest Point Utils ******************************/ @@ -3743,7 +3649,8 @@ static void dynamic_paint_brush_velocity_compute_cb( } static void dynamicPaint_brushMeshCalculateVelocity( - Scene *scene, Object *ob, DynamicPaintBrushSettings *brush, Vec3f **brushVel, float timescale) + struct Depsgraph *depsgraph, Scene *scene, + Object *ob, DynamicPaintBrushSettings *brush, Vec3f **brushVel, float timescale) { float prev_obmat[4][4]; DerivedMesh *dm_p, *dm_c; @@ -3765,7 +3672,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); + depsgraph, 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 +3683,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); + depsgraph, 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 +3714,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(struct Depsgraph *depsgraph, 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 +3733,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); + depsgraph, 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); + depsgraph, scene, ob, false, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint); /* calculate speed */ mul_m4_v3(prev_obmat, prev_loc); @@ -3847,7 +3754,6 @@ typedef struct DynamicPaintPaintData { const DynamicPaintSurface *surface; const DynamicPaintBrushSettings *brush; Object *brushOb; - const BrushMaterials *bMats; const Scene *scene; const float timescale; const int c_index; @@ -3884,14 +3790,10 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex( VolumeGrid *grid = bData->grid; const DynamicPaintBrushSettings *brush = data->brush; - Object *brushOb = data->brushOb; - const BrushMaterials *bMats = data->bMats; - const Scene *scene = data->scene; const float timescale = data->timescale; const int c_index = data->c_index; - DerivedMesh *dm = data->dm; const MVert *mvert = data->mvert; const MLoop *mloop = data->mloop; const MLoopTri *mlooptri = data->mlooptri; @@ -4151,13 +4053,6 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex( sampleColor[1] = brush->g; sampleColor[2] = brush->b; - /* Get material+textures color on hit point if required */ - if (brush_usesMaterial(brush, scene)) { - dynamicPaint_doMaterialTex(bMats, sampleColor, &alpha_factor, brushOb, - bData->realCoord[bData->s_pos[index] + ss].v, - hitCoord, hitTri, dm); - } - /* Sample proximity colorband if required */ if ((hit_found == HIT_PROXIMITY) && (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP)) @@ -4205,10 +4100,9 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex( } } -static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, +static int dynamicPaint_paintMesh(struct Depsgraph *depsgraph, DynamicPaintSurface *surface, DynamicPaintBrushSettings *brush, Object *brushOb, - BrushMaterials *bMats, Scene *scene, float timescale) { @@ -4221,7 +4115,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(depsgraph, scene, brushOb, brush, &brushVelocity, timescale); if (!brush->dm) return 0; @@ -4286,7 +4180,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface, /* loop through cell points and process brush */ DynamicPaintPaintData data = { .surface = surface, - .brush = brush, .brushOb = brushOb, .bMats = bMats, + .brush = brush, .brushOb = brushOb, .scene = scene, .timescale = timescale, .c_index = c_index, .dm = dm, .mvert = mvert, .mloop = mloop, .mlooptri = mlooptri, .brush_radius = brush_radius, .avg_brushNor = avg_brushNor, .brushVelocity = brushVelocity, @@ -4611,13 +4505,9 @@ static void dynamic_paint_paint_single_point_cb_ex( const PaintBakeData *bData = sData->bData; const DynamicPaintBrushSettings *brush = data->brush; - Object *brushOb = data->brushOb; - const BrushMaterials *bMats = data->bMats; - const Scene *scene = data->scene; const float timescale = data->timescale; - const MVert *mvert = data->mvert; const float brush_radius = data->brush_radius; const Vec3f *brushVelocity = data->brushVelocity; @@ -4646,17 +4536,6 @@ static void dynamic_paint_paint_single_point_cb_ex( float depth = 0.0f; float velocity_val = 0.0f; - /* material */ - if (brush_usesMaterial(brush, scene)) { - float alpha_factor = 1.0f; - float hit_coord[3]; - /* use dummy coord of first vertex */ - mul_v3_m4v3(hit_coord, brushOb->obmat, mvert[0].co); - - dynamicPaint_doMaterialTex(bMats, paintColor, &alpha_factor, brushOb, - bData->realCoord[bData->s_pos[index]].v, hit_coord, 0, brush->dm); - } - /* color ramp */ if (brush->proximity_falloff == MOD_DPAINT_PRFALL_RAMP && BKE_colorband_evaluate(brush->paint_ramp, (1.0f - strength), colorband)) @@ -4694,11 +4573,9 @@ static void dynamic_paint_paint_single_point_cb_ex( paintColor[2] = colorband[2]; } else { - if (!brush_usesMaterial(brush, scene)) { - paintColor[0] = brush->r; - paintColor[1] = brush->g; - paintColor[2] = brush->b; - } + paintColor[0] = brush->r; + paintColor[1] = brush->g; + paintColor[2] = brush->b; } } else if (ELEM(surface->type, MOD_DPAINT_SURFACE_T_DISPLACE, MOD_DPAINT_SURFACE_T_WAVE)) { @@ -4711,15 +4588,15 @@ static void dynamic_paint_paint_single_point_cb_ex( } static int dynamicPaint_paintSinglePoint( - DynamicPaintSurface *surface, float *pointCoord, DynamicPaintBrushSettings *brush, - Object *brushOb, BrushMaterials *bMats, Scene *scene, float timescale) + struct Depsgraph *depsgraph, DynamicPaintSurface *surface, float *pointCoord, DynamicPaintBrushSettings *brush, + Object *brushOb, Scene *scene, float timescale) { PaintSurfaceData *sData = surface->data; float brush_radius = brush->paint_distance * surface->radius_scale; Vec3f brushVel; if (brush->flags & MOD_DPAINT_USES_VELOCITY) - dynamicPaint_brushObjectCalculateVelocity(scene, brushOb, &brushVel, timescale); + dynamicPaint_brushObjectCalculateVelocity(depsgraph, scene, brushOb, &brushVel, timescale); const MVert *mvert = brush->dm->getVertArray(brush->dm); @@ -4728,7 +4605,7 @@ static int dynamicPaint_paintSinglePoint( */ DynamicPaintPaintData data = { .surface = surface, - .brush = brush, .brushOb = brushOb, .bMats = bMats, + .brush = brush, .brushOb = brushOb, .scene = scene, .timescale = timescale, .mvert = mvert, .brush_radius = brush_radius, .brushVelocity = &brushVel, @@ -5041,7 +4918,7 @@ static void dynamic_paint_prepare_effect_cb( } static int dynamicPaint_prepareEffectStep( - DynamicPaintSurface *surface, Scene *scene, Object *ob, float **force, float timescale) + struct Depsgraph *depsgraph, 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 +4929,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(depsgraph, 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 +5761,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 +5769,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 +5886,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(struct Depsgraph *depsgraph, Scene *scene, Object *ob, DynamicPaintSurface *surface, float timescale, float subframe) { PaintSurfaceData *sData = surface->data; PaintBakeData *bData = sData->bData; @@ -6035,9 +5912,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 = DEG_get_evaluated_view_layer(depsgraph); /* backup current scene frame */ int scene_frame = scene->r.cfra; @@ -6045,25 +5922,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 */ @@ -6077,7 +5946,6 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su /* make sure we're dealing with a brush */ if (pmd2->brush) { DynamicPaintBrushSettings *brush = pmd2->brush; - BrushMaterials bMats = {NULL}; /* calculate brush speed vectors if required */ if (surface->type == MOD_DPAINT_SURFACE_T_PAINT && brush->flags & MOD_DPAINT_DO_SMUDGE) { @@ -6092,43 +5960,35 @@ 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(depsgraph, scene, brushObj, true, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint); } - /* Prepare materials if required */ - if (brush_usesMaterial(brush, scene)) - 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)) - { - /* Paint a particle system */ - BKE_animsys_evaluate_animdata(scene, &brush->psys->part->id, brush->psys->part->adt, - BKE_scene_frame_get(scene), ADT_RECALC_ANIM); - dynamicPaint_paintParticles(surface, brush->psys, brush, timescale); - } + if (brush->psys && brush->psys->part && + ELEM(brush->psys->part->type, PART_EMITTER, PART_FLUID) && + psys_check_enabled(brushObj, brush->psys, G.is_rendering)) + { + /* Paint a particle system */ + BKE_animsys_evaluate_animdata(scene, &brush->psys->part->id, brush->psys->part->adt, + 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(depsgraph, surface, brushObj->loc, brush, brushObj, scene, timescale); } /* Mesh volume/proximity: */ else if (brushObj != ob) { - dynamicPaint_paintMesh(surface, brush, brushObj, &bMats, scene, timescale); + dynamicPaint_paintMesh(depsgraph, surface, brush, brushObj, scene, timescale); } - /* free temp material data */ - if (brush_usesMaterial(brush, scene)) - dynamicPaint_freeBrushMaterials(&bMats); /* reset object to it's original state */ 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(depsgraph, scene, brushObj, true, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint); } @@ -6163,7 +6023,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(depsgraph, surface, scene, ob, &force, timescale); for (s = 0; s < steps; s++) { dynamicPaint_doEffectStep(surface, force, prevPoint, timescale, (float)steps); } @@ -6187,7 +6047,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, struct Depsgraph *depsgraph, + Scene *scene, Object *cObject, int frame) { float timescale = 1.0f; @@ -6196,7 +6058,8 @@ int dynamicPaint_calculateFrame(DynamicPaintSurface *surface, Scene *scene, Obje dynamicPaint_applySurfaceDisplace(surface, surface->canvas->dm); /* update bake data */ - dynamicPaint_generateBakeData(surface, scene, cObject); + ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); + dynamicPaint_generateBakeData(surface, view_layer, cObject); /* don't do substeps for first frame */ if (surface->substeps && (frame != surface->start_frame)) { @@ -6205,10 +6068,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(depsgraph, scene, cObject, surface, timescale, subframe)) return 0; } } - return dynamicPaint_doStep(scene, cObject, surface, timescale, 0.0f); + return dynamicPaint_doStep(depsgraph, scene, cObject, surface, timescale, 0.0f); } diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c index ffa7fdc3ec9..f5e5a37c7d7 100644 --- a/source/blender/blenkernel/intern/editderivedmesh.c +++ b/source/blender/blenkernel/intern/editderivedmesh.c @@ -52,32 +52,20 @@ #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" +#include "DNA_mesh_types.h" #include "MEM_guardedalloc.h" -#include "GPU_glew.h" -#include "GPU_buffers.h" -#include "GPU_shader.h" -#include "GPU_basic_shader.h" - -static void bmdm_get_tri_colpreview(BMLoop *ls[3], MLoopCol *lcol[3], unsigned char(*color_vert_array)[4]); - typedef struct EditDerivedBMesh { DerivedMesh dm; BMEditMesh *em; - /** when set, \a vertexNos, polyNos are lazy initialized */ - const float (*vertexCos)[3]; - - /** lazy initialize (when \a vertexCos is set) */ - float const (*vertexNos)[3]; - float const (*polyNos)[3]; - /** also lazy init but dont depend on \a vertexCos */ - const float (*polyCos)[3]; + EditMeshData emd; } EditDerivedBMesh; /* -------------------------------------------------------------------- */ @@ -87,7 +75,7 @@ static void emDM_ensurePolyNormals(EditDerivedBMesh *bmdm); static void emDM_ensureVertNormals(EditDerivedBMesh *bmdm) { - if (bmdm->vertexCos && (bmdm->vertexNos == NULL)) { + if (bmdm->emd.vertexCos && (bmdm->emd.vertexNos == NULL)) { BMesh *bm = bmdm->em->bm; const float (*vertexCos)[3], (*polyNos)[3]; @@ -98,19 +86,19 @@ static void emDM_ensureVertNormals(EditDerivedBMesh *bmdm) BM_mesh_elem_index_ensure(bm, BM_FACE); - polyNos = bmdm->polyNos; - vertexCos = bmdm->vertexCos; + polyNos = bmdm->emd.polyNos; + vertexCos = bmdm->emd.vertexCos; vertexNos = MEM_callocN(sizeof(*vertexNos) * bm->totvert, __func__); BM_verts_calc_normal_vcos(bm, polyNos, vertexCos, vertexNos); - bmdm->vertexNos = (const float (*)[3])vertexNos; + bmdm->emd.vertexNos = (const float (*)[3])vertexNos; } } static void emDM_ensurePolyNormals(EditDerivedBMesh *bmdm) { - if (bmdm->vertexCos && (bmdm->polyNos == NULL)) { + if (bmdm->emd.vertexCos && (bmdm->emd.polyNos == NULL)) { BMesh *bm = bmdm->em->bm; const float (*vertexCos)[3]; float (*polyNos)[3]; @@ -123,7 +111,7 @@ static void emDM_ensurePolyNormals(EditDerivedBMesh *bmdm) polyNos = MEM_mallocN(sizeof(*polyNos) * bm->totface, __func__); - vertexCos = bmdm->vertexCos; + vertexCos = bmdm->emd.vertexCos; BM_ITER_MESH_INDEX (efa, &fiter, bm, BM_FACES_OF_MESH, i) { BM_elem_index_set(efa, i); /* set_inline */ @@ -131,13 +119,13 @@ static void emDM_ensurePolyNormals(EditDerivedBMesh *bmdm) } bm->elem_index_dirty &= ~BM_FACE; - bmdm->polyNos = (const float (*)[3])polyNos; + bmdm->emd.polyNos = (const float (*)[3])polyNos; } } static void emDM_ensurePolyCenters(EditDerivedBMesh *bmdm) { - if (bmdm->polyCos == NULL) { + if (bmdm->emd.polyCos == NULL) { BMesh *bm = bmdm->em->bm; float (*polyCos)[3]; @@ -147,9 +135,9 @@ static void emDM_ensurePolyCenters(EditDerivedBMesh *bmdm) polyCos = MEM_mallocN(sizeof(*polyCos) * bm->totface, __func__); - if (bmdm->vertexCos) { + if (bmdm->emd.vertexCos) { const float (*vertexCos)[3]; - vertexCos = bmdm->vertexCos; + vertexCos = bmdm->emd.vertexCos; BM_mesh_elem_index_ensure(bm, BM_VERT); @@ -163,7 +151,7 @@ static void emDM_ensurePolyCenters(EditDerivedBMesh *bmdm) } } - bmdm->polyCos = (const float (*)[3])polyCos; + bmdm->emd.polyCos = (const float (*)[3])polyCos; } } @@ -199,9 +187,9 @@ static void emDM_calcLoopNormalsSpaceArray( emDM_ensurePolyNormals(bmdm); dm->dirty &= ~DM_DIRTY_NORMALS; - vertexCos = bmdm->vertexCos; - vertexNos = bmdm->vertexNos; - polyNos = bmdm->polyNos; + vertexCos = bmdm->emd.vertexCos; + vertexNos = bmdm->emd.vertexNos; + polyNos = bmdm->emd.polyNos; loopNos = dm->getLoopDataArray(dm, CD_NORMAL); if (!loopNos) { @@ -242,392 +230,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->emd.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)) { @@ -680,13 +305,13 @@ static void emDM_foreachMappedVert( BMIter iter; int i; - if (bmdm->vertexCos) { - const float (*vertexCos)[3] = bmdm->vertexCos; + if (bmdm->emd.vertexCos) { + const float (*vertexCos)[3] = bmdm->emd.vertexCos; const float (*vertexNos)[3]; if (flag & DM_FOREACH_USE_NORMAL) { emDM_ensureVertNormals(bmdm); - vertexNos = bmdm->vertexNos; + vertexNos = bmdm->emd.vertexNos; } else { vertexNos = NULL; @@ -715,14 +340,14 @@ static void emDM_foreachMappedEdge( BMIter iter; int i; - if (bmdm->vertexCos) { + if (bmdm->emd.vertexCos) { BM_mesh_elem_index_ensure(bm, BM_VERT); BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) { func(userData, i, - bmdm->vertexCos[BM_elem_index_get(eed->v1)], - bmdm->vertexCos[BM_elem_index_get(eed->v2)]); + bmdm->emd.vertexCos[BM_elem_index_get(eed->v1)], + bmdm->emd.vertexCos[BM_elem_index_get(eed->v2)]); } } else { @@ -732,123 +357,6 @@ static void emDM_foreachMappedEdge( } } -static void emDM_drawMappedEdges( - DerivedMesh *dm, - DMSetDrawOptions setDrawOptions, - void *userData) -{ - EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; - BMesh *bm = bmdm->em->bm; - BMEdge *eed; - BMIter iter; - int i; - - if (bmdm->vertexCos) { - - BM_mesh_elem_index_ensure(bm, BM_VERT); - - glBegin(GL_LINES); - BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) { - if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) { - glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v1)]); - glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v2)]); - } - } - glEnd(); - } - else { - glBegin(GL_LINES); - BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) { - if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) { - glVertex3fv(eed->v1->co); - glVertex3fv(eed->v2->co); - } - } - glEnd(); - } -} -static void emDM_drawEdges( - DerivedMesh *dm, - bool UNUSED(drawLooseEdges), - bool UNUSED(drawAllEdges)) -{ - emDM_drawMappedEdges(dm, NULL, NULL); -} - -static void emDM_drawMappedEdgesInterp( - DerivedMesh *dm, - DMSetDrawOptions setDrawOptions, - DMSetDrawInterpOptions setDrawInterpOptions, - void *userData) -{ - EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; - BMesh *bm = bmdm->em->bm; - BMEdge *eed; - BMIter iter; - int i; - - if (bmdm->vertexCos) { - - BM_mesh_elem_index_ensure(bm, BM_VERT); - - glBegin(GL_LINES); - BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) { - if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) { - setDrawInterpOptions(userData, i, 0.0); - glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v1)]); - setDrawInterpOptions(userData, i, 1.0); - glVertex3fv(bmdm->vertexCos[BM_elem_index_get(eed->v2)]); - } - } - glEnd(); - } - else { - glBegin(GL_LINES); - BM_ITER_MESH_INDEX (eed, &iter, bm, BM_EDGES_OF_MESH, i) { - if (!setDrawOptions || (setDrawOptions(userData, i) != DM_DRAW_OPTION_SKIP)) { - setDrawInterpOptions(userData, i, 0.0); - glVertex3fv(eed->v1->co); - setDrawInterpOptions(userData, i, 1.0); - glVertex3fv(eed->v2->co); - } - } - glEnd(); - } -} - -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]), @@ -864,7 +372,7 @@ static void emDM_foreachMappedLoop( BMFace *efa; BMIter iter; - const float (*vertexCos)[3] = bmdm->vertexCos; + const float (*vertexCos)[3] = bmdm->emd.vertexCos; int f_idx; BM_mesh_elem_index_ensure(bm, BM_VERT); @@ -897,11 +405,11 @@ static void emDM_foreachMappedFaceCenter( int i; emDM_ensurePolyCenters(bmdm); - polyCos = bmdm->polyCos; /* always set */ + polyCos = bmdm->emd.polyCos; /* always set */ if (flag & DM_FOREACH_USE_NORMAL) { emDM_ensurePolyNormals(bmdm); - polyNos = bmdm->polyNos; /* maybe NULL */ + polyNos = bmdm->emd.polyNos; /* maybe NULL */ } else { polyNos = NULL; @@ -921,783 +429,6 @@ static void emDM_foreachMappedFaceCenter( } } -static void emDM_drawMappedFaces( - DerivedMesh *dm, - DMSetDrawOptions setDrawOptions, - DMSetMaterial setMaterial, - /* currently unused -- each original face is handled separately */ - DMCompareDrawOptions UNUSED(compareDrawOptions), - void *userData, - DMDrawFlag flag) -{ - EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; - BMEditMesh *em = bmdm->em; - BMesh *bm = em->bm; - BMFace *efa; - struct BMLoop *(*looptris)[3] = bmdm->em->looptris; - const int tottri = bmdm->em->tottri; - DMDrawOption draw_option; - int i; - const int skip_normals = !(flag & DM_DRAW_NEED_NORMALS); - const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL); - MLoopCol *lcol[3] = {NULL} /* , dummylcol = {0} */; - unsigned char(*color_vert_array)[4] = em->derivedVertColor; - unsigned char(*color_face_array)[4] = em->derivedFaceColor; - bool has_vcol_preview = (color_vert_array != NULL) && !skip_normals; - bool has_fcol_preview = (color_face_array != NULL) && !skip_normals; - bool has_vcol_any = has_vcol_preview; - - /* GL_ZERO is used to detect if drawing has started or not */ - GLenum poly_prev = GL_ZERO; - GLenum shade_prev = GL_ZERO; - DMDrawOption draw_option_prev = DM_DRAW_OPTION_SKIP; - - /* call again below is ok */ - if (has_vcol_preview) { - BM_mesh_elem_index_ensure(bm, BM_VERT); - } - if (has_fcol_preview) { - BM_mesh_elem_index_ensure(bm, BM_FACE); - } - if (has_vcol_preview || has_fcol_preview) { - flag |= DM_DRAW_ALWAYS_SMOOTH; - /* weak, this logic should really be moved higher up */ - setMaterial = NULL; - } - - if (bmdm->vertexCos) { - short prev_mat_nr = -1; - - /* add direct access */ - const float (*vertexCos)[3] = bmdm->vertexCos; - const float (*vertexNos)[3]; - const float (*polyNos)[3]; - - if (skip_normals) { - vertexNos = NULL; - polyNos = NULL; - } - else { - emDM_ensureVertNormals(bmdm); - emDM_ensurePolyNormals(bmdm); - vertexNos = bmdm->vertexNos; - polyNos = bmdm->polyNos; - } - - BM_mesh_elem_index_ensure(bm, lnors ? BM_VERT | BM_FACE | BM_LOOP : BM_VERT | BM_FACE); - - for (i = 0; i < tottri; i++) { - BMLoop **ltri = looptris[i]; - int drawSmooth; - - efa = ltri[0]->f; - drawSmooth = lnors || ((flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH)); - - draw_option = (!setDrawOptions ? - DM_DRAW_OPTION_NORMAL : - setDrawOptions(userData, BM_elem_index_get(efa))); - if (draw_option != DM_DRAW_OPTION_SKIP) { - const GLenum poly_type = GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */ - - if (draw_option_prev != draw_option) { - if (draw_option_prev == DM_DRAW_OPTION_STIPPLE) { - if (poly_prev != GL_ZERO) glEnd(); - poly_prev = GL_ZERO; /* force glBegin */ - - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - } - draw_option_prev = draw_option; - } - - - if (efa->mat_nr != prev_mat_nr) { - if (setMaterial) { - if (poly_prev != GL_ZERO) glEnd(); - poly_prev = GL_ZERO; /* force glBegin */ - - setMaterial(efa->mat_nr + 1, NULL); - } - prev_mat_nr = efa->mat_nr; - } - - if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */ - - if (poly_prev != GL_ZERO) glEnd(); - poly_prev = GL_ZERO; /* force glBegin */ - - GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR); - GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_QUARTTONE); - } - - if (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array); - else if (has_fcol_preview) glColor3ubv((const GLubyte *)&(color_face_array[BM_elem_index_get(efa)])); - if (skip_normals) { - if (poly_type != poly_prev) { - 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)); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]); - } - else { - const GLenum shade_type = drawSmooth ? GL_SMOOTH : GL_FLAT; - if (shade_type != shade_prev) { - if (poly_prev != GL_ZERO) glEnd(); - glShadeModel((shade_prev = shade_type)); /* same as below but switch shading */ - glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */ - } - if (poly_type != poly_prev) { - if (poly_prev != GL_ZERO) glEnd(); - glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */ - } - - if (!drawSmooth) { - glNormal3fv(polyNos[BM_elem_index_get(efa)]); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r)); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]); - if (has_vcol_any) glColor4ubv((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 (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 (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 (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)]); - } - } - } - } - } - else { - short prev_mat_nr = -1; - - BM_mesh_elem_index_ensure(bm, lnors ? BM_FACE | BM_LOOP : BM_FACE); - - for (i = 0; i < tottri; i++) { - BMLoop **ltri = looptris[i]; - int drawSmooth; - - efa = ltri[0]->f; - drawSmooth = lnors || ((flag & DM_DRAW_ALWAYS_SMOOTH) ? 1 : BM_elem_flag_test(efa, BM_ELEM_SMOOTH)); - - draw_option = (setDrawOptions ? - setDrawOptions(userData, BM_elem_index_get(efa)) : - DM_DRAW_OPTION_NORMAL); - - if (draw_option != DM_DRAW_OPTION_SKIP) { - const GLenum poly_type = GL_TRIANGLES; /* BMESH NOTE, this is odd but keep it for now to match trunk */ - - if (draw_option_prev != draw_option) { - if (draw_option_prev == DM_DRAW_OPTION_STIPPLE) { - if (poly_prev != GL_ZERO) glEnd(); - poly_prev = GL_ZERO; /* force glBegin */ - - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - } - draw_option_prev = draw_option; - } - - if (efa->mat_nr != prev_mat_nr) { - if (setMaterial) { - if (poly_prev != GL_ZERO) glEnd(); - poly_prev = GL_ZERO; /* force glBegin */ - - setMaterial(efa->mat_nr + 1, NULL); - } - prev_mat_nr = efa->mat_nr; - } - - if (draw_option == DM_DRAW_OPTION_STIPPLE) { /* enabled with stipple */ - - if (poly_prev != GL_ZERO) glEnd(); - poly_prev = GL_ZERO; /* force glBegin */ - - GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR); - GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_QUARTTONE); - } - - if (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array); - else if (has_fcol_preview) glColor3ubv((const GLubyte *)&(color_face_array[BM_elem_index_get(efa)])); - - if (skip_normals) { - if (poly_type != poly_prev) { - 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)); - glVertex3fv(ltri[0]->v->co); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); - glVertex3fv(ltri[1]->v->co); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); - glVertex3fv(ltri[2]->v->co); - } - else { - const GLenum shade_type = drawSmooth ? GL_SMOOTH : GL_FLAT; - if (shade_type != shade_prev) { - if (poly_prev != GL_ZERO) glEnd(); - glShadeModel((shade_prev = shade_type)); /* same as below but switch shading */ - glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */ - } - if (poly_type != poly_prev) { - if (poly_prev != GL_ZERO) glEnd(); - glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */ - } - - if (!drawSmooth) { - glNormal3fv(efa->no); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r)); - glVertex3fv(ltri[0]->v->co); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r)); - glVertex3fv(ltri[1]->v->co); - if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r)); - glVertex3fv(ltri[2]->v->co); - } - else { - 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); - 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); - 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); - } - } - } - } - } - - /* if non zero we know a face was rendered */ - if (poly_prev != GL_ZERO) glEnd(); - - if (draw_option_prev == DM_DRAW_OPTION_STIPPLE) { - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - } - - if (shade_prev == GL_FLAT) { - glShadeModel(GL_SMOOTH); - } -} - -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)]; - lcol[1] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[1]->v)]; - 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 - * - * For UV's: - * const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, attribs->tface[i].em_offset); - * - * This is intentionally different to calling: - * CustomData_bmesh_get_n(&bm->ldata, loop->head.data, CD_MLOOPUV, i); - * - * ... because the material may use layer names to select different UV's - * see: [#34378] - */ -static void emdm_pass_attrib_vertex_glsl(const DMVertexAttribs *attribs, const BMLoop *loop) -{ - BMVert *eve = loop->v; - int i; - const float zero[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - - if (attribs->totorco) { - int index = BM_elem_index_get(eve); - const float *orco = (attribs->orco.array) ? attribs->orco.array[index] : zero; - - if (attribs->orco.gl_texco) - glTexCoord3fv(orco); - else - glVertexAttrib3fv(attribs->orco.gl_index, orco); - } - for (i = 0; i < attribs->tottface; i++) { - const float *uv; - - if (attribs->tface[i].em_offset != -1) { - const MLoopUV *luv = BM_ELEM_CD_GET_VOID_P(loop, attribs->tface[i].em_offset); - uv = luv->uv; - } - else { - uv = zero; - } - - if (attribs->tface[i].gl_texco) - glTexCoord2fv(uv); - else - glVertexAttrib2fv(attribs->tface[i].gl_index, uv); - } - for (i = 0; i < attribs->totmcol; i++) { - float col[4]; - if (attribs->mcol[i].em_offset != -1) { - const MLoopCol *cp = BM_ELEM_CD_GET_VOID_P(loop, attribs->mcol[i].em_offset); - rgba_uchar_to_float(col, &cp->r); - } - else { - col[0] = 0.0f; col[1] = 0.0f; col[2] = 0.0f; col[3] = 0.0f; - } - glVertexAttrib4fv(attribs->mcol[i].gl_index, col); - } - - for (i = 0; i < attribs->tottang; i++) { - const float *tang; - if (attribs->tang[i].em_offset != -1) { - tang = attribs->tang[i].array[BM_elem_index_get(loop)]; - } - else { - tang = zero; - } - glVertexAttrib4fv(attribs->tang[i].gl_index, tang); - } -} - -static void emDM_drawMappedFacesGLSL( - DerivedMesh *dm, - DMSetMaterial setMaterial, - DMSetDrawOptions setDrawOptions, - void *userData) -{ - EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; - BMEditMesh *em = bmdm->em; - BMesh *bm = em->bm; - struct BMLoop *(*looptris)[3] = em->looptris; - /* add direct access */ - const float (*vertexCos)[3] = bmdm->vertexCos; - const float (*vertexNos)[3]; - const float (*polyNos)[3]; - const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL); - - BMFace *efa; - DMVertexAttribs attribs; - GPUVertexAttribs gattribs; - - int i, matnr, new_matnr, fi; - bool do_draw; - - do_draw = false; - matnr = -1; - - memset(&attribs, 0, sizeof(attribs)); - - emDM_ensureVertNormals(bmdm); - emDM_ensurePolyNormals(bmdm); - vertexNos = bmdm->vertexNos; - polyNos = bmdm->polyNos; - - BM_mesh_elem_index_ensure(bm, (BM_VERT | BM_FACE) | (lnors ? BM_LOOP : 0)); - - for (i = 0; i < em->tottri; i++) { - BMLoop **ltri = looptris[i]; - int drawSmooth; - - efa = ltri[0]->f; - - if (setDrawOptions && (setDrawOptions(userData, BM_elem_index_get(efa)) == DM_DRAW_OPTION_SKIP)) - continue; - - /* material */ - new_matnr = efa->mat_nr + 1; - if (new_matnr != matnr) { - if (matnr != -1) - glEnd(); - - do_draw = setMaterial(matnr = new_matnr, &gattribs); - if (do_draw) { - DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); - DM_draw_attrib_vertex_uniforms(&attribs); - if (UNLIKELY(attribs.tottang && bm->elem_index_dirty & BM_LOOP)) { - BM_mesh_elem_index_ensure(bm, BM_LOOP); - } - } - - glBegin(GL_TRIANGLES); - } - - if (do_draw) { - - /* draw face */ - drawSmooth = lnors || BM_elem_flag_test(efa, BM_ELEM_SMOOTH); - - if (!drawSmooth) { - if (vertexCos) { - glNormal3fv(polyNos[BM_elem_index_get(efa)]); - for (fi = 0; fi < 3; fi++) { - emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[fi]->v)]); - } - } - else { - glNormal3fv(efa->no); - for (fi = 0; fi < 3; fi++) { - emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]); - glVertex3fv(ltri[fi]->v->co); - } - } - } - else { - if (vertexCos) { - for (fi = 0; fi < 3; fi++) { - const int j = BM_elem_index_get(ltri[fi]->v); - emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]); - else glNormal3fv(vertexNos[j]); - glVertex3fv(vertexCos[j]); - } - } - else { - for (fi = 0; fi < 3; fi++) { - emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]); - else glNormal3fv(ltri[fi]->v->no); - glVertex3fv(ltri[fi]->v->co); - } - } - } - } - } - - if (matnr != -1) { - glEnd(); - } -} - -static void emDM_drawFacesGLSL( - DerivedMesh *dm, - int (*setMaterial)(int matnr, void *attribs)) -{ - dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL); -} - -static void emDM_drawMappedFacesMat( - DerivedMesh *dm, - void (*setMaterial)(void *userData, int matnr, void *attribs), - bool (*setFace)(void *userData, int index), void *userData) -{ - EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; - BMEditMesh *em = bmdm->em; - BMesh *bm = em->bm; - struct BMLoop *(*looptris)[3] = em->looptris; - const float (*vertexCos)[3] = bmdm->vertexCos; - const float (*vertexNos)[3]; - const float (*polyNos)[3]; - const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL); - BMFace *efa; - DMVertexAttribs attribs = {{{NULL}}}; - GPUVertexAttribs gattribs; - int i, matnr, new_matnr, fi; - - matnr = -1; - - emDM_ensureVertNormals(bmdm); - emDM_ensurePolyNormals(bmdm); - - vertexNos = bmdm->vertexNos; - polyNos = bmdm->polyNos; - - BM_mesh_elem_index_ensure(bm, (BM_VERT | BM_FACE) | (lnors ? BM_LOOP : 0)); - - for (i = 0; i < em->tottri; i++) { - BMLoop **ltri = looptris[i]; - int drawSmooth; - - efa = ltri[0]->f; - - /* face hiding */ - if (setFace && !setFace(userData, BM_elem_index_get(efa))) - continue; - - /* material */ - new_matnr = efa->mat_nr + 1; - if (new_matnr != matnr) { - if (matnr != -1) - glEnd(); - - setMaterial(userData, matnr = new_matnr, &gattribs); - DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); - if (UNLIKELY(attribs.tottang && bm->elem_index_dirty & BM_LOOP)) { - BM_mesh_elem_index_ensure(bm, BM_LOOP); - } - - glBegin(GL_TRIANGLES); - } - - /* draw face */ - drawSmooth = lnors || BM_elem_flag_test(efa, BM_ELEM_SMOOTH); - - if (!drawSmooth) { - if (vertexCos) { - glNormal3fv(polyNos[BM_elem_index_get(efa)]); - for (fi = 0; fi < 3; fi++) { - emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]); - glVertex3fv(vertexCos[BM_elem_index_get(ltri[fi]->v)]); - } - } - else { - glNormal3fv(efa->no); - for (fi = 0; fi < 3; fi++) { - emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]); - glVertex3fv(ltri[fi]->v->co); - } - } - } - else { - if (vertexCos) { - for (fi = 0; fi < 3; fi++) { - const int j = BM_elem_index_get(ltri[fi]->v); - emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]); - else glNormal3fv(vertexNos[j]); - glVertex3fv(vertexCos[j]); - } - } - else { - for (fi = 0; fi < 3; fi++) { - emdm_pass_attrib_vertex_glsl(&attribs, ltri[fi]); - if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[fi])]); - else glNormal3fv(ltri[fi]->v->no); - glVertex3fv(ltri[fi]->v->co); - } - } - } - } - - if (matnr != -1) { - glEnd(); - } -} - static void emDM_getMinMax(DerivedMesh *dm, float r_min[3], float r_max[3]) { EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; @@ -1707,9 +438,9 @@ static void emDM_getMinMax(DerivedMesh *dm, float r_min[3], float r_max[3]) int i; if (bm->totvert) { - if (bmdm->vertexCos) { + if (bmdm->emd.vertexCos) { BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { - minmax_v3v3_v3(r_min, r_max, bmdm->vertexCos[i]); + minmax_v3v3_v3(r_min, r_max, bmdm->emd.vertexCos[i]); } } else { @@ -1789,8 +520,8 @@ static void emDM_getVert(DerivedMesh *dm, int index, MVert *r_vert) // ev = BM_vert_at_index(bm, index); /* warning, does list loop, _not_ ideal */ bmvert_to_mvert(bm, ev, r_vert); - if (bmdm->vertexCos) - copy_v3_v3(r_vert->co, bmdm->vertexCos[index]); + if (bmdm->emd.vertexCos) + copy_v3_v3(r_vert->co, bmdm->emd.vertexCos[index]); } static void emDM_getVertCo(DerivedMesh *dm, int index, float r_co[3]) @@ -1803,8 +534,8 @@ static void emDM_getVertCo(DerivedMesh *dm, int index, float r_co[3]) return; } - if (bmdm->vertexCos) { - copy_v3_v3(r_co, bmdm->vertexCos[index]); + if (bmdm->emd.vertexCos) { + copy_v3_v3(r_co, bmdm->emd.vertexCos[index]); } else { BMVert *ev; @@ -1827,9 +558,9 @@ static void emDM_getVertNo(DerivedMesh *dm, int index, float r_no[3]) } - if (bmdm->vertexCos) { + if (bmdm->emd.vertexCos) { emDM_ensureVertNormals(bmdm); - copy_v3_v3(r_no, bmdm->vertexNos[index]); + copy_v3_v3(r_no, bmdm->emd.vertexNos[index]); } else { BMVert *ev; @@ -1851,9 +582,9 @@ static void emDM_getPolyNo(DerivedMesh *dm, int index, float r_no[3]) return; } - if (bmdm->vertexCos) { + if (bmdm->emd.vertexCos) { emDM_ensurePolyNormals(bmdm); - copy_v3_v3(r_no, bmdm->polyNos[index]); + copy_v3_v3(r_no, bmdm->emd.polyNos[index]); } else { BMFace *efa; @@ -1928,11 +659,11 @@ static void emDM_copyVertArray(DerivedMesh *dm, MVert *r_vert) BMIter iter; const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); - if (bmdm->vertexCos) { + if (bmdm->emd.vertexCos) { int i; BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { - copy_v3_v3(r_vert->co, bmdm->vertexCos[i]); + copy_v3_v3(r_vert->co, bmdm->emd.vertexCos[i]); normal_float_to_short_v3(r_vert->no, eve->no); r_vert->flag = BM_vert_flag_to_mflag(eve); @@ -2061,14 +792,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 +809,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); @@ -2149,9 +867,9 @@ static void emDM_getVertCos(DerivedMesh *dm, float (*r_cos)[3]) BMIter iter; int i; - if (bmdm->vertexCos) { + if (bmdm->emd.vertexCos) { BM_ITER_MESH_INDEX (eve, &iter, bm, BM_VERTS_OF_MESH, i) { - copy_v3_v3(r_cos[i], bmdm->vertexCos[i]); + copy_v3_v3(r_cos[i], bmdm->emd.vertexCos[i]); } } else { @@ -2166,18 +884,18 @@ static void emDM_release(DerivedMesh *dm) EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm; if (DM_release(dm)) { - if (bmdm->vertexCos) { - MEM_freeN((void *)bmdm->vertexCos); - if (bmdm->vertexNos) { - MEM_freeN((void *)bmdm->vertexNos); + if (bmdm->emd.vertexCos) { + MEM_freeN((void *)bmdm->emd.vertexCos); + if (bmdm->emd.vertexNos) { + MEM_freeN((void *)bmdm->emd.vertexNos); } - if (bmdm->polyNos) { - MEM_freeN((void *)bmdm->polyNos); + if (bmdm->emd.polyNos) { + MEM_freeN((void *)bmdm->emd.polyNos); } } - if (bmdm->polyCos) { - MEM_freeN((void *)bmdm->polyCos); + if (bmdm->emd.polyCos) { + MEM_freeN((void *)bmdm->emd.polyCos); } MEM_freeN(bmdm); @@ -2280,20 +998,9 @@ DerivedMesh *getEditDerivedBMesh( bmdm->dm.foreachMappedEdge = emDM_foreachMappedEdge; bmdm->dm.foreachMappedFaceCenter = emDM_foreachMappedFaceCenter; - bmdm->dm.drawEdges = emDM_drawEdges; - 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; - bmdm->vertexCos = (const float (*)[3])vertexCos; + bmdm->emd.vertexCos = (const float (*)[3])vertexCos; bmdm->dm.deformedOnly = (vertexCos != NULL); const int cd_dvert_offset = (data_mask & CD_MASK_MDEFORMVERT) ? @@ -2721,7 +1428,7 @@ void BKE_editmesh_statvis_calc( { BKE_editmesh_color_ensure(em, BM_FACE); statvis_calc_overhang( - em, bmdm ? bmdm->polyNos : NULL, + em, bmdm ? bmdm->emd.polyNos : NULL, statvis->overhang_min / (float)M_PI, statvis->overhang_max / (float)M_PI, statvis->overhang_axis, @@ -2733,7 +1440,7 @@ void BKE_editmesh_statvis_calc( const float scale = 1.0f / mat4_to_scale(em->ob->obmat); BKE_editmesh_color_ensure(em, BM_FACE); statvis_calc_thickness( - em, bmdm ? bmdm->vertexCos : NULL, + em, bmdm ? bmdm->emd.vertexCos : NULL, statvis->thickness_min * scale, statvis->thickness_max * scale, statvis->thickness_samples, @@ -2744,7 +1451,7 @@ void BKE_editmesh_statvis_calc( { BKE_editmesh_color_ensure(em, BM_FACE); statvis_calc_intersect( - em, bmdm ? bmdm->vertexCos : NULL, + em, bmdm ? bmdm->emd.vertexCos : NULL, em->derivedFaceColor); break; } @@ -2756,7 +1463,7 @@ void BKE_editmesh_statvis_calc( emDM_ensurePolyNormals(bmdm); statvis_calc_distort( - em, bmdm ? bmdm->vertexCos : NULL, bmdm ? bmdm->polyNos : NULL, + em, bmdm ? bmdm->emd.vertexCos : NULL, bmdm ? bmdm->emd.polyNos : NULL, statvis->distort_min, statvis->distort_max, em->derivedFaceColor); @@ -2766,7 +1473,7 @@ void BKE_editmesh_statvis_calc( { BKE_editmesh_color_ensure(em, BM_VERT); statvis_calc_sharp( - em, bmdm ? bmdm->vertexCos : NULL, + em, bmdm ? bmdm->emd.vertexCos : NULL, statvis->sharp_min, statvis->sharp_max, /* in this case they are vertex colors */ @@ -2799,14 +1506,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(struct Depsgraph *depsgraph, 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(depsgraph, 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..b63ab276b14 100644 --- a/source/blender/blenkernel/intern/editmesh.c +++ b/source/blender/blenkernel/intern/editmesh.c @@ -89,11 +89,13 @@ BMEditMesh *BKE_editmesh_from_object(Object *ob) { BLI_assert(ob->type == OB_MESH); /* sanity check */ +#if 0 /* disable in mutlti-object edit. */ #ifndef NDEBUG if (((Mesh *)ob->data)->edit_btmesh) { BLI_assert(((Mesh *)ob->data)->edit_btmesh->ob == ob); } #endif +#endif return ((Mesh *)ob->data)->edit_btmesh; } @@ -165,26 +167,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_bvh.c b/source/blender/blenkernel/intern/editmesh_bvh.c index 2927354241c..e68f11f6274 100644 --- a/source/blender/blenkernel/intern/editmesh_bvh.c +++ b/source/blender/blenkernel/intern/editmesh_bvh.c @@ -547,4 +547,4 @@ BVHTreeOverlap *BKE_bmbvh_overlap(const BMBVHTree *bmtree_a, const BMBVHTree *bm data.epsilon = max_ff(BLI_bvhtree_get_epsilon(bmtree_a->tree), BLI_bvhtree_get_epsilon(bmtree_b->tree)); return BLI_bvhtree_overlap(bmtree_a->tree, bmtree_b->tree, r_overlap_tot, bmbvh_overlap_cb, &data); -}
\ No newline at end of file +} diff --git a/source/blender/blenkernel/intern/editmesh_tangent.c b/source/blender/blenkernel/intern/editmesh_tangent.c new file mode 100644 index 00000000000..9e8b4fa8782 --- /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 */ +} + +/** \} */ diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c index e47af83e00e..8bdc74edffd 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,8 @@ #include "BKE_scene.h" #include "BKE_smoke.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "RE_render_ext.h" #include "RE_shader_ext.h" @@ -145,9 +149,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(struct Depsgraph *depsgraph, Scene *scene, Object *ob, ParticleSystem *psys, PartDeflect *pd) { EffectorCache *eff = MEM_callocN(sizeof(EffectorCache), "EffectorCache"); + eff->depsgraph = depsgraph; eff->scene = scene; eff->ob = ob; eff->psys = psys; @@ -155,7 +160,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, struct Depsgraph *depsgraph, Scene *scene, EffectorWeights *weights, Object *ob, Object *ob_src, bool for_simulation) { EffectorCache *eff = NULL; @@ -173,14 +178,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(depsgraph, 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, struct Depsgraph *depsgraph, Scene *scene, EffectorWeights *weights, Object *ob, ParticleSystem *psys, ParticleSystem *psys_src, bool for_simulation) { ParticleSettings *part= psys->part; @@ -194,61 +199,60 @@ 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(depsgraph, 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(depsgraph, 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( + struct Depsgraph *depsgraph, 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; + } + /* TODO(mai): the check for view_layer shouldnt be needed, remove when render engine api is updated for this */ + else if (depsgraph && DEG_get_evaluated_view_layer(depsgraph)) { + view_layer = DEG_get_evaluated_view_layer(depsgraph); + } + else { + /* depsgraph 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, depsgraph, 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, depsgraph, scene, weights, base->object, psys, psys_src, for_simulation); } } } - - if (for_simulation) - pdPrecalculateEffectors(effectors); - + + if (for_simulation) { + pdPrecalculateEffectors(depsgraph, effectors); + } + return effectors; } @@ -268,7 +272,7 @@ void pdEndEffectors(ListBase **effectors) } } -static void precalculate_effector(EffectorCache *eff) +static void precalculate_effector(struct Depsgraph *depsgraph, 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 +284,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(depsgraph, 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 +305,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(depsgraph, 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(depsgraph, eff->scene, eff->ob, cfra); sub_v3_v3v3(eff->velocity, eff->ob->obmat[3], old_vel); } } -void pdPrecalculateEffectors(ListBase *effectors) +void pdPrecalculateEffectors(struct Depsgraph *depsgraph, ListBase *effectors) { if (effectors) { EffectorCache *eff = effectors->first; for (; eff; eff=eff->next) - precalculate_effector(eff); + precalculate_effector(depsgraph, eff); } } @@ -612,6 +616,7 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin } else { ParticleSimulationData sim= {NULL}; + sim.depsgraph = eff->depsgraph; 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 7dc6e3575b2..c79b2bb4aee 100644 --- a/source/blender/blenkernel/intern/fluidsim.c +++ b/source/blender/blenkernel/intern/fluidsim.c @@ -64,7 +64,7 @@ // file handling //------------------------------------------------------------------------------- -void initElbeemMesh(struct Scene *scene, struct Object *ob, +void initElbeemMesh(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob, int *numVertices, float **vertices, int *numTriangles, int **triangles, int useGlobalCoords, int modifierIndex) @@ -77,7 +77,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(depsgraph, scene, ob, CD_MASK_BAREMESH, modifierIndex); mvert = dm->getVertArray(dm); mloop = dm->getLoopArray(dm); diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c index 5545eba8764..34b185417e3 100644 --- a/source/blender/blenkernel/intern/font.c +++ b/source/blender/blenkernel/intern/font.c @@ -1022,7 +1022,7 @@ makebreak: /* top and top-baseline are the same when text-boxes are used */ if (cu->align_y != CU_ALIGN_Y_TOP && i_textbox < slen) { /* all previous textboxes are 'full', only align the last used text-box */ - float yoff; + float yoff = 0.0f; int lines; struct CharTrans *ct_last, *ct_textbox; @@ -1051,7 +1051,7 @@ makebreak: else { /* non text-box case handled separately */ ct = chartransdata; - float yoff; + float yoff = 0.0f; if (cu->align_y == CU_ALIGN_Y_TOP) { yoff = -linedist; 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..f2c9bfdd974 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); -} +#include "DEG_depsgraph.h" /** 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_BEGIN(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_BEGIN(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(struct Depsgraph *depsgraph, 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 @@ -352,7 +354,7 @@ void BKE_group_handle_recalc_and_update(EvaluationContext *eval_ctx, Scene *scen go->ob->recalc = go->recalc; group_replaces_nla(parent, go->ob, 's'); - BKE_object_handle_update(eval_ctx, scene, go->ob); + BKE_object_handle_update(depsgraph, scene, go->ob); group_replaces_nla(parent, go->ob, 'e'); /* leave recalc tags in case group members are in normal scene */ @@ -367,12 +369,21 @@ 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_BEGIN(group, object) + { + if (object->id.recalc & ID_RECALC_ALL) { + BKE_object_handle_update(depsgraph, scene, object); } } + FOREACH_GROUP_OBJECT_END; } } + +/* ******** Dependency graph evaluation ******** */ + +void BKE_group_eval_view_layers(struct Depsgraph *depsgraph, + Group *group) +{ + DEG_debug_print_eval(depsgraph, __func__, group->id.name, group); + BKE_layer_eval_view_layer(depsgraph, &group->id, group->view_layer); +} diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c index 3ac8abd55f6..e1d1211f6e5 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" @@ -50,6 +51,7 @@ #include "BLI_ghash.h" #include "BLI_linklist_lockfree.h" #include "BLI_string.h" +#include "BLI_fileops.h" #include "BLI_threads.h" #include "BKE_icons.h" @@ -63,6 +65,14 @@ #include "IMB_imbuf_types.h" #include "IMB_thumbs.h" +/** + * Only allow non-managed icons to be removed (by Python for eg). + * Previews & ID's have their own functions to remove icons. + */ +enum { + ICON_FLAG_MANAGED = (1 << 0), +}; + /* GLOBALS */ static GHash *gIcons = NULL; @@ -85,6 +95,19 @@ static void icon_free(void *val) Icon *icon = val; if (icon) { + if (icon->obj_type == ICON_DATA_GEOM) { + struct Icon_Geom *obj = icon->obj; + if (obj->mem) { + /* coords & colors are part of this memory. */ + MEM_freeN((void *)obj->mem); + } + else { + MEM_freeN((void *)obj->coords); + MEM_freeN((void *)obj->colors); + } + MEM_freeN(icon->obj); + } + if (icon->drawinfo_free) { icon->drawinfo_free(icon->drawinfo); } @@ -95,6 +118,22 @@ static void icon_free(void *val) } } +static void icon_free_data(Icon *icon) +{ + if (icon->obj_type == ICON_DATA_ID) { + ((ID *)(icon->obj))->icon_id = 0; + } + else if (icon->obj_type == ICON_DATA_PREVIEW) { + ((PreviewImage *)(icon->obj))->icon_id = 0; + } + else if (icon->obj_type == ICON_DATA_GEOM) { + ((struct Icon_Geom *)(icon->obj))->icon_id = 0; + } + else { + BLI_assert(0); + } +} + /* create an id for a new icon and make sure that ids from deleted icons get reused * after the integer number range is used up */ static int get_next_free_id(void) @@ -284,6 +323,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; @@ -476,6 +516,7 @@ void BKE_icon_changed(const int icon_id) if (icon) { /* We *only* expect ID-tied icons here, not non-ID icon/preview! */ BLI_assert(icon->id_type != 0); + BLI_assert(icon->obj_type == ICON_DATA_ID); /* Do not enforce creation of previews for valid ID types using BKE_previewimg_id_ensure() here , * we only want to ensure *existing* preview images are properly tagged as changed/invalid, that's all. */ @@ -492,22 +533,31 @@ void BKE_icon_changed(const int icon_id) } } -static int icon_id_ensure_create_icon(struct ID *id) +static Icon *icon_create(int icon_id, int obj_type, void *obj) { - BLI_assert(BLI_thread_is_main()); - - Icon *new_icon = NULL; + Icon *new_icon = MEM_mallocN(sizeof(Icon), __func__); - new_icon = MEM_mallocN(sizeof(Icon), __func__); - - new_icon->obj = id; - new_icon->id_type = GS(id->name); + new_icon->obj_type = obj_type; + new_icon->obj = obj; + new_icon->id_type = 0; + new_icon->flag = 0; /* next two lines make sure image gets created */ new_icon->drawinfo = NULL; new_icon->drawinfo_free = NULL; - BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(id->icon_id), new_icon); + BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(icon_id), new_icon); + + return new_icon; +} + +static int icon_id_ensure_create_icon(struct ID *id) +{ + BLI_assert(BLI_thread_is_main()); + + Icon *icon = icon_create(id->icon_id, ICON_DATA_ID, id); + icon->id_type = GS(id->name); + icon->flag = ICON_FLAG_MANAGED; return id->icon_id; } @@ -542,8 +592,6 @@ int BKE_icon_id_ensure(struct ID *id) */ int BKE_icon_preview_ensure(ID *id, PreviewImage *preview) { - Icon *new_icon = NULL; - if (!preview || G.background) return 0; @@ -574,16 +622,8 @@ int BKE_icon_preview_ensure(ID *id, PreviewImage *preview) return icon_id_ensure_create_icon(id); } - new_icon = MEM_mallocN(sizeof(Icon), __func__); - - new_icon->obj = preview; - new_icon->id_type = 0; /* Special, tags as non-ID icon/preview. */ - - /* next two lines make sure image gets created */ - new_icon->drawinfo = NULL; - new_icon->drawinfo_free = NULL; - - BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(preview->icon_id), new_icon); + Icon *icon = icon_create(preview->icon_id, ICON_DATA_PREVIEW, preview); + icon->flag = ICON_FLAG_MANAGED; return preview->icon_id; } @@ -645,21 +685,116 @@ void BKE_icon_id_delete(struct ID *id) /** * Remove icon and free data. */ -void BKE_icon_delete(const int icon_id) +bool BKE_icon_delete(const int icon_id) { - Icon *icon; + if (icon_id == 0) { + /* no icon defined for library object */ + return false; + } - if (!icon_id) return; /* no icon defined for library object */ + Icon *icon = BLI_ghash_popkey(gIcons, SET_INT_IN_POINTER(icon_id), NULL); + if (icon) { + icon_free_data(icon); + icon_free(icon); + return true; + } + else { + return false; + } +} - icon = BLI_ghash_popkey(gIcons, SET_INT_IN_POINTER(icon_id), NULL); +bool BKE_icon_delete_unmanaged(const int icon_id) +{ + if (icon_id == 0) { + /* no icon defined for library object */ + return false; + } + Icon *icon = BLI_ghash_popkey(gIcons, SET_INT_IN_POINTER(icon_id), NULL); if (icon) { - if (icon->id_type != 0) { - ((ID *)(icon->obj))->icon_id = 0; + if (UNLIKELY(icon->flag & ICON_FLAG_MANAGED)) { + BLI_ghash_insert(gIcons, SET_INT_IN_POINTER(icon_id), icon); + return false; } else { - ((PreviewImage *)(icon->obj))->icon_id = 0; + icon_free_data(icon); + icon_free(icon); + return true; } - icon_free(icon); } + else { + return false; + } +} + +/* -------------------------------------------------------------------- */ +/** \name Geometry Icon + * \{ */ + +int BKE_icon_geom_ensure(struct Icon_Geom *geom) +{ + BLI_assert(BLI_thread_is_main()); + + if (geom->icon_id) { + return geom->icon_id; + } + + geom->icon_id = get_next_free_id(); + + icon_create(geom->icon_id, ICON_DATA_GEOM, geom); + /* Not managed for now, we may want this to be configurable per icon). */ + + return geom->icon_id; +} + +struct Icon_Geom *BKE_icon_geom_from_memory(const uchar *data, size_t data_len) +{ + BLI_assert(BLI_thread_is_main()); + if (data_len <= 8) { + goto fail; + } + /* Skip the header. */ + data_len -= 8; + const int div = 3 * 2 * 3; + const int coords_len = data_len / div; + if (coords_len * div != data_len) { + goto fail; + } + + const uchar header[4] = {'V', 'C', 'O', 0}; + const uchar *p = data; + if (memcmp(p, header, ARRAY_SIZE(header)) != 0) { + goto fail; + } + p += 4; + + struct Icon_Geom *geom = MEM_mallocN(sizeof(*geom), __func__); + geom->coords_range[0] = (int)*p++; + geom->coords_range[1] = (int)*p++; + /* x, y ignored for now */ + p += 2; + + geom->coords_len = coords_len; + geom->coords = (const void *)p; + geom->colors = (const void *)(p + (data_len / 3)); + geom->icon_id = 0; + geom->mem = data; + return geom; + +fail: + MEM_freeN((void *)data); + return NULL; +} + +struct Icon_Geom *BKE_icon_geom_from_file(const char *filename) +{ + BLI_assert(BLI_thread_is_main()); + size_t data_len; + uchar *data = BLI_file_read_binary_as_mem(filename, 0, &data_len); + if (data == NULL) { + return NULL; + } + return BKE_icon_geom_from_memory(data, data_len); } + +/** \} */ diff --git a/source/blender/blenkernel/intern/icons_rasterize.c b/source/blender/blenkernel/intern/icons_rasterize.c new file mode 100644 index 00000000000..24576c24953 --- /dev/null +++ b/source/blender/blenkernel/intern/icons_rasterize.c @@ -0,0 +1,146 @@ +/* + * ***** 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/icons_rasterize.c + * \ingroup bke + */ +#include "MEM_guardedalloc.h" + +#include "BLI_utildefines.h" +#include "BLI_bitmap_draw_2d.h" +#include "BLI_math_geom.h" + +#include "IMB_imbuf.h" +#include "IMB_imbuf_types.h" + +#include "BKE_icons.h" + +#include "BLI_strict_flags.h" + +struct UserRasterInfo { + int pt[3][2]; + const uint *color; + /* only for smooth shading */ + struct { + float pt_fl[3][2]; + uint color_u[3][4]; + } smooth; + int rect_size[2]; + uint *rect; +}; + +static void tri_fill_flat(int x, int x_end, int y, void *user_data) +{ + struct UserRasterInfo *data = user_data; + uint *p = &data->rect[(y * data->rect_size[1]) + x]; + uint col = data->color[0]; + while (x++ != x_end) { + *p++ = col; + } +} + +static void tri_fill_smooth(int x, int x_end, int y, void *user_data) +{ + struct UserRasterInfo *data = user_data; + uint *p = &data->rect[(y * data->rect_size[1]) + x]; + float pt_step_fl[2] = {(float)x, (float)y}; + while (x++ != x_end) { + float w[3]; + barycentric_weights_v2_clamped(UNPACK3(data->smooth.pt_fl), pt_step_fl, w); + + uint col_u[4] = {0, 0, 0, 0}; + for (uint corner = 0; corner < 3; corner++) { + for (uint chan = 0; chan < 4; chan++) { + col_u[chan] += data->smooth.color_u[corner][chan] * (uint)(w[corner] * 255.0f); + } + } + union { + uint as_u32; + uchar as_bytes[4]; + } col; + col.as_bytes[0] = (uchar)(col_u[0] / 255); + col.as_bytes[1] = (uchar)(col_u[1] / 255); + col.as_bytes[2] = (uchar)(col_u[2] / 255); + col.as_bytes[3] = (uchar)(col_u[3] / 255); + *p++ = col.as_u32; + + pt_step_fl[0] += 1.0f; + } +} + +ImBuf *BKE_icon_geom_rasterize( + const struct Icon_Geom *geom, + const unsigned int size_x, const unsigned int size_y) +{ + const int coords_len = geom->coords_len; + + const uchar (*pos)[2] = geom->coords; + const uint *col = (void *)geom->colors; + + /* TODO(campbell): Currently rasterizes to fixed size, then scales. + * Should rasterize to double size for eg instead. */ + const int rect_size[2] = {max_ii(256, (int)size_x * 2), max_ii(256, (int)size_y * 2)}; + + ImBuf *ibuf = IMB_allocImBuf((uint)rect_size[0], (uint)rect_size[1], 32, IB_rect); + + struct UserRasterInfo data; + + data.rect_size[0] = rect_size[0]; + data.rect_size[1] = rect_size[1]; + + data.rect = ibuf->rect; + + float scale[2]; + const bool use_scale = (rect_size[0] != 256) || (rect_size[1] != 256); + + if (use_scale) { + scale[0] = ((float)rect_size[0] / 256.0f); + scale[1] = ((float)rect_size[1] / 256.0f); + } + + for (int t = 0; t < coords_len; t += 1, pos += 3, col += 3) { + if (use_scale) { + ARRAY_SET_ITEMS(data.pt[0], (int)(pos[0][0] * scale[0]), (int)(pos[0][1] * scale[1])); + ARRAY_SET_ITEMS(data.pt[1], (int)(pos[1][0] * scale[0]), (int)(pos[1][1] * scale[1])); + ARRAY_SET_ITEMS(data.pt[2], (int)(pos[2][0] * scale[0]), (int)(pos[2][1] * scale[1])); + } + else { + ARRAY_SET_ITEMS(data.pt[0], UNPACK2(pos[0])); + ARRAY_SET_ITEMS(data.pt[1], UNPACK2(pos[1])); + ARRAY_SET_ITEMS(data.pt[2], UNPACK2(pos[2])); + } + data.color = col; + if ((col[0] == col[1]) && (col[0] == col[2])) { + BLI_bitmap_draw_2d_tri_v2i(UNPACK3(data.pt), tri_fill_flat, &data); + } + else { + ARRAY_SET_ITEMS(data.smooth.pt_fl[0], UNPACK2_EX((float), data.pt[0], )); + ARRAY_SET_ITEMS(data.smooth.pt_fl[1], UNPACK2_EX((float), data.pt[1], )); + ARRAY_SET_ITEMS(data.smooth.pt_fl[2], UNPACK2_EX((float), data.pt[2], )); + ARRAY_SET_ITEMS(data.smooth.color_u[0], UNPACK4_EX((uint), ((uchar *)(col + 0)), )); + ARRAY_SET_ITEMS(data.smooth.color_u[1], UNPACK4_EX((uint), ((uchar *)(col + 1)), )); + ARRAY_SET_ITEMS(data.smooth.color_u[2], UNPACK4_EX((uint), ((uchar *)(col + 2)), )); + BLI_bitmap_draw_2d_tri_v2i(UNPACK3(data.pt), tri_fill_smooth, &data); + } + } + IMB_scaleImBuf(ibuf, size_x, size_y); + return ibuf; +} 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 5c13ba7907d..87e5ed8cc1e 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. * @@ -1068,4 +1095,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 e8b5ce77613..50b1756ff87 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -82,6 +82,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" @@ -369,7 +370,6 @@ static void image_init(Image *ima, short source, short type) ima->ok = IMA_OK; - ima->xrep = ima->yrep = 1; ima->aspx = ima->aspy = 1.0; ima->gen_x = 1024; ima->gen_y = 1024; ima->gen_type = IMA_GENTYPE_GRID; @@ -472,12 +472,10 @@ void BKE_image_copy_data(Main *UNUSED(bmain), Image *ima_dst, const Image *ima_s BLI_listbase_clear(&ima_dst->anims); - ima_dst->totbind = 0; for (int i = 0; i < TEXTARGET_COUNT; i++) { ima_dst->bindcode[i] = 0; ima_dst->gputexture[i] = NULL; } - ima_dst->repbind = NULL; if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) { BKE_previewimg_id_copy(&ima_dst->id, &ima_src->id); @@ -2653,19 +2651,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/ipo.c b/source/blender/blenkernel/intern/ipo.c index fcbc25ebad5..941c7eb2a87 100644 --- a/source/blender/blenkernel/intern/ipo.c +++ b/source/blender/blenkernel/intern/ipo.c @@ -46,7 +46,6 @@ /* since we have versioning code here */ #define DNA_DEPRECATED_ALLOW -#include "DNA_actuator_types.h" #include "DNA_anim_types.h" #include "DNA_constraint_types.h" #include "DNA_camera_types.h" @@ -146,17 +145,6 @@ static AdrBit2Path ob_layer_bits[] = { {(1 << 19), "layers", 19} }; -/* Material mode */ -static AdrBit2Path ma_mode_bits[] = { -// {MA_TRACEBLE, "traceable", 0}, -// {MA_SHADOW, "shadow", 0}, -// {MA_SHLESS, "shadeless", 0}, -// ... - {MA_RAYTRANSP, "transparency", 0}, - {MA_RAYMIRROR, "raytrace_mirror.enabled", 0}, -// {MA_HALO, "type", MA_TYPE_HALO} -}; - /* ----------------- */ /* quick macro for returning the appropriate array for adrcode_bitmaps_to_paths() */ @@ -173,9 +161,6 @@ static AdrBit2Path *adrcode_bitmaps_to_paths(int blocktype, int adrcode, int *to if ((blocktype == ID_OB) && (adrcode == OB_LAY)) { RET_ABP(ob_layer_bits); } - else if ((blocktype == ID_MA) && (adrcode == MA_MODE)) { - RET_ABP(ma_mode_bits); - } // XXX TODO: add other types... /* Normal curve */ @@ -1768,23 +1753,6 @@ void do_versions_ipos_to_animato(Main *main) ipo_to_animdata(id, ob->ipo, NULL, NULL, NULL); id_us_min(&ob->ipo->id); ob->ipo = NULL; - - { - /* If we have any empty action actuators, assume they were - * converted IPO Actuators using the object IPO */ - bActuator *act; - bActionActuator *aa; - - for (act = ob->actuators.first; act; act = act->next) { - /* Any actuators set to ACT_IPO at this point are actually Action Actuators that - * need this converted IPO to finish converting the actuator. */ - if (act->type == ACT_IPO) { - aa = (bActionActuator *)act->data; - aa->act = ob->adt->action; - act->type = ACT_ACTION; - } - } - } } } diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c index 2714c4f43a1..195280aad5a 100644 --- a/source/blender/blenkernel/intern/lamp.c +++ b/source/blender/blenkernel/intern/lamp.c @@ -64,42 +64,30 @@ void BKE_lamp_init(Lamp *la) la->spotsize = DEG2RADF(45.0f); la->spotblend = 0.15f; la->att2 = 1.0f; - la->mode = LA_SHAD_BUF; + la->mode = LA_SHADOW; 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; - la->compressthresh = 0.05f; - la->ray_samp = la->ray_sampy = la->ray_sampz = 1; la->area_size = la->area_sizey = la->area_sizez = 0.1f; la->buffers = 1; - la->buftype = LA_SHADBUF_HALFWAY; - la->ray_samp_method = LA_SAMP_HALTON; - la->adapt_thresh = 0.001f; la->preview = NULL; la->falloff_type = LA_FALLOFF_INVSQUARE; la->coeff_const = 1.0f; la->coeff_lin = 0.0f; la->coeff_quad = 0.0f; la->curfalloff = curvemapping_add(1, 0.0f, 1.0f, 1.0f, 0.0f); - la->sun_effect_type = 0; - la->horizon_brightness = 1.0; - la->spread = 1.0; - la->sun_brightness = 1.0; - la->sun_size = 1.0; - la->backscattered_light = 1.0f; - la->atm_turbidity = 2.0f; - la->atm_inscattering_factor = 1.0f; - la->atm_extinction_factor = 1.0f; - la->atm_distance_factor = 1.0f; - la->sun_intensity = 1.0f; - la->skyblendtype = MA_RAMP_ADD; - la->skyblendfac = 1.0f; - 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); } @@ -125,13 +113,6 @@ Lamp *BKE_lamp_add(Main *bmain, const char *name) */ void BKE_lamp_copy_data(Main *bmain, Lamp *la_dst, const Lamp *la_src, const int flag) { - for (int a = 0; a < MAX_MTEX; a++) { - if (la_dst->mtex[a]) { - la_dst->mtex[a] = MEM_mallocN(sizeof(*la_dst->mtex[a]), __func__); - *la_dst->mtex[a] = *la_src->mtex[a]; - } - } - la_dst->curfalloff = curvemapping_copy(la_src->curfalloff); if (la_src->nodetree) { @@ -164,18 +145,8 @@ Lamp *BKE_lamp_localize(Lamp *la) * * ... Once f*** nodes are fully converted to that too :( */ - Lamp *lan; - int a; - - lan = BKE_libblock_copy_nolib(&la->id, false); + Lamp *lan = BKE_libblock_copy_nolib(&la->id, false); - for (a = 0; a < MAX_MTEX; a++) { - if (lan->mtex[a]) { - lan->mtex[a] = MEM_mallocN(sizeof(MTex), __func__); - memcpy(lan->mtex[a], la->mtex[a], sizeof(MTex)); - } - } - lan->curfalloff = curvemapping_copy(la->curfalloff); if (la->nodetree) @@ -193,12 +164,6 @@ void BKE_lamp_make_local(Main *bmain, Lamp *la, const bool lib_local) void BKE_lamp_free(Lamp *la) { - int a; - - for (a = 0; a < MAX_MTEX; a++) { - MEM_SAFE_FREE(la->mtex[a]); - } - BKE_animdata_free((ID *)la, false); curvemapping_free(la->curfalloff); @@ -214,41 +179,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 4b9748133d7..609c4b95dab 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_key.h" #include "BKE_lattice.h" @@ -66,11 +65,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) { @@ -313,6 +307,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); @@ -601,7 +597,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; @@ -609,12 +605,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 */ @@ -705,7 +699,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; @@ -764,7 +758,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]); } @@ -787,7 +781,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]); } @@ -798,7 +792,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]); } } @@ -813,7 +807,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]); } } @@ -823,7 +817,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; @@ -842,7 +836,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); @@ -855,7 +849,7 @@ void curve_deform_vector(Scene *scene, Object *cuOb, Object *target, } -void lattice_deform_verts(Object *laOb, Object *target, DerivedMesh *dm, +void lattice_deform_verts(Object *laOb, Object *target, Mesh *mesh, float (*vertexCos)[3], int numVerts, const char *vgroup, float fac) { LatticeDeformData *lattice_deform_data; @@ -873,8 +867,8 @@ void lattice_deform_verts(Object *laOb, Object *target, DerivedMesh *dm, */ if (target && target->type == OB_MESH) { /* if there's derived data without deformverts, don't use vgroups */ - if (dm) { - use_vgroups = (dm->getVertDataArray(dm, CD_MDEFORMVERT) != NULL); + if (mesh) { + use_vgroups = (mesh->dvert != NULL); } else { Mesh *me = target->data; @@ -890,12 +884,10 @@ void lattice_deform_verts(Object *laOb, Object *target, DerivedMesh *dm, const int defgrp_index = defgroup_name_index(target, vgroup); float weight; - if (defgrp_index >= 0 && (me->dvert || dm)) { - MDeformVert *dvert = me->dvert; + if (defgrp_index >= 0 && (me->dvert || mesh)) { + MDeformVert *dvert = mesh ? mesh->dvert : me->dvert; for (a = 0; a < numVerts; a++, dvert++) { - if (dm) dvert = dm->getVertData(dm, a, CD_MDEFORMVERT); - weight = defvert_find_weight(dvert, defgrp_index); if (weight > 0.0f) @@ -1032,13 +1024,14 @@ 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(struct Depsgraph *depsgraph, Scene *scene, Object *ob) { Lattice *lt = ob->data; VirtualModifierData virtualModifierData; ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); float (*vertexCos)[3] = NULL; int numVerts, editmode = (lt->editlatt != NULL); + const ModifierEvalContext mectx = {depsgraph, ob, 0}; if (ob->curve_cache) { BKE_displist_free(&ob->curve_cache->disp); @@ -1059,7 +1052,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); + modifier_deformVerts_DM_deprecated(md, &mectx, NULL, vertexCos, numVerts); } /* always displist to make this work like derivedmesh */ @@ -1233,8 +1226,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(struct Depsgraph *UNUSED(depsgraph), 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..d3b47681a75 --- /dev/null +++ b/source/blender/blenkernel/intern/layer.c @@ -0,0 +1,2539 @@ +/* + * ***** 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_array.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 "BKE_object.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 "DEG_depsgraph.h" +#include "DEG_depsgraph_debug.h" +#include "DEG_depsgraph_query.h" + +#include "DRW_engine.h" + +#include "MEM_guardedalloc.h" + +/* 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 default view layer to view in workspaces if there is + * none linked to the workspace yet. */ +ViewLayer *BKE_view_layer_default_view(const Scene *scene) +{ + /* TODO: it makes more sense to have the Viewport layer as the default, + * but this breaks view layer tests so change it later. */ +#if 0 + for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + if (!(view_layer->flag & VIEW_LAYER_RENDER)) { + return view_layer; + } + } + + BLI_assert(scene->view_layers.first); + return scene->view_layers.first; +#else + return BKE_view_layer_default_render(scene); +#endif +} + +/* Returns the default view layer to render if we need to render just one. */ +ViewLayer *BKE_view_layer_default_render(const Scene *scene) +{ + for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + if (view_layer->flag & VIEW_LAYER_RENDER) { + return view_layer; + } + } + + BLI_assert(scene->view_layers.first); + return scene->view_layers.first; +} + +/** + * 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) +{ + 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) +{ + BLI_assert(scene->view_layers.first); + return scene->view_layers.first; +} + +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_SAFE_FREE(view_layer->object_bases_array); + + 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; + } + } + + view_layer_dst->object_bases_array = NULL; +} + +/** + * 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; +} + +/* ---------------------------------------------------------------------- */ + +/** + * Return the first matching LayerCollection in the ViewLayer for the SceneCollection. + */ +LayerCollection *BKE_layer_collection_first_from_scene_collection(ViewLayer *view_layer, const SceneCollection *scene_collection) +{ + for (LayerCollection *layer_collection = view_layer->layer_collections.first; + layer_collection != NULL; + layer_collection = layer_collection->next) + { + LayerCollection *found = find_layer_collection_by_scene_collection(layer_collection, scene_collection); + + if (found != NULL) { + return found; + } + } + return NULL; +} + +/** + * See if view layer has the scene collection linked directly, or indirectly (nested) + */ +bool BKE_view_layer_has_collection(ViewLayer *view_layer, const SceneCollection *scene_collection) +{ + return BKE_layer_collection_first_from_scene_collection(view_layer, scene_collection) != NULL; +} + +/** + * 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 */ + +/* -------------------------------------------------------------------- */ +/** \name Private Iterator Helpers + * \{ */ + +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; + } +} + +/* -------------------------------------------------------------------- */ +/** \name BKE_view_layer_selected_objects_iterator + * See: #FOREACH_SELECTED_OBJECT_BEGIN + * \{ */ + +void BKE_view_layer_selected_objects_iterator_begin(BLI_Iterator *iter, void *data_in) +{ + objects_iterator_begin(iter, data_in, BASE_SELECTED); +} + +void BKE_view_layer_selected_objects_iterator_next(BLI_Iterator *iter) +{ + objects_iterator_next(iter, BASE_SELECTED); +} + +void BKE_view_layer_selected_objects_iterator_end(BLI_Iterator *UNUSED(iter)) +{ + /* do nothing */ +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name BKE_view_layer_selected_objects_iterator + * \{ */ + +void BKE_view_layer_visible_objects_iterator_begin(BLI_Iterator *iter, void *data_in) +{ + objects_iterator_begin(iter, data_in, BASE_VISIBLED); +} + +void BKE_view_layer_visible_objects_iterator_next(BLI_Iterator *iter) +{ + objects_iterator_next(iter, BASE_VISIBLED); +} + +void BKE_view_layer_visible_objects_iterator_end(BLI_Iterator *UNUSED(iter)) +{ + /* do nothing */ +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name BKE_view_layer_selected_bases_iterator + * \{ */ + +void BKE_view_layer_selected_bases_iterator_begin(BLI_Iterator *iter, void *data_in) +{ + object_bases_iterator_begin(iter, data_in, BASE_SELECTED); +} + +void BKE_view_layer_selected_bases_iterator_next(BLI_Iterator *iter) +{ + object_bases_iterator_next(iter, BASE_SELECTED); +} + +void BKE_view_layer_selected_bases_iterator_end(BLI_Iterator *UNUSED(iter)) +{ + /* do nothing */ +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name BKE_view_layer_visible_bases_iterator + * \{ */ + +void BKE_view_layer_visible_bases_iterator_begin(BLI_Iterator *iter, void *data_in) +{ + object_bases_iterator_begin(iter, data_in, BASE_VISIBLED); +} + +void BKE_view_layer_visible_bases_iterator_next(BLI_Iterator *iter) +{ + object_bases_iterator_next(iter, BASE_VISIBLED); +} + +void BKE_view_layer_visible_bases_iterator_end(BLI_Iterator *UNUSED(iter)) +{ + /* do nothing */ +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name BKE_view_layer_renderable_objects_iterator + * \{ */ + +void BKE_view_layer_renderable_objects_iterator_begin(BLI_Iterator *iter, void *data_in) +{ + struct 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_view_layer_renderable_objects_iterator_next(iter); +} + +void BKE_view_layer_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; + + struct 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_default_render(data->iter.set); + data->base_temp.next = view_layer->object_bases.first; + data->iter.base = &data->base_temp; + return; + } + + iter->valid = false; +} + +void BKE_view_layer_renderable_objects_iterator_end(BLI_Iterator *UNUSED(iter)) +{ + /* Do nothing - iter->data was static allocated, we can't free it. */ +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name BKE_view_layer_bases_in_mode_iterator + * \{ */ + +void BKE_view_layer_bases_in_mode_iterator_begin(BLI_Iterator *iter, void *data_in) +{ + struct ObjectsInModeIteratorData *data = data_in; + Base *base = data->base_active; + + /* when there are no objects */ + if (base == NULL) { + iter->valid = false; + return; + } + iter->data = data_in; + iter->current = base; +} + +void BKE_view_layer_bases_in_mode_iterator_next(BLI_Iterator *iter) +{ + struct ObjectsInModeIteratorData *data = iter->data; + Base *base = iter->current; + + if (base == data->base_active) { + /* first step */ + base = data->view_layer->object_bases.first; + if (base == data->base_active) { + base = base->next; + } + } + else { + base = base->next; + } + + while (base) { + if ((base->flag & BASE_SELECTED) != 0 && + (base->object->type == data->base_active->object->type) && + (base != data->base_active) && + (base->object->mode & data->object_mode)) + { + iter->current = base; + return; + } + base = base->next; + } + iter->valid = false; +} + +void BKE_view_layer_bases_in_mode_iterator_end(BLI_Iterator *UNUSED(iter)) +{ + /* do nothing */ +} + +/** \} */ + +/* 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); + } +} + +static void layer_eval_layer_collection_pre(Depsgraph *depsgraph, ID *owner_id, ViewLayer *view_layer) +{ + DEG_debug_print_eval(depsgraph, __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(Depsgraph *depsgraph, LayerCollection *layer_collection) +{ + if (layer_collection->flag_evaluated & COLLECTION_DISABLED) { + return false; + } + + if (DEG_get_mode(depsgraph) == DAG_EVAL_VIEWPORT) { + return (layer_collection->flag_evaluated & COLLECTION_VIEWPORT) != 0; + } + else { + return (layer_collection->flag_evaluated & COLLECTION_RENDER) != 0; + } +} + +static void layer_eval_layer_collection(Depsgraph *depsgraph, + LayerCollection *layer_collection, + LayerCollection *parent_layer_collection) +{ + DEG_debug_print_eval_parent_typed( + depsgraph, + __func__, + layer_collection->scene_collection->name, + layer_collection->scene_collection, + collection_type_lookup[layer_collection->scene_collection->type], + "parent", + (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(depsgraph, 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(depsgraph, 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; + } + } +} + +static void layer_eval_layer_collection_post(Depsgraph *depsgraph, ViewLayer *view_layer) +{ + DEG_debug_print_eval(depsgraph, __func__, view_layer->name, view_layer); + /* Create array of bases, for fast index-based lookup. */ + const int num_object_bases = BLI_listbase_count(&view_layer->object_bases); + MEM_SAFE_FREE(view_layer->object_bases_array); + view_layer->object_bases_array = MEM_malloc_arrayN( + num_object_bases, sizeof(Base *), "view_layer->object_bases_array"); + int base_index = 0; + for (Base *base = view_layer->object_bases.first; base; base = base->next) { + /* if base is not selectabled, clear select. */ + if ((base->flag & BASE_SELECTABLED) == 0) { + base->flag &= ~BASE_SELECTED; + } + /* Store base in the array. */ + view_layer->object_bases_array[base_index++] = base; + } +} + +static void layer_eval_collections_recurse(Depsgraph *depsgraph, + ListBase *layer_collections, + LayerCollection *parent_layer_collection) +{ + for (LayerCollection *layer_collection = layer_collections->first; + layer_collection != NULL; + layer_collection = layer_collection->next) + { + layer_eval_layer_collection(depsgraph, + layer_collection, + parent_layer_collection); + layer_eval_collections_recurse(depsgraph, + &layer_collection->layer_collections, + layer_collection); + } +} + +void BKE_layer_eval_view_layer(struct Depsgraph *depsgraph, + struct ID *owner_id, + ViewLayer *view_layer) +{ + layer_eval_layer_collection_pre(depsgraph, owner_id, view_layer); + layer_eval_collections_recurse(depsgraph, + &view_layer->layer_collections, + NULL); + layer_eval_layer_collection_post(depsgraph, view_layer); +} + +void BKE_layer_eval_view_layer_indexed(struct Depsgraph *depsgraph, + struct ID *owner_id, + int view_layer_index) +{ + BLI_assert(GS(owner_id->name) == ID_SCE); + BLI_assert(view_layer_index >= 0); + Scene *scene = (Scene *)owner_id; + ViewLayer *view_layer = BLI_findlink(&scene->view_layers, view_layer_index); + BLI_assert(view_layer != NULL); + BKE_layer_eval_view_layer(depsgraph, owner_id, view_layer); +} + +/** + * Free any static allocated memory. + */ +void BKE_layer_exit(void) +{ + layer_collection_engine_settings_validate_free(); +} diff --git a/source/blender/blenkernel/intern/layer_utils.c b/source/blender/blenkernel/intern/layer_utils.c new file mode 100644 index 00000000000..94bac8a33d6 --- /dev/null +++ b/source/blender/blenkernel/intern/layer_utils.c @@ -0,0 +1,125 @@ +/* + * ***** 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/layer_utils.c + * \ingroup bke + */ + +#include <string.h> + +#include "BLI_array.h" +#include "BLI_listbase.h" + +#include "BKE_collection.h" +#include "BKE_editmesh.h" +#include "BKE_layer.h" + +#include "DNA_ID.h" +#include "DNA_layer_types.h" +#include "DNA_object_types.h" +#include "DNA_mesh_types.h" +#include "DNA_scene_types.h" + +#include "MEM_guardedalloc.h" + +Base **BKE_view_layer_array_from_bases_in_mode_params( + ViewLayer *view_layer, uint *r_len, + const struct ObjectsInModeParams *params) +{ + if (params->no_dup_data) { + FOREACH_BASE_IN_MODE_BEGIN(view_layer, params->object_mode, base_iter) { + ID *id = base_iter->object->data; + if (id) { + id->tag |= LIB_TAG_DOIT; + } + } FOREACH_BASE_IN_MODE_END; + } + + Base **base_array = NULL; + BLI_array_declare(base_array); + + FOREACH_BASE_IN_MODE_BEGIN(view_layer, params->object_mode, base_iter) { + if (params->filter_fn) { + if (!params->filter_fn(base_iter->object, params->filter_userdata)) { + continue; + } + } + if (params->no_dup_data) { + ID *id = base_iter->object->data; + if (id) { + if (id->tag & LIB_TAG_DOIT) { + id->tag &= ~LIB_TAG_DOIT; + } + else { + continue; + } + } + } + BLI_array_append(base_array, base_iter); + } FOREACH_BASE_IN_MODE_END; + + if (base_array != NULL) { + base_array = MEM_reallocN(base_array, sizeof(*base_array) * BLI_array_len(base_array)); + } + *r_len = BLI_array_len(base_array); + return base_array; +} + +Object **BKE_view_layer_array_from_objects_in_mode_params( + ViewLayer *view_layer, uint *r_len, + const struct ObjectsInModeParams *params) +{ + Base **base_array = BKE_view_layer_array_from_bases_in_mode_params( + view_layer, r_len, params); + if (base_array != NULL) { + for (uint i = 0; i < *r_len; i++) { + ((Object **)base_array)[i] = base_array[i]->object; + } + } + return (Object **)base_array; +} + +bool BKE_view_layer_filter_edit_mesh_has_uvs(Object *ob, void *UNUSED(user_data)) +{ + if (ob->type == OB_MESH) { + Mesh *me = ob->data; + BMEditMesh *em = me->edit_btmesh; + if (em != NULL) { + if (CustomData_get_offset(&em->bm->ldata, CD_MLOOPUV) != -1) { + return true; + } + } + } + return false; +} + +bool BKE_view_layer_filter_edit_mesh_has_edges(Object *ob, void *UNUSED(user_data)) +{ + if (ob->type == OB_MESH) { + Mesh *me = ob->data; + BMEditMesh *em = me->edit_btmesh; + if (em != NULL) { + if (em->bm->totedge != 0) { + return true; + } + } + } + return false; +} diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 292f37b5ce9..d23d48752b6 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) { @@ -847,6 +930,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: @@ -877,6 +962,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; } @@ -962,11 +1049,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); } /** @@ -1015,6 +1102,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); @@ -1022,6 +1110,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); @@ -1074,6 +1163,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); @@ -1089,6 +1179,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 @@ -1146,7 +1237,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 { @@ -1205,6 +1296,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; @@ -1282,7 +1376,7 @@ static void id_copy_animdata(Main *bmain, ID *id, const bool do_action) if (adt) { IdAdtTemplate *iat = (IdAdtTemplate *)id; - iat->adt = BKE_animdata_copy(bmain, iat->adt, do_action); /* could be set to false, need to investigate */ + iat->adt = BKE_animdata_copy(bmain, iat->adt, do_action, true); /* could be set to false, need to investigate */ } } @@ -1325,12 +1419,27 @@ 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 */ - BLI_assert((flag & LIB_ID_COPY_ACTIONS) == 0 || (flag & LIB_ID_CREATE_NO_MAIN) == 0); - id_copy_animdata(bmain, new_id, (flag & LIB_ID_COPY_ACTIONS) != 0 && (flag & LIB_ID_CREATE_NO_MAIN) == 0); + if ((flag & LIB_ID_COPY_NO_ANIMDATA) == 0) { + BLI_assert((flag & LIB_ID_COPY_ACTIONS) == 0 || (flag & LIB_ID_CREATE_NO_MAIN) == 0); + id_copy_animdata(bmain, new_id, (flag & LIB_ID_COPY_ACTIONS) != 0 && (flag & LIB_ID_CREATE_NO_MAIN) == 0); + } + else if (id_can_have_animdata(new_id)) { + IdAdtTemplate *iat = (IdAdtTemplate *)new_id; + iat->adt = NULL; + } 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; @@ -1364,7 +1473,6 @@ void BKE_library_free(Library *lib) Main *BKE_main_new(void) { Main *bmain = MEM_callocN(sizeof(Main), "new main"); - bmain->eval_ctx = DEG_evaluation_context_new(DAG_EVAL_VIEWPORT); bmain->lock = MEM_mallocN(sizeof(SpinLock), "main lock"); BLI_spin_init((SpinLock *)bmain->lock); return bmain; @@ -1439,7 +1547,6 @@ void BKE_main_free(Main *mainvar) BLI_spin_end((SpinLock *)mainvar->lock); MEM_freeN(mainvar->lock); - DEG_evaluation_context_free(mainvar->eval_ctx); MEM_freeN(mainvar); } diff --git a/source/blender/blenkernel/intern/library_override.c b/source/blender/blenkernel/intern/library_override.c new file mode 100644 index 00000000000..9f3cc578d2a --- /dev/null +++ b/source/blender/blenkernel/intern/library_override.c @@ -0,0 +1,771 @@ +/* + * ***** 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 <string.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_REFOK; + /* 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_REFOK; +} + +/** 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 |= STATICOVERRIDE_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 != NULL) { + opop = BLI_findstring_ptr(&override_property->operations, subitem_locname, + offsetof(IDOverrideStaticPropertyOperation, subitem_local_name)); + + if (opop == NULL) { + return NULL; + } + + if (subitem_refname == NULL || opop->subitem_reference_name == NULL) { + return subitem_refname == opop->subitem_reference_name ? opop : NULL; + } + return (subitem_refname != NULL && opop->subitem_reference_name != NULL && + STREQ(subitem_refname, opop->subitem_reference_name)) ? opop : NULL; + } + + if (subitem_refname != NULL) { + opop = BLI_findstring_ptr(&override_property->operations, subitem_refname, + offsetof(IDOverrideStaticPropertyOperation, subitem_reference_name)); + + if (opop == NULL) { + return NULL; + } + + if (subitem_locname == NULL || opop->subitem_local_name == NULL) { + return subitem_locname == opop->subitem_local_name ? opop : NULL; + } + return (subitem_locname != NULL && opop->subitem_local_name != NULL && + STREQ(subitem_locname, opop->subitem_local_name)) ? opop : NULL; + } + + if ((opop = BLI_listbase_bytes_find(&override_property->operations, &subitem_locindex, sizeof(subitem_locindex), + offsetof(IDOverrideStaticPropertyOperation, subitem_local_index)))) + { + return ELEM(subitem_refindex, -1, opop->subitem_reference_index) ? opop : NULL; + } + + if ((opop = BLI_listbase_bytes_find(&override_property->operations, &subitem_refindex, sizeof(subitem_refindex), + offsetof(IDOverrideStaticPropertyOperation, subitem_reference_index)))) + { + return ELEM(subitem_locindex, -1, opop->subitem_local_index) ? opop : NULL; + } + + /* 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_REFOK; + 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_REFOK) == 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_REFOK; + 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_REFOK; + 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 if new overriding op was created, or some local data was reset. */ +bool BKE_override_static_operations_create(ID *local, const bool force_auto) +{ + BLI_assert(local->override_static != NULL); + const bool is_template = (local->override_static->reference == NULL); + bool ret = false; + + if (!is_template && (force_auto || local->override_static->flag & STATICOVERRIDE_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, const bool force_auto) +{ + 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 (force_auto || + (ID_IS_STATIC_OVERRIDE_AUTO(id) && (id->tag & LIB_TAG_OVERRIDESTATIC_AUTOREFRESH))) + { + BKE_override_static_operations_create(id, force_auto); + id->tag &= ~LIB_TAG_OVERRIDESTATIC_AUTOREFRESH; + } + } + } +} + +/** 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_REFOK) == 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_REFOK; + + /* 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, false); + + 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 d59658a2a07..efc550ac64c 100644 --- a/source/blender/blenkernel/intern/library_query.c +++ b/source/blender/blenkernel/intern/library_query.c @@ -31,13 +31,11 @@ #include "MEM_guardedalloc.h" -#include "DNA_actuator_types.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_brush_types.h" #include "DNA_camera_types.h" #include "DNA_constraint_types.h" -#include "DNA_controller_types.h" #include "DNA_group_types.h" #include "DNA_gpencil_types.h" #include "DNA_key_types.h" @@ -52,15 +50,17 @@ #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" #include "DNA_sequence_types.h" #include "DNA_screen_types.h" #include "DNA_speaker_types.h" #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 +69,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" @@ -79,9 +81,9 @@ #include "BKE_node.h" #include "BKE_particle.h" #include "BKE_rigidbody.h" -#include "BKE_sca.h" #include "BKE_sequencer.h" #include "BKE_tracking.h" +#include "BKE_workspace.h" #define FOREACH_FINALIZE _finalize @@ -213,33 +215,6 @@ static void library_foreach_particlesystemsObjectLooper( FOREACH_FINALIZE_VOID; } -static void library_foreach_sensorsObjectLooper( - bSensor *UNUSED(sensor), ID **id_pointer, void *user_data, int cb_flag) -{ - LibraryForeachIDData *data = (LibraryForeachIDData *) user_data; - FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag); - - FOREACH_FINALIZE_VOID; -} - -static void library_foreach_controllersObjectLooper( - bController *UNUSED(controller), ID **id_pointer, void *user_data, int cb_flag) -{ - LibraryForeachIDData *data = (LibraryForeachIDData *) user_data; - FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag); - - FOREACH_FINALIZE_VOID; -} - -static void library_foreach_actuatorsObjectLooper( - bActuator *UNUSED(actuator), ID **id_pointer, void *user_data, int cb_flag) -{ - LibraryForeachIDData *data = (LibraryForeachIDData *) user_data; - FOREACH_CALLBACK_INVOKE_ID_PP(data, id_pointer, cb_flag); - - FOREACH_FINALIZE_VOID; -} - static void library_foreach_nla_strip(LibraryForeachIDData *data, NlaStrip *strip) { NlaStrip *substrip; @@ -368,6 +343,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 +381,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); @@ -413,35 +390,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ library_foreach_ID_as_subdata_link((ID **)&scene->nodetree, callback, user_data, flag, &data); } - /* DO NOT handle scene->basact here, it's doubling with the loop over whole scene->base later, - * 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 +409,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_BEGIN(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) { @@ -470,8 +445,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call } if (toolsett) { - CALLBACK_INVOKE(toolsett->skgen_template, IDWALK_CB_NOP); - CALLBACK_INVOKE(toolsett->particle.scene, IDWALK_CB_NOP); CALLBACK_INVOKE(toolsett->particle.object, IDWALK_CB_NOP); CALLBACK_INVOKE(toolsett->particle.shape_object, IDWALK_CB_NOP); @@ -500,8 +473,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call BKE_rigidbody_world_id_loop(scene->rigidbody_world, library_foreach_rigidbodyworldSceneLooper, &data); } - CALLBACK_INVOKE(scene->gm.dome.warptext, IDWALK_CB_NOP); - break; } @@ -599,10 +570,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call CALLBACK_INVOKE(object->soft->effector_weights->group, IDWALK_CB_NOP); } } - - BKE_sca_sensors_id_loop(&object->sensors, library_foreach_sensorsObjectLooper, &data); - BKE_sca_controllers_id_loop(&object->controllers, library_foreach_controllersObjectLooper, &data); - BKE_sca_actuators_id_loop(&object->actuators, library_foreach_actuatorsObjectLooper, &data); break; } @@ -624,31 +591,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; } @@ -681,16 +623,10 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call case ID_MA: { Material *material = (Material *) id; - for (i = 0; i < MAX_MTEX; i++) { - if (material->mtex[i]) { - library_foreach_mtex(&data, material->mtex[i]); - } - } if (material->nodetree) { /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ library_foreach_ID_as_subdata_link((ID **)&material->nodetree, callback, user_data, flag, &data); } - CALLBACK_INVOKE(material->group, IDWALK_CB_USER); if (material->texpaintslot != NULL) { CALLBACK_INVOKE(material->texpaintslot->ima, IDWALK_CB_NOP); } @@ -705,16 +641,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call library_foreach_ID_as_subdata_link((ID **)&texture->nodetree, callback, user_data, flag, &data); } CALLBACK_INVOKE(texture->ima, IDWALK_CB_USER); - if (texture->env) { - CALLBACK_INVOKE(texture->env->object, IDWALK_CB_NOP); - CALLBACK_INVOKE(texture->env->ima, IDWALK_CB_USER); - } - if (texture->pd) - CALLBACK_INVOKE(texture->pd->object, IDWALK_CB_NOP); - if (texture->vd) - CALLBACK_INVOKE(texture->vd->object, IDWALK_CB_NOP); - if (texture->ot) - CALLBACK_INVOKE(texture->ot->object, IDWALK_CB_NOP); break; } @@ -728,11 +654,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call case ID_LA: { Lamp *lamp = (Lamp *) id; - for (i = 0; i < MAX_MTEX; i++) { - if (lamp->mtex[i]) { - library_foreach_mtex(&data, lamp->mtex[i]); - } - } if (lamp->nodetree) { /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ library_foreach_ID_as_subdata_link((ID **)&lamp->nodetree, callback, user_data, flag, &data); @@ -754,21 +675,9 @@ 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; - for (i = 0; i < MAX_MTEX; i++) { - if (world->mtex[i]) { - library_foreach_mtex(&data, world->mtex[i]); - } - } if (world->nodetree) { /* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */ library_foreach_ID_as_subdata_link((ID **)&world->nodetree, callback, user_data, flag, &data); @@ -783,13 +692,22 @@ 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); + CALLBACK_INVOKE(probe->visibility_grp, IDWALK_CB_NOP); + 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_BEGIN(group, base) + { + CALLBACK_INVOKE(base->object, IDWALK_CB_USER_ONE); } + FOREACH_GROUP_BASE_END break; } @@ -971,6 +889,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; @@ -982,11 +934,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: @@ -1067,7 +1019,7 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used) #if 0 return ELEM(id_type_used, ID_ME, ID_CU, ID_MB, ID_LT, ID_SPK, ID_AR, ID_LA, ID_CA, /* obdata */ ID_OB, ID_MA, ID_GD, ID_GR, ID_TE, ID_PA, ID_TXT, ID_SO, ID_MC, ID_IM, ID_AC - /* + constraints, modifiers and game logic ID types... */); + /* + constraints and modifiers ... */); #else return true; #endif @@ -1114,6 +1066,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..f6e03fec380 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,15 +103,19 @@ #include "BKE_object.h" #include "BKE_paint.h" #include "BKE_particle.h" -#include "BKE_sca.h" +#include "BKE_lightprobe.h" #include "BKE_speaker.h" #include "BKE_sound.h" #include "BKE_screen.h" #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 +181,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 +192,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 +209,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 +223,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 +240,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,23 +263,41 @@ 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; } } } +static void libblock_remap_data_preprocess_group_unlink( + IDRemap *r_id_remap_data, Object *ob, const bool skip_indirect, const bool is_indirect) +{ + Main *bmain = r_id_remap_data->bmain; + for (Group *group = bmain->group.first; group; group = group->id.next) { + if (BKE_group_object_exists(group, ob)) { + if (skip_indirect && is_indirect) { + r_id_remap_data->skipped_indirect++; + r_id_remap_data->skipped_refcounted++; + } + else { + BKE_collections_object_remove(bmain, &group->id, ob, false); + if (!is_indirect) { + r_id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT; + } + } + } + } +} + static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data) { switch (GS(r_id_remap_data->id->name)) { @@ -283,23 +312,24 @@ 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_BEGIN(sce, ob_iter) + { + libblock_remap_data_preprocess_scene_object_unlink( + r_id_remap_data, sce, ob_iter, skip_indirect, is_indirect); + libblock_remap_data_preprocess_group_unlink( + r_id_remap_data, 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); + libblock_remap_data_preprocess_group_unlink( + r_id_remap_data, old_ob, skip_indirect, is_indirect); } + } break; } @@ -340,7 +370,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 +380,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 +390,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_BEGIN(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) @@ -480,10 +505,6 @@ ATTR_NONNULL(1) static void libblock_remap_data( } } - if (old_id && GS(old_id->name) == ID_OB) { - BKE_sca_logic_links_remap(bmain, (Object *)old_id, (Object *)new_id); - } - /* XXX We may not want to always 'transfer' fakeuser from old to new id... Think for now it's desired behavior * though, we can always add an option (flag) to control this later if needed. */ if (old_id && (old_id->flag & LIB_FAKEUSER)) { @@ -594,8 +615,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 +768,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 +836,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 +885,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 +926,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 +989,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 e00884c8a9d..5757ae7480b 100644 --- a/source/blender/blenkernel/intern/linestyle.c +++ b/source/blender/blenkernel/intern/linestyle.c @@ -212,20 +212,11 @@ void BKE_linestyle_make_local(struct Main *bmain, FreestyleLineStyle *linestyle, BKE_id_make_local_generic(bmain, &linestyle->id, true, lib_local); } -FreestyleLineStyle *BKE_linestyle_active_from_scene(Scene *scene) +FreestyleLineStyle *BKE_linestyle_active_from_view_layer(ViewLayer *view_layer) { - SceneRenderLayer *actsrl = BLI_findlink(&scene->r.layers, scene->r.actlay); - if (!actsrl) { - return NULL; - } - - FreestyleConfig *config = &actsrl->freestyleConfig; + FreestyleConfig *config = &view_layer->freestyle_config; FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config); - - if (lineset) { - return lineset->linestyle; - } - return NULL; + return (lineset) ? lineset->linestyle : NULL; } static LineStyleModifier *new_modifier(const char *name, int type, size_t size) diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c index b5742dbdbb7..ba5a6a25048 100644 --- a/source/blender/blenkernel/intern/mask.c +++ b/source/blender/blenkernel/intern/mask.c @@ -51,7 +51,7 @@ #include "BKE_animsys.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" + #include "BKE_library.h" #include "BKE_main.h" #include "BKE_mask.h" @@ -61,6 +61,8 @@ #include "BKE_movieclip.h" #include "BKE_image.h" +#include "DEG_depsgraph_build.h" + static struct { ListBase splines; struct GHash *id_hash; @@ -817,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; } @@ -1457,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 e2a9691e577..55939f8eadf 100644 --- a/source/blender/blenkernel/intern/mask_evaluate.c +++ b/source/blender/blenkernel/intern/mask_evaluate.c @@ -40,12 +40,13 @@ #include "BLI_math.h" #include "DNA_mask_types.h" +#include "DNA_object_types.h" #include "BKE_curve.h" -#include "BKE_depsgraph.h" #include "BKE_mask.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" unsigned int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height) { @@ -897,24 +898,26 @@ void BKE_mask_layer_evaluate_deform(MaskLayer *masklay, const float ctime) } } -void BKE_mask_eval_animation(struct EvaluationContext *eval_ctx, Mask *mask) +void BKE_mask_eval_animation(struct Depsgraph *depsgraph, Mask *mask) { - DEG_debug_print_eval(__func__, mask->id.name, mask); + float ctime = DEG_get_ctime(depsgraph); + DEG_debug_print_eval(depsgraph, __func__, mask->id.name, mask); for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer != NULL; mask_layer = mask_layer->next) { - BKE_mask_layer_evaluate_animation(mask_layer, eval_ctx->ctime); + BKE_mask_layer_evaluate_animation(mask_layer, ctime); } } -void BKE_mask_eval_update(struct EvaluationContext *eval_ctx, Mask *mask) +void BKE_mask_eval_update(struct Depsgraph *depsgraph, Mask *mask) { - DEG_debug_print_eval(__func__, mask->id.name, mask); + float ctime = DEG_get_ctime(depsgraph); + DEG_debug_print_eval(depsgraph, __func__, mask->id.name, mask); for (MaskLayer *mask_layer = mask->masklayers.first; mask_layer != NULL; mask_layer = mask_layer->next) { - BKE_mask_layer_evaluate_deform(mask_layer, eval_ctx->ctime); + BKE_mask_layer_evaluate_deform(mask_layer, ctime); } } diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c index 01f16625386..131d79c249f 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,9 @@ #include "BKE_editmesh.h" #include "BKE_font.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" + #include "GPU_material.h" /* used in UI and render */ @@ -87,16 +89,10 @@ void init_def_material(void) /** Free (or release) any data used by this material (does not free the material itself). */ void BKE_material_free(Material *ma) { - int a; - BKE_animdata_free((ID *)ma, false); - for (a = 0; a < MAX_MTEX; a++) { - MEM_SAFE_FREE(ma->mtex[a]); - } - - MEM_SAFE_FREE(ma->ramp_col); - MEM_SAFE_FREE(ma->ramp_spec); + /* Free gpu material before the ntree */ + GPU_material_free(&ma->gpumaterial); /* is no lib link block, but material extension */ if (ma->nodetree) { @@ -107,8 +103,6 @@ void BKE_material_free(Material *ma) MEM_SAFE_FREE(ma->texpaintslot); - GPU_material_free(&ma->gpumaterial); - BKE_icon_id_delete((ID *)ma); BKE_previewimg_free(&ma->preview); } @@ -117,95 +111,19 @@ void BKE_material_init(Material *ma) { BLI_assert(MEMCMP_STRUCT_OFS_IS_ZERO(ma, id)); - ma->r = ma->g = ma->b = ma->ref = 0.8; + ma->r = ma->g = ma->b = 0.8; ma->specr = ma->specg = ma->specb = 1.0; - ma->mirr = ma->mirg = ma->mirb = 1.0; - ma->spectra = 1.0; - ma->amb = 1.0; ma->alpha = 1.0; - ma->spec = ma->hasize = 0.5; - ma->har = 50; - ma->starc = ma->ringc = 4; - ma->linec = 12; - ma->flarec = 1; - ma->flaresize = ma->subsize = 1.0; - ma->flareboost = 1; - ma->seed2 = 6; - ma->friction = 0.5; - ma->refrac = 4.0; - ma->roughness = 0.5; - ma->param[0] = 0.5; - ma->param[1] = 0.1; - ma->param[2] = 0.5; - ma->param[3] = 0.1; - ma->rms = 0.1; - ma->darkness = 1.0; - - ma->strand_sta = ma->strand_end = 1.0f; - - ma->ang = 1.0; - ma->ray_depth = 2; - ma->ray_depth_tra = 2; - ma->fresnel_mir = 0.0; - ma->fresnel_tra = 0.0; - ma->fresnel_tra_i = 1.25; - ma->fresnel_mir_i = 1.25; - ma->tx_limit = 0.0; - ma->tx_falloff = 1.0; - ma->shad_alpha = 1.0f; - ma->vcol_alpha = 0; - - ma->gloss_mir = ma->gloss_tra = 1.0; - ma->samp_gloss_mir = ma->samp_gloss_tra = 18; - ma->adapt_thresh_mir = ma->adapt_thresh_tra = 0.005; - ma->dist_mir = 0.0; - ma->fadeto_mir = MA_RAYMIR_FADETOSKY; + ma->spec = 0.5; + + ma->gloss_mir = 1.0; - ma->rampfac_col = 1.0; - ma->rampfac_spec = 1.0; ma->pr_lamp = 3; /* two lamps, is bits */ ma->pr_type = MA_SPHERE; - ma->sss_radius[0] = 1.0f; - ma->sss_radius[1] = 1.0f; - ma->sss_radius[2] = 1.0f; - ma->sss_col[0] = 1.0f; - ma->sss_col[1] = 1.0f; - ma->sss_col[2] = 1.0f; - ma->sss_error = 0.05f; - ma->sss_scale = 0.1f; - ma->sss_ior = 1.3f; - ma->sss_colfac = 1.0f; - ma->sss_texfac = 0.0f; - ma->sss_front = 1.0f; - ma->sss_back = 1.0f; - - ma->vol.density = 1.0f; - ma->vol.emission = 0.0f; - ma->vol.scattering = 1.0f; - ma->vol.reflection = 1.0f; - ma->vol.transmission_col[0] = ma->vol.transmission_col[1] = ma->vol.transmission_col[2] = 1.0f; - ma->vol.reflection_col[0] = ma->vol.reflection_col[1] = ma->vol.reflection_col[2] = 1.0f; - ma->vol.emission_col[0] = ma->vol.emission_col[1] = ma->vol.emission_col[2] = 1.0f; - ma->vol.density_scale = 1.0f; - ma->vol.depth_cutoff = 0.01f; - ma->vol.stepsize_type = MA_VOL_STEP_RANDOMIZED; - ma->vol.stepsize = 0.2f; - ma->vol.shade_type = MA_VOL_SHADE_SHADED; - ma->vol.shadeflag |= MA_VOL_PRECACHESHADING; - ma->vol.precache_resolution = 50; - ma->vol.ms_spread = 0.2f; - ma->vol.ms_diff = 1.f; - ma->vol.ms_intensity = 1.f; - - ma->game.flag = GEMAT_BACKCULL; - ma->game.alpha_blend = 0; - ma->game.face_orientation = 0; - - ma->mode = MA_TRACEBLE | MA_SHADBUF | MA_SHADOW | MA_RAYBIAS | MA_TANGENT_STR | MA_ZTRANSP; - 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) @@ -229,20 +147,6 @@ Material *BKE_material_add(Main *bmain, const char *name) */ void BKE_material_copy_data(Main *bmain, Material *ma_dst, const Material *ma_src, const int flag) { - for (int a = 0; a < MAX_MTEX; a++) { - if (ma_src->mtex[a]) { - ma_dst->mtex[a] = MEM_mallocN(sizeof(*ma_dst->mtex[a]), __func__); - *ma_dst->mtex[a] = *ma_src->mtex[a]; - } - } - - if (ma_src->ramp_col) { - ma_dst->ramp_col = MEM_dupallocN(ma_src->ramp_col); - } - if (ma_src->ramp_spec) { - ma_dst->ramp_spec = MEM_dupallocN(ma_src->ramp_spec); - } - if (ma_src->nodetree) { /* Note: nodetree is *not* in bmain, however this specific case is handled at lower level * (see BKE_libblock_copy_ex()). */ @@ -261,6 +165,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) @@ -281,29 +187,24 @@ Material *BKE_material_localize(Material *ma) * ... Once f*** nodes are fully converted to that too :( */ Material *man; - int a; - - man = BKE_libblock_copy_nolib(&ma->id, false); - /* no increment for texture ID users, in previewrender.c it prevents decrement */ - for (a = 0; a < MAX_MTEX; a++) { - if (ma->mtex[a]) { - man->mtex[a] = MEM_mallocN(sizeof(MTex), "copymaterial"); - memcpy(man->mtex[a], ma->mtex[a], sizeof(MTex)); - } - } - - if (ma->ramp_col) man->ramp_col = MEM_dupallocN(ma->ramp_col); - if (ma->ramp_spec) man->ramp_spec = MEM_dupallocN(ma->ramp_spec); + BKE_id_copy_ex( + NULL, &ma->id, (ID **)&man, + (LIB_ID_CREATE_NO_MAIN | + LIB_ID_CREATE_NO_USER_REFCOUNT | + LIB_ID_COPY_NO_PREVIEW | + LIB_ID_COPY_NO_ANIMDATA), + false); man->texpaintslot = NULL; man->preview = NULL; - - if (ma->nodetree) - man->nodetree = ntreeLocalize(ma->nodetree); - + BLI_listbase_clear(&man->gpumaterial); - + + /* TODO Duplicate Engine Settings and set runtime to NULL */ + + man->id.tag |= LIB_TAG_LOCALIZED; + return man; } @@ -458,7 +359,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) @@ -475,7 +376,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); } } @@ -509,7 +410,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); } } @@ -536,7 +437,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); } } @@ -631,7 +532,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) @@ -936,278 +837,8 @@ bool BKE_object_material_slot_add(Object *ob) return true; } -static void do_init_render_material(Material *ma, int r_mode, float *amb) -{ - MTex *mtex; - int a, needuv = 0, needtang = 0; - - if (ma->flarec == 0) ma->flarec = 1; - - /* add all texcoflags from mtex, texco and mapto were cleared in advance */ - for (a = 0; a < MAX_MTEX; a++) { - - /* separate tex switching */ - if (ma->septex & (1 << a)) continue; - - mtex = ma->mtex[a]; - if (mtex && mtex->tex && (mtex->tex->type | (mtex->tex->use_nodes && mtex->tex->nodetree) )) { - - ma->texco |= mtex->texco; - ma->mapto |= mtex->mapto; - - /* always get derivatives for these textures */ - if (ELEM(mtex->tex->type, TEX_IMAGE, TEX_ENVMAP)) ma->texco |= TEXCO_OSA; - else if (mtex->texflag & (MTEX_COMPAT_BUMP | MTEX_3TAP_BUMP | MTEX_5TAP_BUMP | MTEX_BICUBIC_BUMP)) ma->texco |= TEXCO_OSA; - - if (ma->texco & (TEXCO_ORCO | TEXCO_REFL | TEXCO_NORM | TEXCO_STRAND | TEXCO_STRESS)) needuv = 1; - else if (ma->texco & (TEXCO_GLOB | TEXCO_UV | TEXCO_OBJECT | TEXCO_SPEED)) needuv = 1; - else if (ma->texco & (TEXCO_LAVECTOR | TEXCO_VIEW)) needuv = 1; - - if ((ma->mapto & MAP_NORM) && (mtex->normapspace == MTEX_NSPACE_TANGENT)) - needtang = 1; - } - } - - if (needtang) ma->mode |= MA_NORMAP_TANG; - else ma->mode &= ~MA_NORMAP_TANG; - - if (ma->mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) { - needuv = 1; - if (r_mode & R_OSA) ma->texco |= TEXCO_OSA; /* for texfaces */ - } - if (needuv) ma->texco |= NEED_UV; - - /* since the raytracer doesnt recalc O structs for each ray, we have to preset them all */ - if (r_mode & R_RAYTRACE) { - if ((ma->mode & (MA_RAYMIRROR | MA_SHADOW_TRA)) || ((ma->mode & MA_TRANSP) && (ma->mode & MA_RAYTRANSP))) { - ma->texco |= NEED_UV | TEXCO_ORCO | TEXCO_REFL | TEXCO_NORM; - if (r_mode & R_OSA) ma->texco |= TEXCO_OSA; - } - } - - if (amb) { - ma->ambr = ma->amb * amb[0]; - ma->ambg = ma->amb * amb[1]; - ma->ambb = ma->amb * amb[2]; - } - - /* local group override */ - if ((ma->shade_flag & MA_GROUP_LOCAL) && ma->id.lib && ma->group && ma->group->id.lib) { - Group *group; - - for (group = G.main->group.first; group; group = group->id.next) { - if (!ID_IS_LINKED(group) && STREQ(group->id.name, ma->group->id.name)) { - ma->group = group; - } - } - } -} - -static void init_render_nodetree(bNodeTree *ntree, Material *basemat, int r_mode, float *amb) -{ - bNode *node; - - /* parses the geom+tex nodes */ - ntreeShaderGetTexcoMode(ntree, r_mode, &basemat->texco, &basemat->mode_l); - for (node = ntree->nodes.first; node; node = node->next) { - if (node->id) { - if (GS(node->id->name) == ID_MA) { - Material *ma = (Material *)node->id; - if (ma != basemat) { - do_init_render_material(ma, r_mode, amb); - basemat->texco |= ma->texco; - } - - basemat->mode_l |= ma->mode & ~(MA_MODE_PIPELINE | MA_SHLESS); - basemat->mode2_l |= ma->mode2 & ~MA_MODE2_PIPELINE; - /* basemat only considered shadeless if all node materials are too */ - if (!(ma->mode & MA_SHLESS)) - basemat->mode_l &= ~MA_SHLESS; - - if (ma->strand_surfnor > 0.0f) - basemat->mode_l |= MA_STR_SURFDIFF; - } - else if (node->type == NODE_GROUP) - init_render_nodetree((bNodeTree *)node->id, basemat, r_mode, amb); - } - else if (node->typeinfo->type == SH_NODE_NORMAL_MAP) { - basemat->mode2_l |= MA_TANGENT_CONCRETE; - NodeShaderNormalMap *nm = node->storage; - bool taken_into_account = false; - for (int i = 0; i < basemat->nmap_tangent_names_count; i++) { - if (STREQ(basemat->nmap_tangent_names[i], nm->uv_map)) { - taken_into_account = true; - break; - } - } - if (!taken_into_account) { - BLI_assert(basemat->nmap_tangent_names_count < MAX_MTFACE + 1); - strcpy(basemat->nmap_tangent_names[basemat->nmap_tangent_names_count++], nm->uv_map); - } - } - } -} - -void init_render_material(Material *mat, int r_mode, float *amb) -{ - - do_init_render_material(mat, r_mode, amb); - - if (mat->nodetree && mat->use_nodes) { - /* mode_l will take the pipeline options from the main material, and the or-ed - * result of non-pipeline options from the nodes. shadeless is an exception, - * mode_l will have it set when all node materials are shadeless. */ - mat->mode_l = (mat->mode & MA_MODE_PIPELINE) | MA_SHLESS; - mat->mode2_l = mat->mode2 & MA_MODE2_PIPELINE; - mat->nmap_tangent_names_count = 0; - init_render_nodetree(mat->nodetree, mat, r_mode, amb); - - if (!mat->nodetree->execdata) - mat->nodetree->execdata = ntreeShaderBeginExecTree(mat->nodetree); - } - else { - mat->mode_l = mat->mode; - mat->mode2_l = mat->mode2; - - if (mat->strand_surfnor > 0.0f) - mat->mode_l |= MA_STR_SURFDIFF; - } -} - -void init_render_materials(Main *bmain, int r_mode, float *amb, bool do_default_material) -{ - Material *ma; - - /* clear these flags before going over materials, to make sure they - * are cleared only once, otherwise node materials contained in other - * node materials can go wrong */ - for (ma = bmain->mat.first; ma; ma = ma->id.next) { - if (ma->id.us) { - ma->texco = 0; - ma->mapto = 0; - } - } - - /* two steps, first initialize, then or the flags for layers */ - for (ma = bmain->mat.first; ma; ma = ma->id.next) { - /* is_used flag comes back in convertblender.c */ - ma->flag &= ~MA_IS_USED; - if (ma->id.us) - init_render_material(ma, r_mode, amb); - } - - if (do_default_material) { - init_render_material(&defmaterial, r_mode, amb); - } -} - -/* only needed for nodes now */ -void end_render_material(Material *mat) -{ - if (mat && mat->nodetree && mat->use_nodes) { - if (mat->nodetree->execdata) - ntreeShaderEndExecTree(mat->nodetree->execdata); - } -} - -void end_render_materials(Main *bmain) -{ - Material *ma; - for (ma = bmain->mat.first; ma; ma = ma->id.next) - if (ma->id.us) - end_render_material(ma); -} - -static bool material_in_nodetree(bNodeTree *ntree, Material *mat) -{ - bNode *node; - - for (node = ntree->nodes.first; node; node = node->next) { - if (node->id) { - if (GS(node->id->name) == ID_MA) { - if (node->id == (ID *)mat) { - return true; - } - } - else if (node->type == NODE_GROUP) { - if (material_in_nodetree((bNodeTree *)node->id, mat)) { - return true; - } - } - } - } - - return false; -} - -bool material_in_material(Material *parmat, Material *mat) -{ - if (parmat == mat) - return true; - else if (parmat->nodetree && parmat->use_nodes) - return material_in_nodetree(parmat->nodetree, mat); - else - return false; -} - - /* ****************** */ -/* 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; @@ -1297,13 +928,6 @@ bool BKE_object_material_slot_remove(Object *ob) return true; } -static bool get_mtex_slot_valid_texpaint(struct MTex *mtex) -{ - return (mtex && (mtex->texco == TEXCO_UV) && - mtex->tex && (mtex->tex->type == TEX_IMAGE) && - mtex->tex->ima); -} - static bNode *nodetree_uv_node_recursive(bNode *node) { bNode *inode; @@ -1326,13 +950,9 @@ static bNode *nodetree_uv_node_recursive(bNode *node) void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma) { - MTex **mtex; short count = 0; - short index = 0, i; + short index = 0; - 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); - if (!ma) return; @@ -1348,88 +968,50 @@ void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma) return; } - if (use_nodes || ma->use_nodes) { - bNode *node, *active_node; - - if (!(ma->nodetree)) { - ma->paint_active_slot = 0; - ma->paint_clone_slot = 0; - return; - } + bNode *node, *active_node; - for (node = ma->nodetree->nodes.first; node; node = node->next) { - if (node->typeinfo->nclass == NODE_CLASS_TEXTURE && node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id) - count++; - } + if (!(ma->nodetree)) { + ma->paint_active_slot = 0; + ma->paint_clone_slot = 0; + return; + } - if (count == 0) { - ma->paint_active_slot = 0; - ma->paint_clone_slot = 0; - return; - } - ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots"); - - active_node = nodeGetActiveTexture(ma->nodetree); - - for (node = ma->nodetree->nodes.first; node; node = node->next) { - if (node->typeinfo->nclass == NODE_CLASS_TEXTURE && node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id) { - if (active_node == node) - ma->paint_active_slot = index; - ma->texpaintslot[index].ima = (Image *)node->id; - - /* for new renderer, we need to traverse the treeback in search of a UV node */ - if (use_nodes) { - bNode *uvnode = nodetree_uv_node_recursive(node); - - if (uvnode) { - NodeShaderUVMap *storage = (NodeShaderUVMap *)uvnode->storage; - ma->texpaintslot[index].uvname = storage->uv_map; - /* set a value to index so UI knows that we have a valid pointer for the mesh */ - ma->texpaintslot[index].index = 0; - } - else { - /* just invalidate the index here so UV map does not get displayed on the UI */ - ma->texpaintslot[index].index = -1; - } - } - else { - ma->texpaintslot[index].index = -1; - } - index++; - } - } + for (node = ma->nodetree->nodes.first; node; node = node->next) { + if (node->typeinfo->nclass == NODE_CLASS_TEXTURE && node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id) + count++; } - else if (is_bi) { - for (mtex = ma->mtex, i = 0; i < MAX_MTEX; i++, mtex++) { - if (get_mtex_slot_valid_texpaint(*mtex)) { - count++; - } - } - if (count == 0) { - ma->paint_active_slot = 0; - ma->paint_clone_slot = 0; - return; - } + if (count == 0) { + ma->paint_active_slot = 0; + ma->paint_clone_slot = 0; + return; + } + ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots"); - ma->texpaintslot = MEM_callocN(sizeof(*ma->texpaintslot) * count, "texpaint_slots"); + active_node = nodeGetActiveTexture(ma->nodetree); - for (mtex = ma->mtex, i = 0; i < MAX_MTEX; i++, mtex++) { - if (get_mtex_slot_valid_texpaint(*mtex)) { - ma->texpaintslot[index].ima = (*mtex)->tex->ima; - ma->texpaintslot[index].uvname = (*mtex)->uvname; - ma->texpaintslot[index].index = i; - - index++; + for (node = ma->nodetree->nodes.first; node; node = node->next) { + if (node->typeinfo->nclass == NODE_CLASS_TEXTURE && node->typeinfo->type == SH_NODE_TEX_IMAGE && node->id) { + if (active_node == node) + ma->paint_active_slot = index; + ma->texpaintslot[index].ima = (Image *)node->id; + + /* for new renderer, we need to traverse the treeback in search of a UV node */ + bNode *uvnode = nodetree_uv_node_recursive(node); + + if (uvnode) { + NodeShaderUVMap *storage = (NodeShaderUVMap *)uvnode->storage; + ma->texpaintslot[index].uvname = storage->uv_map; + /* set a value to index so UI knows that we have a valid pointer for the mesh */ + ma->texpaintslot[index].valid = true; + } + else { + /* just invalidate the index here so UV map does not get displayed on the UI */ + ma->texpaintslot[index].valid = false; } + index++; } } - else { - ma->paint_active_slot = 0; - ma->paint_clone_slot = 0; - return; - } - ma->tot_slots = count; @@ -1685,21 +1267,6 @@ void clear_matcopybuf(void) void free_matcopybuf(void) { - int a; - - for (a = 0; a < MAX_MTEX; a++) { - if (matcopybuf.mtex[a]) { - MEM_freeN(matcopybuf.mtex[a]); - matcopybuf.mtex[a] = NULL; - } - } - - if (matcopybuf.ramp_col) MEM_freeN(matcopybuf.ramp_col); - if (matcopybuf.ramp_spec) MEM_freeN(matcopybuf.ramp_spec); - - matcopybuf.ramp_col = NULL; - matcopybuf.ramp_spec = NULL; - if (matcopybuf.nodetree) { ntreeFreeTree(matcopybuf.nodetree); MEM_freeN(matcopybuf.nodetree); @@ -1711,575 +1278,44 @@ void free_matcopybuf(void) void copy_matcopybuf(Material *ma) { - int a; - MTex *mtex; - if (matcopied) free_matcopybuf(); memcpy(&matcopybuf, ma, sizeof(Material)); - if (matcopybuf.ramp_col) matcopybuf.ramp_col = MEM_dupallocN(matcopybuf.ramp_col); - if (matcopybuf.ramp_spec) matcopybuf.ramp_spec = MEM_dupallocN(matcopybuf.ramp_spec); - for (a = 0; a < MAX_MTEX; a++) { - mtex = matcopybuf.mtex[a]; - if (mtex) { - matcopybuf.mtex[a] = MEM_dupallocN(mtex); - } - } 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; } void paste_matcopybuf(Material *ma) { - int a; - MTex *mtex; ID id; if (matcopied == 0) return; - /* free current mat */ - if (ma->ramp_col) MEM_freeN(ma->ramp_col); - if (ma->ramp_spec) MEM_freeN(ma->ramp_spec); - for (a = 0; a < MAX_MTEX; a++) { - mtex = ma->mtex[a]; - if (mtex && mtex->tex) - id_us_min(&mtex->tex->id); - if (mtex) - MEM_freeN(mtex); - } + + /* Free gpu material before the ntree */ + GPU_material_free(&ma->gpumaterial); if (ma->nodetree) { ntreeFreeTree(ma->nodetree); MEM_freeN(ma->nodetree); } - GPU_material_free(&ma->gpumaterial); - id = (ma->id); memcpy(ma, &matcopybuf, sizeof(Material)); (ma->id) = id; - if (matcopybuf.ramp_col) ma->ramp_col = MEM_dupallocN(matcopybuf.ramp_col); - if (matcopybuf.ramp_spec) ma->ramp_spec = MEM_dupallocN(matcopybuf.ramp_spec); - - for (a = 0; a < MAX_MTEX; a++) { - mtex = ma->mtex[a]; - if (mtex) { - ma->mtex[a] = MEM_dupallocN(mtex); - if (mtex->tex) { - /* first check this is in main (we may have loaded another file) [#35500] */ - if (BLI_findindex(&G.main->tex, mtex->tex) != -1) { - id_us_plus((ID *)mtex->tex); - } - else { - ma->mtex[a]->tex = NULL; - } - } - } - } - 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) -{ - /* 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; -} - -/* set the material options based in the tface flag */ -static void decode_tfaceflag(Material *ma, int flag, int convertall) -{ - 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; - } - - /* 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) +void BKE_material_eval(struct Depsgraph *depsgraph, Material *material) { - int i = 0; - if (number == 0) return 1; - - while (number != 0) { - number = (int)(number / 10); - i++; + DEG_debug_print_eval(depsgraph, __func__, material->id.name, material); + if ((BLI_listbase_is_empty(&material->gpumaterial) == false)) { + GPU_material_uniform_buffer_tag_dirty(&material->gpumaterial); } - 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; -} - -static void set_facetexture_flags(Material *ma, 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++; - } - } - } -} - - -#define MAT_BGE_DISPUTED -99999 - -int do_version_tface(Main *main) -{ - 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; - } - } - } - - } - - /* 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; - } - } - } - - return nowarning; -} - diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index dfc49c996b1..d7fb2d0a17b 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,12 +329,14 @@ 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; BLI_split_name_num(basisname, &basisnr, active_object->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)) { + /* Pass depsgraph as NULL, which means we will not expand into + * duplis unlike when we generate the mball. Expanding duplis + * would not be compatible when editing multiple view layers. */ + BKE_scene_base_iter_next(NULL, &iter, &sce_iter, 0, NULL, NULL); + while (BKE_scene_base_iter_next(NULL, &iter, &sce_iter, 1, &base, &ob)) { if (ob->type == OB_MBALL) { if (ob != active_object) { BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.'); @@ -362,27 +368,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 +543,25 @@ void BKE_mball_select_swap(struct MetaBall *mb) /* **** Depsgraph evaluation **** */ -void BKE_mball_eval_geometry(EvaluationContext *UNUSED(eval_ctx), +void BKE_mball_eval_geometry(struct Depsgraph *UNUSED(depsgraph), MetaBall *UNUSED(mball)) { } + +/* Draw Engine */ + +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..0f13618c76a 100644 --- a/source/blender/blenkernel/intern/mball_tessellate.c +++ b/source/blender/blenkernel/intern/mball_tessellate.c @@ -48,11 +48,13 @@ #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 "DEG_depsgraph_query.h" + #include "BLI_strict_flags.h" /* experimental (faster) normal calculation */ @@ -1055,7 +1057,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(Depsgraph *depsgraph, PROCESS *process, Scene *scene, Object *ob) { Scene *sce_iter = scene; Base *base; @@ -1074,13 +1076,13 @@ static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scen BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.'); /* make main array */ - 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, &bob)) { + BKE_scene_base_iter_next(depsgraph, &iter, &sce_iter, 0, NULL, NULL); + while (BKE_scene_base_iter_next(depsgraph, &iter, &sce_iter, 1, &base, &bob)) { if (bob->type == OB_MBALL) { 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,12 +1234,13 @@ 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(Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *dispbase) { MetaBall *mb; DispList *dl; unsigned int a; PROCESS process = {0}; + bool is_render = DEG_get_mode(depsgraph) == DAG_EVAL_RENDER; mb = ob->data; @@ -1248,10 +1251,10 @@ void BKE_mball_polygonize(EvaluationContext *eval_ctx, Scene *scene, Object *ob, else if (process.thresh < 0.1f) process.converge_res = 4; else process.converge_res = 2; - if ((eval_ctx->mode != DAG_EVAL_RENDER) && (mb->flag == MB_UPDATE_NEVER)) return; + if (is_render && (mb->flag == MB_UPDATE_NEVER)) return; if ((G.moving & (G_TRANSFORM_OBJ | G_TRANSFORM_EDIT)) && mb->flag == MB_UPDATE_FAST) return; - if (eval_ctx->mode == DAG_EVAL_RENDER) { + if (is_render) { process.size = mb->rendersize; } else { @@ -1266,7 +1269,7 @@ void BKE_mball_polygonize(EvaluationContext *eval_ctx, Scene *scene, Object *ob, process.pgn_elements = BLI_memarena_new(BLI_MEMARENA_STD_BUFSIZE, "Metaball memarena"); /* initialize all mainb (MetaElems) */ - init_meta(eval_ctx, &process, scene, ob); + init_meta(depsgraph, &process, scene, ob); if (process.totelem > 0) { build_bvh_spatial(&process, &process.metaball_bvh, 0, process.totelem, &process.allbb); diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index fd56534146d..9bd1b587abd 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -44,12 +44,14 @@ #include "BLI_memarena.h" #include "BLI_edgehash.h" #include "BLI_string.h" +#include "BLI_utildefines_stack.h" #include "BKE_animsys.h" #include "BKE_main.h" #include "BKE_DerivedMesh.h" #include "BKE_global.h" #include "BKE_mesh.h" +#include "BKE_mesh_mapping.h" #include "BKE_displist.h" #include "BKE_library.h" #include "BKE_library_query.h" @@ -59,7 +61,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" /* -- */ @@ -67,6 +68,7 @@ #include "BKE_editmesh.h" #include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" /* Define for cases when you want extra validation of mesh * after certain modifications. @@ -127,7 +129,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 +137,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 +151,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 +326,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 +337,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 +346,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 +390,78 @@ void BKE_mesh_ensure_skin_customdata(Mesh *me) } } +bool BKE_mesh_ensure_edit_data(struct Mesh *me) +{ + if (me->runtime.edit_data != NULL) { + return false; + } + + me->runtime.edit_data = MEM_callocN(sizeof(EditMeshData), "EditMeshData"); + return true; +} + +bool BKE_mesh_clear_edit_data(struct Mesh *me) +{ + if (me->runtime.edit_data == NULL) { + return false; + } + + if (me->runtime.edit_data->polyCos != NULL) + MEM_freeN((void *)me->runtime.edit_data->polyCos); + if (me->runtime.edit_data->polyNos != NULL) + MEM_freeN((void *)me->runtime.edit_data->polyNos); + if (me->runtime.edit_data->vertexCos != NULL) + MEM_freeN((void *)me->runtime.edit_data->vertexCos); + if (me->runtime.edit_data->vertexNos != NULL) + MEM_freeN((void *)me->runtime.edit_data->vertexNos); + + MEM_SAFE_FREE(me->runtime.edit_data); + return true; +} + + +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 +470,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 +493,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 +512,9 @@ void BKE_mesh_free(Mesh *me) { BKE_animdata_free(&me->id, false); + BKE_mesh_batch_cache_free(me); + BKE_mesh_clear_edit_data(me); + CustomData_free(&me->vdata, me->totvert); CustomData_free(&me->edata, me->totedge); CustomData_free(&me->fdata, me->totface); @@ -529,6 +602,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->runtime.batch_cache = NULL; me_dst->mselect = MEM_dupallocN(me_dst->mselect); me_dst->bb = MEM_dupallocN(me_dst->bb); @@ -539,6 +613,59 @@ void BKE_mesh_copy_data(Main *bmain, Mesh *me_dst, const Mesh *me_src, const int } } +static Mesh *mesh_from_template_ex( + const Mesh *me_src, + int numVerts, int numEdges, int numTessFaces, + int numLoops, int numPolys, + CustomDataMask mask) +{ + const bool do_tessface = ((me_src->totface != 0) && (me_src->totpoly == 0)); /* only do tessface if we have no polys */ + + Mesh *me_dst = MEM_callocN(sizeof(struct Mesh), "Mesh"); + BKE_mesh_init(me_dst); + + me_dst->mat = MEM_dupallocN(me_src->mat); + me_dst->mselect = MEM_dupallocN(me_dst->mselect); + + me_dst->totvert = numVerts; + me_dst->totedge = numEdges; + me_dst->totloop = numLoops; + me_dst->totpoly = numPolys; + + CustomData_copy(&me_src->vdata, &me_dst->vdata, mask, CD_CALLOC, numVerts); + CustomData_copy(&me_src->edata, &me_dst->edata, mask, CD_CALLOC, numEdges); + CustomData_copy(&me_src->ldata, &me_dst->ldata, mask, CD_CALLOC, numLoops); + CustomData_copy(&me_src->pdata, &me_dst->pdata, mask, CD_CALLOC, numPolys); + if (do_tessface) { + CustomData_copy(&me_src->fdata, &me_dst->fdata, mask, CD_CALLOC, numTessFaces); + } + else { + mesh_tessface_clear_intern(me_dst, false); + } + + BKE_mesh_update_customdata_pointers(me_dst, false); + + if (!CustomData_get_layer(&me_dst->vdata, CD_ORIGINDEX)) + CustomData_add_layer(&me_dst->vdata, CD_ORIGINDEX, CD_CALLOC, NULL, numVerts); + if (!CustomData_get_layer(&me_dst->edata, CD_ORIGINDEX)) + CustomData_add_layer(&me_dst->edata, CD_ORIGINDEX, CD_CALLOC, NULL, numEdges); + if (!CustomData_get_layer(&me_dst->pdata, CD_ORIGINDEX)) + CustomData_add_layer(&me_dst->pdata, CD_ORIGINDEX, CD_CALLOC, NULL, numPolys); + + return me_dst; +} + +Mesh * BKE_mesh_from_template(const Mesh *me_src, + int numVerts, int numEdges, int numTessFaces, + int numLoops, int numPolys) +{ + return mesh_from_template_ex( + me_src, + numVerts, numEdges, numTessFaces, + numLoops, numPolys, + CD_MASK_EVERYTHING); +} + Mesh *BKE_mesh_copy(Main *bmain, const Mesh *me) { Mesh *me_copy; @@ -546,143 +673,123 @@ Mesh *BKE_mesh_copy(Main *bmain, const Mesh *me) return me_copy; } -BMesh *BKE_mesh_to_bmesh( - Mesh *me, Object *ob, - const bool add_key_index, const struct BMeshCreateParams *params) +BMesh *BKE_mesh_to_bmesh_ex( + Mesh *me, + const struct BMeshCreateParams *create_params, + const struct BMeshFromMeshParams *convert_params) { BMesh *bm; const BMAllocTemplate allocsize = BMALLOC_TEMPLATE_FROM_ME(me); - bm = BM_mesh_create(&allocsize, params); - - BM_mesh_bm_from_me( - bm, me, (&(struct BMeshFromMeshParams){ - .add_key_index = add_key_index, .use_shapekey = true, .active_shapekey = ob->shapenr, - })); + bm = BM_mesh_create(&allocsize, create_params); + BM_mesh_bm_from_me(bm, me, convert_params); return bm; } +BMesh *BKE_mesh_to_bmesh( + Mesh *me, Object *ob, + const bool add_key_index, const struct BMeshCreateParams *params) +{ + struct BMeshFromMeshParams convert_params = { + .calc_face_normal = false, + .add_key_index = add_key_index, + .use_shapekey = true, + .active_shapekey = ob->shapenr, + }; + return BKE_mesh_to_bmesh_ex(me, params, &convert_params); +} + +Mesh *BKE_bmesh_to_mesh(BMesh *bm, const struct BMeshToMeshParams *params) +{ + Mesh *mesh = BKE_libblock_alloc_notest(ID_ME); + BKE_mesh_init(mesh); + BM_mesh_bm_to_me(bm, mesh, params); + return mesh; +} + void BKE_mesh_make_local(Main *bmain, Mesh *me, const bool lib_local) { BKE_id_make_local_generic(bmain, &me->id, true, lib_local); } -bool BKE_mesh_uv_cdlayer_rename_index(Mesh *me, const int poly_index, const int loop_index, const int face_index, - const char *new_name, const bool do_tessface) +bool BKE_mesh_uv_cdlayer_rename_index( + Mesh *me, const int loop_index, const int face_index, + const char *new_name, const bool do_tessface) { - CustomData *pdata, *ldata, *fdata; - CustomDataLayer *cdlp, *cdlu, *cdlf; - const int step = do_tessface ? 3 : 2; - int i; + CustomData *ldata, *fdata; + CustomDataLayer *cdlu, *cdlf; if (me->edit_btmesh) { - pdata = &me->edit_btmesh->bm->pdata; ldata = &me->edit_btmesh->bm->ldata; fdata = NULL; /* No tessellated data in BMesh! */ } else { - pdata = &me->pdata; 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; + 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); } - /* 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++) { - switch (i % step) { - case 0: - BLI_strncpy(cdlp->name, cdlu->name, sizeof(cdlp->name)); - CustomData_set_layer_unique_name(pdata, cdlp - pdata->layers); - break; - case 1: - BLI_strncpy(cdlu->name, cdlp->name, sizeof(cdlu->name)); - CustomData_set_layer_unique_name(ldata, cdlu - ldata->layers); - break; - case 2: - if (cdlf) { - BLI_strncpy(cdlf->name, cdlp->name, sizeof(cdlf->name)); - CustomData_set_layer_unique_name(fdata, cdlf - fdata->layers); - } - break; - } + if (cdlf == NULL) { + return false; } + BLI_strncpy(cdlf->name, cdlu->name, sizeof(cdlf->name)); + CustomData_set_layer_unique_name(fdata, face_index); + return true; } 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; - } + if (lidx == -1) { + if (fidx == -1) { + /* No layer found with this name! */ + return false; } - pidx = lidx; - } - else { - if (lidx == -1) { - lidx = pidx; - } - 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, lidx, fidx, new_name, do_tessface); } } @@ -760,6 +867,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; @@ -1383,7 +1502,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); } @@ -1603,10 +1721,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(Depsgraph *depsgraph, 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(depsgraph, scene, ob, CD_MASK_MESH); ListBase nurblist = {NULL, NULL}; bool needsFree = false; @@ -2388,13 +2506,13 @@ 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, - int apply_modifiers, int settings, int calc_tessface, int calc_undeformed) + Depsgraph *depsgraph, Main *bmain, Scene *sce, Object *ob, + int apply_modifiers, int calc_tessface, int calc_undeformed) { Mesh *tmpmesh; Curve *tmpcu = NULL, *copycu; int i; - const bool render = (settings == eModifierMode_Render); + const bool render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); const bool cage = !apply_modifiers; bool do_mat_id_data_us = true; @@ -2447,7 +2565,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(depsgraph, sce, tmpobj, &dispbase, &derivedFinal, false, render); copycu->editfont = NULL; copycu->editnurb = NULL; @@ -2496,13 +2614,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 rethought. - */ - 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(depsgraph, sce, ob, &disp); BKE_mesh_from_metaball(&disp, tmpmesh); BKE_displist_free(&disp); } @@ -2541,9 +2653,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(depsgraph, sce, ob, mask); else - dm = mesh_create_derived_view(sce, ob, mask); + dm = mesh_create_derived_view(depsgraph, sce, ob, mask); tmpmesh = BKE_mesh_add(bmain, ((ID *)ob->data)->name + 2); DM_to_mesh(dm, tmpmesh, ob, mask, true); @@ -2632,13 +2744,31 @@ Mesh *BKE_mesh_new_from_object( return tmpmesh; } + /* **** Depsgraph evaluation **** */ -void BKE_mesh_eval_geometry(EvaluationContext *UNUSED(eval_ctx), +void BKE_mesh_eval_geometry(Depsgraph *depsgraph, Mesh *mesh) { - DEG_debug_print_eval(__func__, mesh->id.name, mesh); + DEG_debug_print_eval(depsgraph, __func__, mesh->id.name, mesh); if (mesh->bb == NULL || (mesh->bb->flag & BOUNDBOX_DIRTY)) { 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->runtime.batch_cache) { + BKE_mesh_batch_cache_dirty_cb(me, mode); + } +} +void BKE_mesh_batch_cache_free(Mesh *me) +{ + if (me->runtime.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 a67c9de6deb..01cee2a19ff 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -1828,152 +1828,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 * \{ */ @@ -2545,12 +2399,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) */ @@ -2558,17 +2412,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); @@ -2620,14 +2470,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); @@ -2637,17 +2487,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); } @@ -2970,7 +2817,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 @@ -2991,7 +2838,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. @@ -3183,7 +3030,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); @@ -3223,7 +3070,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; @@ -3245,9 +3092,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 { @@ -3265,9 +3113,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); } @@ -3282,11 +3131,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; @@ -3297,9 +3146,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++; @@ -3406,7 +3252,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); } @@ -3449,7 +3295,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 */ @@ -3499,7 +3345,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_merge.c b/source/blender/blenkernel/intern/mesh_merge.c new file mode 100644 index 00000000000..78e470dda4e --- /dev/null +++ b/source/blender/blenkernel/intern/mesh_merge.c @@ -0,0 +1,684 @@ +/* + * ***** 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_merge.c + * \ingroup bke + */ +#include <string.h> // for memcpy + +#include "MEM_guardedalloc.h" + +#include "DNA_mesh_types.h" +#include "DNA_meshdata_types.h" + +#include "BLI_utildefines.h" +#include "BLI_utildefines_stack.h" +#include "BLI_edgehash.h" +#include "BLI_ghash.h" + +#include "BKE_customdata.h" +#include "BKE_mesh.h" +#include "BKE_mesh_mapping.h" + + +/** + * Poly compare with vtargetmap + * Function used by #BKE_mesh_merge_verts. + * The function compares poly_source after applying vtargetmap, with poly_target. + * The two polys are identical if they share the same vertices in the same order, or in reverse order, + * but starting position loopstart may be different. + * The function is called with direct_reverse=1 for same order (i.e. same normal), + * and may be called again with direct_reverse=-1 for reverse order. + * \return 1 if polys are identical, 0 if polys are different. + */ +static int cddm_poly_compare( + MLoop *mloop_array, + MPoly *mpoly_source, MPoly *mpoly_target, + const int *vtargetmap, const int direct_reverse) +{ + int vert_source, first_vert_source, vert_target; + int i_loop_source; + int i_loop_target, i_loop_target_start, i_loop_target_offset, i_loop_target_adjusted; + bool compare_completed = false; + bool same_loops = false; + + MLoop *mloop_source, *mloop_target; + + BLI_assert(direct_reverse == 1 || direct_reverse == -1); + + i_loop_source = 0; + mloop_source = mloop_array + mpoly_source->loopstart; + vert_source = mloop_source->v; + + if (vtargetmap[vert_source] != -1) { + vert_source = vtargetmap[vert_source]; + } + else { + /* All source loop vertices should be mapped */ + BLI_assert(false); + } + + /* Find same vertex within mpoly_target's loops */ + mloop_target = mloop_array + mpoly_target->loopstart; + for (i_loop_target = 0; i_loop_target < mpoly_target->totloop; i_loop_target++, mloop_target++) { + if (mloop_target->v == vert_source) { + break; + } + } + + /* If same vertex not found, then polys cannot be equal */ + if (i_loop_target >= mpoly_target->totloop) { + return false; + } + + /* Now mloop_source and m_loop_target have one identical vertex */ + /* mloop_source is at position 0, while m_loop_target has advanced to find identical vertex */ + /* Go around the loop and check that all vertices match in same order */ + /* Skipping source loops when consecutive source vertices are mapped to same target vertex */ + + i_loop_target_start = i_loop_target; + i_loop_target_offset = 0; + first_vert_source = vert_source; + + compare_completed = false; + same_loops = false; + + while (!compare_completed) { + + vert_target = mloop_target->v; + + /* First advance i_loop_source, until it points to different vertex, after mapping applied */ + do { + i_loop_source++; + + if (i_loop_source == mpoly_source->totloop) { + /* End of loops for source, must match end of loop for target. */ + if (i_loop_target_offset == mpoly_target->totloop - 1) { + compare_completed = true; + same_loops = true; + break; /* Polys are identical */ + } + else { + compare_completed = true; + same_loops = false; + break; /* Polys are different */ + } + } + + mloop_source++; + vert_source = mloop_source->v; + + if (vtargetmap[vert_source] != -1) { + vert_source = vtargetmap[vert_source]; + } + else { + /* All source loop vertices should be mapped */ + BLI_assert(false); + } + + } while (vert_source == vert_target); + + if (compare_completed) { + break; + } + + /* Now advance i_loop_target as well */ + i_loop_target_offset++; + + if (i_loop_target_offset == mpoly_target->totloop) { + /* End of loops for target only, that means no match */ + /* except if all remaining source vertices are mapped to first target */ + for (; i_loop_source < mpoly_source->totloop; i_loop_source++, mloop_source++) { + vert_source = vtargetmap[mloop_source->v]; + if (vert_source != first_vert_source) { + compare_completed = true; + same_loops = false; + break; + } + } + if (!compare_completed) { + same_loops = true; + } + break; + } + + /* Adjust i_loop_target for cycling around and for direct/reverse order defined by delta = +1 or -1 */ + i_loop_target_adjusted = (i_loop_target_start + direct_reverse * i_loop_target_offset) % mpoly_target->totloop; + if (i_loop_target_adjusted < 0) { + i_loop_target_adjusted += mpoly_target->totloop; + } + mloop_target = mloop_array + mpoly_target->loopstart + i_loop_target_adjusted; + vert_target = mloop_target->v; + + if (vert_target != vert_source) { + same_loops = false; /* Polys are different */ + break; + } + } + return same_loops; +} + + +/* Utility stuff for using GHash with polys, used by vertex merging. */ + +typedef struct PolyKey { + int poly_index; /* index of the MPoly within the derived mesh */ + int totloops; /* number of loops in the poly */ + unsigned int hash_sum; /* Sum of all vertices indices */ + unsigned int hash_xor; /* Xor of all vertices indices */ +} PolyKey; + + +static unsigned int poly_gset_hash_fn(const void *key) +{ + const PolyKey *pk = key; + return pk->hash_sum; +} + +static bool poly_gset_compare_fn(const void *k1, const void *k2) +{ + const PolyKey *pk1 = k1; + const PolyKey *pk2 = k2; + if ((pk1->hash_sum == pk2->hash_sum) && + (pk1->hash_xor == pk2->hash_xor) && + (pk1->totloops == pk2->totloops)) + { + /* Equality - note that this does not mean equality of polys */ + return false; + } + else { + return true; + } +} + +/** + * Merge Verts + * + * This frees the given mesh and returns a new mesh. + * + * \param vtargetmap The table that maps vertices to target vertices. a value of -1 + * indicates a vertex is a target, and is to be kept. + * This array is aligned with 'mesh->totvert' + * \warning \a vtargetmap must **not** contain any chained mapping (v1 -> v2 -> v3 etc.), this is not supported + * and will likely generate corrupted geometry. + * + * \param tot_vtargetmap The number of non '-1' values in vtargetmap. (not the size) + * + * \param merge_mode enum with two modes. + * - #MESH_MERGE_VERTS_DUMP_IF_MAPPED + * When called by the Mirror Modifier, + * In this mode it skips any faces that have all vertices merged (to avoid creating pairs + * of faces sharing the same set of vertices) + * - #MESH_MERGE_VERTS_DUMP_IF_EQUAL + * When called by the Array Modifier, + * In this mode, faces where all vertices are merged are double-checked, + * to see whether all target vertices actually make up a poly already. + * Indeed it could be that all of a poly's vertices are merged, + * but merged to vertices that do not make up a single poly, + * in which case the original poly should not be dumped. + * Actually this later behavior could apply to the Mirror Modifier as well, but the additional checks are + * costly and not necessary in the case of mirror, because each vertex is only merged to its own mirror. + * + * \note #BKE_mesh_recalc_tessellation has to run on the returned DM if you want to access tessfaces. + */ +Mesh *BKE_mesh_merge_verts(Mesh *mesh, const int *vtargetmap, const int tot_vtargetmap, const int merge_mode) +{ + /* This was commented out back in 2013, see commit f45d8827bafe6b9eaf9de42f4054e9d84a21955d. */ +// #define USE_LOOPS + + Mesh *result = NULL; + + const int totvert = mesh->totvert; + const int totedge = mesh->totedge; + const int totloop = mesh->totloop; + const int totpoly = mesh->totpoly; + + const int totvert_final = totvert - tot_vtargetmap; + + MVert *mv, *mvert = MEM_malloc_arrayN(totvert_final, sizeof(*mvert), __func__); + int *oldv = MEM_malloc_arrayN(totvert_final, sizeof(*oldv), __func__); + int *newv = MEM_malloc_arrayN(totvert, sizeof(*newv), __func__); + STACK_DECLARE(mvert); + STACK_DECLARE(oldv); + + /* Note: create (totedge + totloop) elements because partially invalid polys due to merge may require + * generating new edges, and while in 99% cases we'll still end with less final edges than totedge, + * cases can be forged that would end requiring more... */ + MEdge *med, *medge = MEM_malloc_arrayN((totedge + totloop), sizeof(*medge), __func__); + int *olde = MEM_malloc_arrayN((totedge + totloop), sizeof(*olde), __func__); + int *newe = MEM_malloc_arrayN((totedge + totloop), sizeof(*newe), __func__); + STACK_DECLARE(medge); + STACK_DECLARE(olde); + + MLoop *ml, *mloop = MEM_malloc_arrayN(totloop, sizeof(*mloop), __func__); + int *oldl = MEM_malloc_arrayN(totloop, sizeof(*oldl), __func__); +#ifdef USE_LOOPS + int *newl = MEM_malloc_arrayN(totloop, sizeof(*newl), __func__); +#endif + STACK_DECLARE(mloop); + STACK_DECLARE(oldl); + + MPoly *mp, *mpoly = MEM_malloc_arrayN(totpoly, sizeof(*medge), __func__); + int *oldp = MEM_malloc_arrayN(totpoly, sizeof(*oldp), __func__); + STACK_DECLARE(mpoly); + STACK_DECLARE(oldp); + + EdgeHash *ehash = BLI_edgehash_new_ex(__func__, totedge); + + int i, j, c; + + PolyKey *poly_keys; + GSet *poly_gset = NULL; + MeshElemMap *poly_map = NULL; + int *poly_map_mem = NULL; + + STACK_INIT(oldv, totvert_final); + STACK_INIT(olde, totedge); + STACK_INIT(oldl, totloop); + STACK_INIT(oldp, totpoly); + + STACK_INIT(mvert, totvert_final); + STACK_INIT(medge, totedge); + STACK_INIT(mloop, totloop); + STACK_INIT(mpoly, totpoly); + + /* fill newv with destination vertex indices */ + mv = mesh->mvert; + c = 0; + for (i = 0; i < totvert; i++, mv++) { + if (vtargetmap[i] == -1) { + STACK_PUSH(oldv, i); + STACK_PUSH(mvert, *mv); + newv[i] = c++; + } + else { + /* dummy value */ + newv[i] = 0; + } + } + + /* now link target vertices to destination indices */ + for (i = 0; i < totvert; i++) { + if (vtargetmap[i] != -1) { + newv[i] = newv[vtargetmap[i]]; + } + } + + /* Don't remap vertices in cddm->mloop, because we need to know the original + * indices in order to skip faces with all vertices merged. + * The "update loop indices..." section further down remaps vertices in mloop. + */ + + /* now go through and fix edges and faces */ + med = mesh->medge; + c = 0; + for (i = 0; i < totedge; i++, med++) { + const unsigned int v1 = (vtargetmap[med->v1] != -1) ? vtargetmap[med->v1] : med->v1; + const unsigned int v2 = (vtargetmap[med->v2] != -1) ? vtargetmap[med->v2] : med->v2; + if (LIKELY(v1 != v2)) { + void **val_p; + + if (BLI_edgehash_ensure_p(ehash, v1, v2, &val_p)) { + newe[i] = GET_INT_FROM_POINTER(*val_p); + } + else { + STACK_PUSH(olde, i); + STACK_PUSH(medge, *med); + newe[i] = c; + *val_p = SET_INT_IN_POINTER(c); + c++; + } + } + else { + newe[i] = -1; + } + } + + if (merge_mode == MESH_MERGE_VERTS_DUMP_IF_EQUAL) { + /* In this mode, we need to determine, whenever a poly' vertices are all mapped */ + /* if the targets already make up a poly, in which case the new poly is dropped */ + /* This poly equality check is rather complex. We use a BLI_ghash to speed it up with a first level check */ + PolyKey *mpgh; + poly_keys = MEM_malloc_arrayN(totpoly, sizeof(PolyKey), __func__); + poly_gset = BLI_gset_new_ex(poly_gset_hash_fn, poly_gset_compare_fn, __func__, totpoly); + /* Duplicates allowed because our compare function is not pure equality */ + BLI_gset_flag_set(poly_gset, GHASH_FLAG_ALLOW_DUPES); + + mp = mesh->mpoly; + mpgh = poly_keys; + for (i = 0; i < totpoly; i++, mp++, mpgh++) { + mpgh->poly_index = i; + mpgh->totloops = mp->totloop; + ml = mesh->mloop + mp->loopstart; + mpgh->hash_sum = mpgh->hash_xor = 0; + for (j = 0; j < mp->totloop; j++, ml++) { + mpgh->hash_sum += ml->v; + mpgh->hash_xor ^= ml->v; + } + BLI_gset_insert(poly_gset, mpgh); + } + + /* Can we optimise by reusing an old pmap ? How do we know an old pmap is stale ? */ + /* When called by MOD_array.c, the cddm has just been created, so it has no valid pmap. */ + BKE_mesh_vert_poly_map_create(&poly_map, &poly_map_mem, + mesh->mpoly, mesh->mloop, + totvert, totpoly, totloop); + } /* done preparing for fast poly compare */ + + + mp = mesh->mpoly; + mv = mesh->mvert; + for (i = 0; i < totpoly; i++, mp++) { + MPoly *mp_new; + + ml = mesh->mloop + mp->loopstart; + + /* check faces with all vertices merged */ + bool all_vertices_merged = true; + + for (j = 0; j < mp->totloop; j++, ml++) { + if (vtargetmap[ml->v] == -1) { + all_vertices_merged = false; + /* This will be used to check for poly using several time the same vert. */ + mv[ml->v].flag &= ~ME_VERT_TMP_TAG; + } + else { + /* This will be used to check for poly using several time the same vert. */ + mv[vtargetmap[ml->v]].flag &= ~ME_VERT_TMP_TAG; + } + } + + if (UNLIKELY(all_vertices_merged)) { + if (merge_mode == MESH_MERGE_VERTS_DUMP_IF_MAPPED) { + /* In this mode, all vertices merged is enough to dump face */ + continue; + } + else if (merge_mode == MESH_MERGE_VERTS_DUMP_IF_EQUAL) { + /* Additional condition for face dump: target vertices must make up an identical face */ + /* The test has 2 steps: (1) first step is fast ghash lookup, but not failproof */ + /* (2) second step is thorough but more costly poly compare */ + int i_poly, v_target; + bool found = false; + PolyKey pkey; + + /* Use poly_gset for fast (although not 100% certain) identification of same poly */ + /* First, make up a poly_summary structure */ + ml = mesh->mloop + mp->loopstart; + pkey.hash_sum = pkey.hash_xor = 0; + pkey.totloops = 0; + for (j = 0; j < mp->totloop; j++, ml++) { + v_target = vtargetmap[ml->v]; /* Cannot be -1, they are all mapped */ + pkey.hash_sum += v_target; + pkey.hash_xor ^= v_target; + pkey.totloops++; + } + if (BLI_gset_haskey(poly_gset, &pkey)) { + + /* There might be a poly that matches this one. + * We could just leave it there and say there is, and do a "continue". + * ... but we are checking whether there is an exact poly match. + * It's not so costly in terms of CPU since it's very rare, just a lot of complex code. + */ + + /* Consider current loop again */ + ml = mesh->mloop + mp->loopstart; + /* Consider the target of the loop's first vert */ + v_target = vtargetmap[ml->v]; + /* Now see if v_target belongs to a poly that shares all vertices with source poly, + * in same order, or reverse order */ + + for (i_poly = 0; i_poly < poly_map[v_target].count; i_poly++) { + MPoly *target_poly = mesh->mpoly + *(poly_map[v_target].indices + i_poly); + + if (cddm_poly_compare(mesh->mloop, mp, target_poly, vtargetmap, +1) || + cddm_poly_compare(mesh->mloop, mp, target_poly, vtargetmap, -1)) + { + found = true; + break; + } + } + if (found) { + /* Current poly's vertices are mapped to a poly that is strictly identical */ + /* Current poly is dumped */ + continue; + } + } + } + } + + + /* Here either the poly's vertices were not all merged + * or they were all merged, but targets do not make up an identical poly, + * the poly is retained. + */ + ml = mesh->mloop + mp->loopstart; + + c = 0; + MLoop *last_valid_ml = NULL; + MLoop *first_valid_ml = NULL; + bool need_edge_from_last_valid_ml = false; + bool need_edge_to_first_valid_ml = false; + int created_edges = 0; + for (j = 0; j < mp->totloop; j++, ml++) { + const uint mlv = (vtargetmap[ml->v] != -1) ? vtargetmap[ml->v] : ml->v; +#ifndef NDEBUG + { + MLoop *next_ml = mesh->mloop + mp->loopstart + ((j + 1) % mp->totloop); + uint next_mlv = (vtargetmap[next_ml->v] != -1) ? vtargetmap[next_ml->v] : next_ml->v; + med = mesh->medge + ml->e; + uint v1 = (vtargetmap[med->v1] != -1) ? vtargetmap[med->v1] : med->v1; + uint v2 = (vtargetmap[med->v2] != -1) ? vtargetmap[med->v2] : med->v2; + BLI_assert((mlv == v1 && next_mlv == v2) || (mlv == v2 && next_mlv == v1)); + } +#endif + /* A loop is only valid if its matching edge is, and it's not reusing a vertex already used by this poly. */ + if (LIKELY((newe[ml->e] != -1) && ((mv[mlv].flag & ME_VERT_TMP_TAG) == 0))) { + mv[mlv].flag |= ME_VERT_TMP_TAG; + + if (UNLIKELY(last_valid_ml != NULL && need_edge_from_last_valid_ml)) { + /* We need to create a new edge between last valid loop and this one! */ + void **val_p; + + uint v1 = (vtargetmap[last_valid_ml->v] != -1) ? vtargetmap[last_valid_ml->v] : last_valid_ml->v; + uint v2 = mlv; + BLI_assert(v1 != v2); + if (BLI_edgehash_ensure_p(ehash, v1, v2, &val_p)) { + last_valid_ml->e = GET_INT_FROM_POINTER(*val_p); + } + else { + const int new_eidx = STACK_SIZE(medge); + STACK_PUSH(olde, olde[last_valid_ml->e]); + STACK_PUSH(medge, mesh->medge[last_valid_ml->e]); + medge[new_eidx].v1 = last_valid_ml->v; + medge[new_eidx].v2 = ml->v; + /* DO NOT change newe mapping, could break actual values due to some deleted original edges. */ + *val_p = SET_INT_IN_POINTER(new_eidx); + created_edges++; + + last_valid_ml->e = new_eidx; + } + need_edge_from_last_valid_ml = false; + } + +#ifdef USE_LOOPS + newl[j + mp->loopstart] = STACK_SIZE(mloop); +#endif + STACK_PUSH(oldl, j + mp->loopstart); + last_valid_ml = STACK_PUSH_RET_PTR(mloop); + *last_valid_ml = *ml; + if (first_valid_ml == NULL) { + first_valid_ml = last_valid_ml; + } + c++; + + /* We absolutely HAVE to handle edge index remapping here, otherwise potential newly created edges + * in that part of code make remapping later totally unreliable. */ + BLI_assert(newe[ml->e] != -1); + last_valid_ml->e = newe[ml->e]; + } + else { + if (last_valid_ml != NULL) { + need_edge_from_last_valid_ml = true; + } + else { + need_edge_to_first_valid_ml = true; + } + } + } + if (UNLIKELY(last_valid_ml != NULL && !ELEM(first_valid_ml, NULL, last_valid_ml) && + (need_edge_to_first_valid_ml || need_edge_from_last_valid_ml))) + { + /* We need to create a new edge between last valid loop and first valid one! */ + void **val_p; + + uint v1 = (vtargetmap[last_valid_ml->v] != -1) ? vtargetmap[last_valid_ml->v] : last_valid_ml->v; + uint v2 = (vtargetmap[first_valid_ml->v] != -1) ? vtargetmap[first_valid_ml->v] : first_valid_ml->v; + BLI_assert(v1 != v2); + if (BLI_edgehash_ensure_p(ehash, v1, v2, &val_p)) { + last_valid_ml->e = GET_INT_FROM_POINTER(*val_p); + } + else { + const int new_eidx = STACK_SIZE(medge); + STACK_PUSH(olde, olde[last_valid_ml->e]); + STACK_PUSH(medge, mesh->medge[last_valid_ml->e]); + medge[new_eidx].v1 = last_valid_ml->v; + medge[new_eidx].v2 = first_valid_ml->v; + /* DO NOT change newe mapping, could break actual values due to some deleted original edges. */ + *val_p = SET_INT_IN_POINTER(new_eidx); + created_edges++; + + last_valid_ml->e = new_eidx; + } + need_edge_to_first_valid_ml = need_edge_from_last_valid_ml = false; + } + + if (UNLIKELY(c == 0)) { + BLI_assert(created_edges == 0); + continue; + } + else if (UNLIKELY(c < 3)) { + STACK_DISCARD(oldl, c); + STACK_DISCARD(mloop, c); + if (created_edges > 0) { + for (j = STACK_SIZE(medge) - created_edges; j < STACK_SIZE(medge); j++) { + BLI_edgehash_remove(ehash, medge[j].v1, medge[j].v2, NULL); + } + STACK_DISCARD(olde, created_edges); + STACK_DISCARD(medge, created_edges); + } + continue; + } + + mp_new = STACK_PUSH_RET_PTR(mpoly); + *mp_new = *mp; + mp_new->totloop = c; + BLI_assert(mp_new->totloop >= 3); + mp_new->loopstart = STACK_SIZE(mloop) - c; + + STACK_PUSH(oldp, i); + } /* end of the loop that tests polys */ + + + if (poly_gset) { + // printf("hash quality %.6f\n", BLI_gset_calc_quality(poly_gset)); + + BLI_gset_free(poly_gset, NULL); + MEM_freeN(poly_keys); + } + + /*create new cddm*/ + result = BKE_mesh_from_template( + mesh, STACK_SIZE(mvert), STACK_SIZE(medge), 0, STACK_SIZE(mloop), STACK_SIZE(mpoly)); + + /*update edge indices and copy customdata*/ + med = medge; + for (i = 0; i < result->totedge; i++, med++) { + BLI_assert(newv[med->v1] != -1); + med->v1 = newv[med->v1]; + BLI_assert(newv[med->v2] != -1); + med->v2 = newv[med->v2]; + + /* Can happen in case vtargetmap contains some double chains, we do not support that. */ + BLI_assert(med->v1 != med->v2); + + CustomData_copy_data(&mesh->edata, &result->edata, olde[i], i, 1); + } + + /*update loop indices and copy customdata*/ + ml = mloop; + for (i = 0; i < result->totloop; i++, ml++) { + /* Edge remapping has already be done in main loop handling part above. */ + BLI_assert(newv[ml->v] != -1); + ml->v = newv[ml->v]; + + CustomData_copy_data(&mesh->ldata, &result->ldata, oldl[i], i, 1); + } + + /*copy vertex customdata*/ + mv = mvert; + for (i = 0; i < result->totvert; i++, mv++) { + CustomData_copy_data(&mesh->vdata, &result->vdata, oldv[i], i, 1); + } + + /*copy poly customdata*/ + mp = mpoly; + for (i = 0; i < result->totpoly; i++, mp++) { + CustomData_copy_data(&mesh->pdata, &result->pdata, oldp[i], i, 1); + } + + /*copy over data. CustomData_add_layer can do this, need to look it up.*/ + memcpy(result->mvert, mvert, sizeof(MVert) * STACK_SIZE(mvert)); + memcpy(result->medge, medge, sizeof(MEdge) * STACK_SIZE(medge)); + memcpy(result->mloop, mloop, sizeof(MLoop) * STACK_SIZE(mloop)); + memcpy(result->mpoly, mpoly, sizeof(MPoly) * STACK_SIZE(mpoly)); + + MEM_freeN(mvert); + MEM_freeN(medge); + MEM_freeN(mloop); + MEM_freeN(mpoly); + + MEM_freeN(newv); + MEM_freeN(newe); +#ifdef USE_LOOPS + MEM_freeN(newl); +#endif + + MEM_freeN(oldv); + MEM_freeN(olde); + MEM_freeN(oldl); + MEM_freeN(oldp); + + BLI_edgehash_free(ehash, NULL); + + if (poly_map != NULL) + MEM_freeN(poly_map); + if (poly_map_mem != NULL) + MEM_freeN(poly_map_mem); + + BKE_mesh_free(mesh); + MEM_freeN(mesh); + + return result; +} diff --git a/source/blender/blenkernel/intern/mesh_tangent.c b/source/blender/blenkernel/intern/mesh_tangent.c new file mode 100644 index 00000000000..05a5a5e8703 --- /dev/null +++ b/source/blender/blenkernel/intern/mesh_tangent.c @@ -0,0 +1,691 @@ +/* + * ***** 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 b0577fdd50d..8301b6a42b1 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 ce04f3c31e2..6722ed2aab1 100644 --- a/source/blender/blenkernel/intern/modifier.c +++ b/source/blender/blenkernel/intern/modifier.c @@ -46,6 +46,7 @@ #include "MEM_guardedalloc.h" #include "DNA_armature_types.h" +#include "DNA_mesh_types.h" #include "DNA_object_types.h" #include "BLI_utildefines.h" @@ -58,9 +59,11 @@ #include "BLT_translation.h" #include "BKE_appdir.h" +#include "BKE_cdderivedmesh.h" #include "BKE_key.h" #include "BKE_library.h" #include "BKE_library_query.h" +#include "BKE_mesh.h" #include "BKE_multires.h" #include "BKE_DerivedMesh.h" @@ -69,6 +72,8 @@ #include "BKE_main.h" /* end */ +#include "DEG_depsgraph.h" + #include "MOD_modifiertypes.h" static ModifierTypeInfo *modifier_types[NUM_MODIFIER_TYPES] = {NULL}; @@ -679,7 +684,7 @@ bool modifiers_usesArmature(Object *ob, bArmature *arm) bool modifier_isCorrectableDeformed(ModifierData *md) { const ModifierTypeInfo *mti = modifierType_getInfo(md->type); - return (mti->deformMatricesEM != NULL); + return (mti->deformMatricesEM != NULL) || (mti->deformMatricesEM_DM != NULL); } bool modifiers_isCorrectableDeformed(struct Scene *scene, Object *ob) @@ -688,9 +693,9 @@ bool modifiers_isCorrectableDeformed(struct Scene *scene, Object *ob) ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData); int required_mode = eModifierMode_Realtime; - if (ob->mode == OB_MODE_EDIT) + if (ob->mode == OB_MODE_EDIT) { required_mode |= eModifierMode_Editmode; - + } for (; md; md = md->next) { if (!modifier_isEnabled(scene, md, required_mode)) { /* pass */ @@ -784,9 +789,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, - ModifierApplyFlag flag) + ModifierData *md, const ModifierEvalContext *ctx, + struct DerivedMesh *dm) { const ModifierTypeInfo *mti = modifierType_getInfo(md->type); BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); @@ -794,14 +798,12 @@ struct DerivedMesh *modwrap_applyModifier( if (mti->dependsOnNormals && mti->dependsOnNormals(md)) { DM_ensure_normals(dm); } - return mti->applyModifier(md, ob, dm, flag); + return modifier_applyModifier_DM_deprecated(md, ctx, dm); } struct DerivedMesh *modwrap_applyModifierEM( - ModifierData *md, Object *ob, - struct BMEditMesh *em, - DerivedMesh *dm, - ModifierApplyFlag flag) + ModifierData *md, const ModifierEvalContext *ctx, + struct BMEditMesh *em, DerivedMesh *dm) { const ModifierTypeInfo *mti = modifierType_getInfo(md->type); BLI_assert(CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); @@ -809,14 +811,12 @@ struct DerivedMesh *modwrap_applyModifierEM( if (mti->dependsOnNormals && mti->dependsOnNormals(md)) { DM_ensure_normals(dm); } - return mti->applyModifierEM(md, ob, em, dm, flag); + return modifier_applyModifierEM_DM_deprecated(md, ctx, em, dm); } void modwrap_deformVerts( - ModifierData *md, Object *ob, - DerivedMesh *dm, - float (*vertexCos)[3], int numVerts, - ModifierApplyFlag flag) + ModifierData *md, const ModifierEvalContext *ctx, + DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { const ModifierTypeInfo *mti = modifierType_getInfo(md->type); BLI_assert(!dm || CustomData_has_layer(&dm->polyData, CD_NORMAL) == false); @@ -824,11 +824,11 @@ void modwrap_deformVerts( if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) { DM_ensure_normals(dm); } - mti->deformVerts(md, ob, dm, vertexCos, numVerts, flag); + modifier_deformVerts_DM_deprecated(md, ctx, dm, vertexCos, numVerts); } void modwrap_deformVertsEM( - ModifierData *md, Object *ob, + ModifierData *md, const ModifierEvalContext *ctx, struct BMEditMesh *em, DerivedMesh *dm, float (*vertexCos)[3], int numVerts) { @@ -838,6 +838,333 @@ void modwrap_deformVertsEM( if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) { DM_ensure_normals(dm); } - mti->deformVertsEM(md, ob, em, dm, vertexCos, numVerts); + modifier_deformVertsEM_DM_deprecated(md, ctx, em, dm, vertexCos, numVerts); } /* end modifier callback wrappers */ + + +/* wrappers for modifier callbacks that accept Mesh and select the proper implementation + * depending on if the modifier has been ported to Mesh or is still using DerivedMesh + */ + +void modifier_deformVerts(struct ModifierData *md, const ModifierEvalContext *ctx, + struct Mesh *mesh, + float (*vertexCos)[3], int numVerts) +{ + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + + if (mti->deformVerts) { + mti->deformVerts(md, ctx, mesh, vertexCos, numVerts); + } + else { + DerivedMesh *dm = NULL; + if (mesh) { + dm = CDDM_from_mesh(mesh); + } + + mti->deformVerts_DM(md, ctx, dm, vertexCos, numVerts); + + if (dm) { + dm->release(dm); + } + } +} + +void modifier_deformMatrices(struct ModifierData *md, const ModifierEvalContext *ctx, + struct Mesh *mesh, + float (*vertexCos)[3], float (*defMats)[3][3], int numVerts) +{ + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + + if (mti->deformMatrices) { + mti->deformMatrices(md, ctx, mesh, vertexCos, defMats, numVerts); + } + else { + DerivedMesh *dm = NULL; + if (mesh) { + dm = CDDM_from_mesh(mesh); + } + + mti->deformMatrices_DM(md, ctx, dm, vertexCos, defMats, numVerts); + + if (dm) { + dm->release(dm); + } + } +} + +void modifier_deformVertsEM(struct ModifierData *md, const ModifierEvalContext *ctx, + struct BMEditMesh *editData, struct Mesh *mesh, + float (*vertexCos)[3], int numVerts) +{ + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + + if (mti->deformVertsEM) { + mti->deformVertsEM(md, ctx, editData, mesh, vertexCos, numVerts); + } + else { + DerivedMesh *dm = NULL; + if (mesh) { + dm = CDDM_from_mesh(mesh); + } + + mti->deformVertsEM_DM(md, ctx, editData, dm, vertexCos, numVerts); + + if (dm) { + dm->release(dm); + } + } +} + +void modifier_deformMatricesEM(struct ModifierData *md, const ModifierEvalContext *ctx, + struct BMEditMesh *editData, struct Mesh *mesh, + float (*vertexCos)[3], float (*defMats)[3][3], int numVerts) +{ + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + + if (mti->deformMatricesEM) { + mti->deformMatricesEM(md, ctx, editData, mesh, vertexCos, defMats, numVerts); + } + else { + DerivedMesh *dm = NULL; + if (mesh) { + dm = CDDM_from_mesh(mesh); + } + + mti->deformMatricesEM_DM(md, ctx, editData, dm, vertexCos, defMats, numVerts); + + if (dm) { + dm->release(dm); + } + } +} + +struct Mesh *modifier_applyModifier(struct ModifierData *md, const ModifierEvalContext *ctx, + struct Mesh *mesh) +{ + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + + if (mti->applyModifier) { + return mti->applyModifier(md, ctx, mesh); + } + else { + DerivedMesh *dm = CDDM_from_mesh(mesh); + + DerivedMesh *ndm = mti->applyModifier_DM(md, ctx, dm); + + if(ndm != dm) { + dm->release(dm); + } + + DM_to_mesh(ndm, mesh, ctx->object, CD_MASK_EVERYTHING, true); + + return mesh; + } +} + +struct Mesh *modifier_applyModifierEM(struct ModifierData *md, const ModifierEvalContext *ctx, + struct BMEditMesh *editData, + struct Mesh *mesh) +{ + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + + if (mti->applyModifierEM) { + return mti->applyModifierEM(md, ctx, editData, mesh); + } + else { + DerivedMesh *dm = CDDM_from_mesh(mesh); + + DerivedMesh *ndm = mti->applyModifierEM_DM(md, ctx, editData, dm); + + if(ndm != dm) { + dm->release(dm); + } + + DM_to_mesh(ndm, mesh, ctx->object, CD_MASK_EVERYTHING, true); + + return mesh; + } +} + +/* depricated variants of above that accept DerivedMesh */ + +void modifier_deformVerts_DM_deprecated(struct ModifierData *md, const ModifierEvalContext *ctx, + struct DerivedMesh *dm, + float (*vertexCos)[3], int numVerts) +{ + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + + if (mti->deformVerts_DM) { + mti->deformVerts_DM(md, ctx, dm, vertexCos, numVerts); + } + else { + /* TODO(sybren): deduplicate all the copies of this code in this file. */ + Mesh *mesh = NULL; + if (dm != NULL) { + mesh = BKE_libblock_alloc_notest(ID_ME); + BKE_mesh_init(mesh); + DM_to_mesh(dm, mesh, ctx->object, CD_MASK_EVERYTHING, false); + } + + mti->deformVerts(md, ctx, mesh, vertexCos, numVerts); + + if (mesh != NULL) { + BKE_mesh_free(mesh); + MEM_freeN(mesh); + } + } +} + +void modifier_deformMatrices_DM_deprecated(struct ModifierData *md, const ModifierEvalContext *ctx, + struct DerivedMesh *dm, + float (*vertexCos)[3], float (*defMats)[3][3], int numVerts) +{ + + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + + if (mti->deformMatrices_DM) { + mti->deformMatrices_DM(md, ctx, dm, vertexCos, defMats, numVerts); + } + else { + /* TODO(sybren): deduplicate all the copies of this code in this file. */ + Mesh *mesh = NULL; + if (dm != NULL) { + mesh = BKE_libblock_alloc_notest(ID_ME); + BKE_mesh_init(mesh); + DM_to_mesh(dm, mesh, ctx->object, CD_MASK_EVERYTHING, false); + } + + mti->deformMatrices(md, ctx, mesh, vertexCos, defMats, numVerts); + + if (mesh != NULL) { + BKE_mesh_free(mesh); + MEM_freeN(mesh); + } + } +} + +void modifier_deformVertsEM_DM_deprecated(struct ModifierData *md, const ModifierEvalContext *ctx, + struct BMEditMesh *editData, struct DerivedMesh *dm, + float (*vertexCos)[3], int numVerts) +{ + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + + if (mti->deformVertsEM_DM) { + mti->deformVertsEM_DM(md, ctx, editData, dm, vertexCos, numVerts); + } + else { + /* TODO(sybren): deduplicate all the copies of this code in this file. */ + Mesh *mesh = NULL; + if (dm != NULL) { + mesh = BKE_libblock_alloc_notest(ID_ME); + BKE_mesh_init(mesh); + DM_to_mesh(dm, mesh, ctx->object, CD_MASK_EVERYTHING, false); + } + + mti->deformVertsEM(md, ctx, editData, mesh, vertexCos, numVerts); + + if (mesh != NULL) { + BKE_mesh_free(mesh); + MEM_freeN(mesh); + } + } +} + +void modifier_deformMatricesEM_DM_deprecated(struct ModifierData *md, const ModifierEvalContext *ctx, + struct BMEditMesh *editData, struct DerivedMesh *dm, + float (*vertexCos)[3], float (*defMats)[3][3], int numVerts) +{ + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + + if (mti->deformMatricesEM_DM) { + mti->deformMatricesEM_DM(md, ctx, editData, dm, vertexCos, defMats, numVerts); + } + else { + /* TODO(sybren): deduplicate all the copies of this code in this file. */ + Mesh *mesh = NULL; + if (dm != NULL) { + mesh = BKE_libblock_alloc_notest(ID_ME); + BKE_mesh_init(mesh); + DM_to_mesh(dm, mesh, ctx->object, CD_MASK_EVERYTHING, false); + } + + mti->deformMatricesEM(md, ctx, editData, mesh, vertexCos, defMats, numVerts); + + if (mesh != NULL) { + BKE_mesh_free(mesh); + MEM_freeN(mesh); + } + } +} + +struct DerivedMesh *modifier_applyModifier_DM_deprecated(struct ModifierData *md, const ModifierEvalContext *ctx, + struct DerivedMesh *dm) +{ + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + + if (mti->applyModifier_DM) { + return mti->applyModifier_DM(md, ctx, dm); + } + else { + /* TODO(sybren): deduplicate all the copies of this code in this file. */ + Mesh *mesh = NULL; + if (dm != NULL) { + mesh = BKE_libblock_alloc_notest(ID_ME); + BKE_mesh_init(mesh); + DM_to_mesh(dm, mesh, ctx->object, CD_MASK_EVERYTHING, false); + } + + struct Mesh *new_mesh = mti->applyModifier(md, ctx, mesh); + + /* Make a DM that doesn't reference new_mesh so we can free the latter. */ + DerivedMesh *ndm = CDDM_from_mesh_ex(new_mesh, CD_DUPLICATE); + + if(new_mesh != mesh) { + BKE_mesh_free(new_mesh); + MEM_freeN(new_mesh); + } + if (mesh != NULL) { + BKE_mesh_free(mesh); + MEM_freeN(mesh); + } + + return ndm; + } +} + +struct DerivedMesh *modifier_applyModifierEM_DM_deprecated(struct ModifierData *md, const ModifierEvalContext *ctx, + struct BMEditMesh *editData, + struct DerivedMesh *dm) +{ + const ModifierTypeInfo *mti = modifierType_getInfo(md->type); + + if (mti->applyModifierEM_DM) { + return mti->applyModifierEM_DM(md, ctx, editData, dm); + } + else { + /* TODO(sybren): deduplicate all the copies of this code in this file. */ + Mesh *mesh = NULL; + if (dm != NULL) { + mesh = BKE_libblock_alloc_notest(ID_ME); + BKE_mesh_init(mesh); + DM_to_mesh(dm, mesh, ctx->object, CD_MASK_EVERYTHING, false); + } + + struct Mesh *new_mesh = mti->applyModifierEM(md, ctx, editData, mesh); + + /* Make a DM that doesn't reference new_mesh so we can free the latter. */ + DerivedMesh *ndm = CDDM_from_mesh_ex(new_mesh, CD_DUPLICATE); + + if(new_mesh != mesh) { + BKE_mesh_free(new_mesh); + MEM_freeN(new_mesh); + } + if (mesh != NULL) { + BKE_mesh_free(mesh); + MEM_freeN(mesh); + } + + return ndm; + } +} + diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index 9ed715d7591..d742bcea69d 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -1609,8 +1609,8 @@ bool BKE_movieclip_put_frame_if_possible(MovieClip *clip, return result; } -void BKE_movieclip_eval_update(struct EvaluationContext *UNUSED(eval_ctx), MovieClip *clip) +void BKE_movieclip_eval_update(struct Depsgraph *depsgraph, MovieClip *clip) { - DEG_debug_print_eval(__func__, clip->id.name, clip); + DEG_debug_print_eval(depsgraph, __func__, clip->id.name, clip); BKE_tracking_dopesheet_tag_update(&clip->tracking); } diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 9c8fc9bfd0c..ee32c2398b2 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -277,14 +277,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(struct Depsgraph *depsgraph, 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(depsgraph, scene, ob, CD_MASK_BAREMESH); DerivedMesh *dm; + ModifierEvalContext mectx = {depsgraph, ob, MOD_APPLY_USECACHE | MOD_APPLY_IGNORE_SIMPLIFY}; - dm = mti->applyModifier(md, ob, tdm, MOD_APPLY_USECACHE | MOD_APPLY_IGNORE_SIMPLIFY); + dm = modifier_applyModifier_DM_deprecated(md, &mectx, tdm); if (dm == tdm) { dm = CDDM_copy(tdm); } @@ -398,10 +398,10 @@ void multires_force_render_update(Object *ob) multires_force_update(ob); } -int multiresModifier_reshapeFromDM(Scene *scene, MultiresModifierData *mmd, +int multiresModifier_reshapeFromDM(struct Depsgraph *depsgraph, Scene *scene, MultiresModifierData *mmd, Object *ob, DerivedMesh *srcdm) { - DerivedMesh *mrdm = get_multires_dm(scene, mmd, ob); + DerivedMesh *mrdm = get_multires_dm(depsgraph, scene, mmd, ob); if (mrdm && srcdm && mrdm->getNumVerts(mrdm) == srcdm->getNumVerts(srcdm)) { multires_mvert_to_ss(mrdm, srcdm->getVertArray(srcdm)); @@ -420,30 +420,30 @@ 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(struct Depsgraph *depsgraph, 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(depsgraph, scene, src, CD_MASK_BAREMESH); + return multiresModifier_reshapeFromDM(depsgraph, scene, mmd, dst, srcdm); } -int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mmd, +int multiresModifier_reshapeFromDeformMod(struct Depsgraph *depsgraph, Scene *scene, MultiresModifierData *mmd, Object *ob, ModifierData *md) { - const ModifierTypeInfo *mti = modifierType_getInfo(md->type); DerivedMesh *dm, *ndm; int numVerts, result; float (*deformedVerts)[3]; + const ModifierEvalContext mectx = {depsgraph, ob, 0}; if (multires_get_level(ob, mmd, false, true) == 0) return 0; /* Create DerivedMesh for deformation modifier */ - dm = get_multires_dm(scene, mmd, ob); + dm = get_multires_dm(depsgraph, 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); + modifier_deformVerts_DM_deprecated(md, &mectx, dm, deformedVerts, numVerts); ndm = CDDM_copy(dm); CDDM_apply_vert_coords(ndm, deformedVerts); @@ -452,7 +452,7 @@ int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mm dm->release(dm); /* Reshaping */ - result = multiresModifier_reshapeFromDM(scene, mmd, ob, ndm); + result = multiresModifier_reshapeFromDM(depsgraph, scene, mmd, ob, ndm); /* Cleanup */ ndm->release(ndm); @@ -2275,7 +2275,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(struct Depsgraph *depsgraph, Scene *scene, Object *ob, float smat[3][3]) { DerivedMesh *dm = NULL, *cddm = NULL, *subdm = NULL; CCGElem **gridData, **subGridData; @@ -2300,10 +2300,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(depsgraph, 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(depsgraph, scene, ob, CD_MASK_BAREMESH); totvert = cddm->getNumVerts(cddm); vertCos = MEM_malloc_arrayN(totvert, sizeof(*vertCos), "multiresScale vertCos"); @@ -2364,17 +2364,17 @@ int multires_mdisp_corners(MDisps *s) return 0; } -void multiresModifier_scale_disp(Scene *scene, Object *ob) +void multiresModifier_scale_disp(struct Depsgraph *depsgraph, 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(depsgraph, scene, ob, smat); } -void multiresModifier_prepare_join(Scene *scene, Object *ob, Object *to_ob) +void multiresModifier_prepare_join(struct Depsgraph *depsgraph, Scene *scene, Object *ob, Object *to_ob) { float smat[3][3], tmat[3][3], mat[3][3]; multires_sync_levels(scene, to_ob, ob); @@ -2385,7 +2385,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(depsgraph, scene, ob, mat); } /* update multires data after topology changing */ diff --git a/source/blender/blenkernel/intern/navmesh_conversion.c b/source/blender/blenkernel/intern/navmesh_conversion.c deleted file mode 100644 index 35bcca52f63..00000000000 --- a/source/blender/blenkernel/intern/navmesh_conversion.c +++ /dev/null @@ -1,502 +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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/blenkernel/intern/navmesh_conversion.c - * \ingroup bke - */ - -#include <math.h> -#include <stdlib.h> - -#include "MEM_guardedalloc.h" - -#include "DNA_meshdata_types.h" - -#include "BLI_utildefines.h" -#include "BLI_math.h" -#include "BLI_sort.h" - -#include "BKE_navmesh_conversion.h" -#include "BKE_cdderivedmesh.h" - -#include "recast-capi.h" - -BLI_INLINE float area2(const float *a, const float *b, const float *c) -{ - return (b[0] - a[0]) * (c[2] - a[2]) - (c[0] - a[0]) * (b[2] - a[2]); -} - -BLI_INLINE int left(const float *a, const float *b, const float *c) -{ - return area2(a, b, c) < 0; -} - -int polyNumVerts(const unsigned short *p, const int vertsPerPoly) -{ - int i, nv = 0; - for (i = 0; i < vertsPerPoly; i++) { - if (p[i] == 0xffff) - break; - nv++; - } - return nv; -} - -int polyIsConvex(const unsigned short *p, const int vertsPerPoly, const float *verts) -{ - int j, nv = polyNumVerts(p, vertsPerPoly); - if (nv < 3) - return 0; - for (j = 0; j < nv; j++) { - const float *v = &verts[3 * p[j]]; - const float *v_next = &verts[3 * p[(j + 1) % nv]]; - const float *v_prev = &verts[3 * p[(nv + j - 1) % nv]]; - if (!left(v_prev, v, v_next)) - return 0; - - } - return 1; -} - -/* XXX, could replace with #dist_to_line_segment_v3(), or add a squared version */ -float distPointToSegmentSq(const float point[3], const float a[3], const float b[3]) -{ - float abx[3], dx[3]; - float d, t; - - sub_v3_v3v3(abx, b, a); - sub_v3_v3v3(dx, point, a); - - d = abx[0] * abx[0] + abx[2] * abx[2]; - t = abx[0] * dx[0] + abx[2] * dx[2]; - - if (d > 0.0f) - t /= d; - if (t < 0.0f) - t = 0.0f; - else if (t > 1.0f) - t = 1.0f; - dx[0] = a[0] + t * abx[0] - point[0]; - dx[2] = a[2] + t * abx[2] - point[2]; - - return dx[0] * dx[0] + dx[2] * dx[2]; -} - -int buildRawVertIndicesData(DerivedMesh *dm, int *nverts_r, float **verts_r, - int *ntris_r, unsigned short **tris_r, int **trisToFacesMap_r, - int **recastData) -{ - int vi, fi, triIdx; - int nverts, ntris; - int *trisToFacesMap; - float *verts; - unsigned short *tris, *tri; - int nfaces; - MFace *faces; - - nverts = dm->getNumVerts(dm); - if (nverts >= 0xffff) { - printf("Converting navmesh: Error! Too many vertices. Max number of vertices %d\n", 0xffff); - return 0; - } - if (nverts == 0) { - printf("Converting navmesh: Error! There are no vertices!\n"); - return 0; - } - - verts = MEM_mallocN(sizeof(float[3]) * nverts, "buildRawVertIndicesData verts"); - dm->getVertCos(dm, (float(*)[3])verts); - - /* flip coordinates */ - for (vi = 0; vi < nverts; vi++) { - SWAP(float, verts[3 * vi + 1], verts[3 * vi + 2]); - } - - /* calculate number of tris */ - dm->recalcTessellation(dm); - nfaces = dm->getNumTessFaces(dm); - if (nfaces == 0) { - printf("Converting navmesh: Error! There are %i vertices, but no faces!\n", nverts); - return 0; - } - - faces = dm->getTessFaceArray(dm); - ntris = nfaces; - for (fi = 0; fi < nfaces; fi++) { - MFace *face = &faces[fi]; - if (face->v4) - ntris++; - } - - /* copy and transform to triangles (reorder on the run) */ - trisToFacesMap = MEM_callocN(sizeof(int) * ntris, "buildRawVertIndicesData trisToFacesMap"); - tris = MEM_callocN(sizeof(unsigned short) * 3 * ntris, "buildRawVertIndicesData tris"); - tri = tris; - triIdx = 0; - for (fi = 0; fi < nfaces; fi++) { - MFace *face = &faces[fi]; - tri[3 * triIdx + 0] = (unsigned short) face->v1; - tri[3 * triIdx + 1] = (unsigned short) face->v3; - tri[3 * triIdx + 2] = (unsigned short) face->v2; - trisToFacesMap[triIdx++] = fi; - if (face->v4) { - tri[3 * triIdx + 0] = (unsigned short) face->v1; - tri[3 * triIdx + 1] = (unsigned short) face->v4; - tri[3 * triIdx + 2] = (unsigned short) face->v3; - trisToFacesMap[triIdx++] = fi; - } - } - - /* carefully, recast data is just reference to data in derived mesh */ - *recastData = (int *)CustomData_get_layer(&dm->polyData, CD_RECAST); - - *nverts_r = nverts; - *verts_r = verts; - *ntris_r = ntris; - *tris_r = tris; - *trisToFacesMap_r = trisToFacesMap; - - return 1; -} - -int buildPolygonsByDetailedMeshes(const int vertsPerPoly, const int npolys, - unsigned short *polys, const unsigned short *dmeshes, - const float *verts, const unsigned short *dtris, - const int *dtrisToPolysMap) -{ - int polyidx; - int capacity = vertsPerPoly; - unsigned short *newPoly = MEM_callocN(sizeof(unsigned short) * capacity, "buildPolygonsByDetailedMeshes newPoly"); - memset(newPoly, 0xff, sizeof(unsigned short) * capacity); - - for (polyidx = 0; polyidx < npolys; polyidx++) { - size_t i; - int j, k; - int nv = 0; - /* search border */ - int tri, btri = -1; - int edge, bedge = -1; - int dtrisNum = dmeshes[polyidx * 4 + 3]; - int dtrisBase = dmeshes[polyidx * 4 + 2]; - unsigned char *traversedTris = MEM_callocN(sizeof(unsigned char) * dtrisNum, "buildPolygonsByDetailedMeshes traversedTris"); - unsigned short *adjustedPoly; - int adjustedNv; - int allBorderTraversed; - - for (j = 0; j < dtrisNum && btri == -1; j++) { - int curpolytri = dtrisBase + j; - for (k = 0; k < 3; k++) { - unsigned short neighbortri = dtris[curpolytri * 3 * 2 + 3 + k]; - if (neighbortri == 0xffff || dtrisToPolysMap[neighbortri] != polyidx + 1) { - btri = curpolytri; - bedge = k; - break; - } - } - } - if (btri == -1 || bedge == -1) { - /* can't find triangle with border edge */ - MEM_freeN(traversedTris); - MEM_freeN(newPoly); - - return 0; - } - - newPoly[nv++] = dtris[btri * 3 * 2 + bedge]; - tri = btri; - edge = (bedge + 1) % 3; - traversedTris[tri - dtrisBase] = 1; - while (tri != btri || edge != bedge) { - int neighbortri = dtris[tri * 3 * 2 + 3 + edge]; - if (neighbortri == 0xffff || dtrisToPolysMap[neighbortri] != polyidx + 1) { - if (nv == capacity) { - unsigned short *newPolyBig; - capacity += vertsPerPoly; - newPolyBig = MEM_callocN(sizeof(unsigned short) * capacity, "buildPolygonsByDetailedMeshes newPolyBig"); - memset(newPolyBig, 0xff, sizeof(unsigned short) * capacity); - memcpy(newPolyBig, newPoly, sizeof(unsigned short) * nv); - MEM_freeN(newPoly); - newPoly = newPolyBig; - } - newPoly[nv++] = dtris[tri * 3 * 2 + edge]; - /* move to next edge */ - edge = (edge + 1) % 3; - } - else { - /* move to next tri */ - int twinedge = -1; - for (k = 0; k < 3; k++) { - if (dtris[neighbortri * 3 * 2 + 3 + k] == tri) { - twinedge = k; - break; - } - } - if (twinedge == -1) { - printf("Converting navmesh: Error! Can't find neighbor edge - invalid adjacency info\n"); - MEM_freeN(traversedTris); - goto returnLabel; - } - tri = neighbortri; - edge = (twinedge + 1) % 3; - traversedTris[tri - dtrisBase] = 1; - } - } - - adjustedPoly = MEM_callocN(sizeof(unsigned short) * nv, "buildPolygonsByDetailedMeshes adjustedPoly"); - adjustedNv = 0; - for (i = 0; i < nv; i++) { - unsigned short prev = newPoly[(nv + i - 1) % nv]; - unsigned short cur = newPoly[i]; - unsigned short next = newPoly[(i + 1) % nv]; - float distSq = distPointToSegmentSq(&verts[3 * cur], &verts[3 * prev], &verts[3 * next]); - static const float tolerance = 0.001f; - if (distSq > tolerance) - adjustedPoly[adjustedNv++] = cur; - } - memcpy(newPoly, adjustedPoly, adjustedNv * sizeof(unsigned short)); - MEM_freeN(adjustedPoly); - nv = adjustedNv; - - allBorderTraversed = 1; - for (i = 0; i < dtrisNum; i++) { - if (traversedTris[i] == 0) { - /* check whether it has border edges */ - int curpolytri = dtrisBase + i; - for (k = 0; k < 3; k++) { - unsigned short neighbortri = dtris[curpolytri * 3 * 2 + 3 + k]; - if (neighbortri == 0xffff || dtrisToPolysMap[neighbortri] != polyidx + 1) { - allBorderTraversed = 0; - break; - } - } - } - } - - if (nv <= vertsPerPoly && allBorderTraversed) { - for (i = 0; i < nv; i++) { - polys[polyidx * vertsPerPoly * 2 + i] = newPoly[i]; - } - } - - MEM_freeN(traversedTris); - } - -returnLabel: - MEM_freeN(newPoly); - - return 1; -} - -struct SortContext { - const int *recastData; - const int *trisToFacesMap; -}; - -static int compareByData(const void *a, const void *b, void *ctx) -{ - return (((struct SortContext *)ctx)->recastData[((struct SortContext *)ctx)->trisToFacesMap[*(int *)a]] - - ((struct SortContext *)ctx)->recastData[((struct SortContext *)ctx)->trisToFacesMap[*(int *)b]]); -} - -int buildNavMeshData(const int nverts, const float *verts, - const int ntris, const unsigned short *tris, - const int *recastData, const int *trisToFacesMap, - int *ndtris_r, unsigned short **dtris_r, - int *npolys_r, unsigned short **dmeshes_r, unsigned short **polys_r, - int *vertsPerPoly_r, int **dtrisToPolysMap_r, int **dtrisToTrisMap_r) - -{ - int *trisMapping; - int i; - struct SortContext context; - int validTriStart, prevPolyIdx, curPolyIdx, newPolyIdx, prevpolyidx; - unsigned short *dmesh; - - int ndtris, npolys, vertsPerPoly; - unsigned short *dtris, *dmeshes, *polys; - int *dtrisToPolysMap, *dtrisToTrisMap; - - if (!recastData) { - printf("Converting navmesh: Error! Can't find recast custom data\n"); - return 0; - } - - trisMapping = MEM_callocN(sizeof(int) * ntris, "buildNavMeshData trisMapping"); - - /* sort the triangles by polygon idx */ - for (i = 0; i < ntris; i++) - trisMapping[i] = i; - context.recastData = recastData; - context.trisToFacesMap = trisToFacesMap; - BLI_qsort_r(trisMapping, ntris, sizeof(int), compareByData, &context); - - /* search first valid triangle - triangle of convex polygon */ - validTriStart = -1; - for (i = 0; i < ntris; i++) { - if (recastData[trisToFacesMap[trisMapping[i]]] > 0) { - validTriStart = i; - break; - } - } - - if (validTriStart < 0) { - printf("Converting navmesh: Error! No valid polygons in mesh\n"); - MEM_freeN(trisMapping); - return 0; - } - - ndtris = ntris - validTriStart; - /* fill dtris to faces mapping */ - dtrisToTrisMap = MEM_callocN(sizeof(int) * ndtris, "buildNavMeshData dtrisToTrisMap"); - memcpy(dtrisToTrisMap, &trisMapping[validTriStart], ndtris * sizeof(int)); - MEM_freeN(trisMapping); - - /* create detailed mesh triangles - copy only valid triangles - * and reserve memory for adjacency info */ - dtris = MEM_callocN(sizeof(unsigned short) * 3 * 2 * ndtris, "buildNavMeshData dtris"); - memset(dtris, 0xff, sizeof(unsigned short) * 3 * 2 * ndtris); - for (i = 0; i < ndtris; i++) { - memcpy(dtris + 3 * 2 * i, tris + 3 * dtrisToTrisMap[i], sizeof(unsigned short) * 3); - } - - /* create new recast data corresponded to dtris and renumber for continuous indices */ - prevPolyIdx = -1; - newPolyIdx = 0; - dtrisToPolysMap = MEM_callocN(sizeof(int) * ndtris, "buildNavMeshData dtrisToPolysMap"); - for (i = 0; i < ndtris; i++) { - curPolyIdx = recastData[trisToFacesMap[dtrisToTrisMap[i]]]; - if (curPolyIdx != prevPolyIdx) { - newPolyIdx++; - prevPolyIdx = curPolyIdx; - } - dtrisToPolysMap[i] = newPolyIdx; - } - - - /* build adjacency info for detailed mesh triangles */ - if (!recast_buildMeshAdjacency(dtris, ndtris, nverts, 3)) { - printf("Converting navmesh: Error! Unable to build mesh adjacency information\n"); - MEM_freeN(trisMapping); - MEM_freeN(dtrisToPolysMap); - return 0; - } - - /* create detailed mesh description for each navigation polygon */ - npolys = dtrisToPolysMap[ndtris - 1]; - dmeshes = MEM_callocN(sizeof(unsigned short) * npolys * 4, "buildNavMeshData dmeshes"); - memset(dmeshes, 0, npolys * 4 * sizeof(unsigned short)); - dmesh = NULL; - prevpolyidx = 0; - for (i = 0; i < ndtris; i++) { - int curpolyidx = dtrisToPolysMap[i]; - if (curpolyidx != prevpolyidx) { - if (curpolyidx != prevpolyidx + 1) { - printf("Converting navmesh: Error! Wrong order of detailed mesh faces\n"); - goto fail; - } - dmesh = dmesh == NULL ? dmeshes : dmesh + 4; - dmesh[2] = (unsigned short)i; /* tbase */ - dmesh[3] = 0; /* tnum */ - prevpolyidx = curpolyidx; - } - dmesh[3]++; - } - - /* create navigation polygons */ - vertsPerPoly = 6; - polys = MEM_callocN(sizeof(unsigned short) * npolys * vertsPerPoly * 2, "buildNavMeshData polys"); - memset(polys, 0xff, sizeof(unsigned short) * vertsPerPoly * 2 * npolys); - - if (!buildPolygonsByDetailedMeshes(vertsPerPoly, npolys, polys, dmeshes, verts, dtris, dtrisToPolysMap)) { - printf("Converting navmesh: Error! Unable to build polygons from detailed mesh\n"); - goto fail; - } - - *ndtris_r = ndtris; - *npolys_r = npolys; - *vertsPerPoly_r = vertsPerPoly; - *dtris_r = dtris; - *dmeshes_r = dmeshes; - *polys_r = polys; - *dtrisToPolysMap_r = dtrisToPolysMap; - *dtrisToTrisMap_r = dtrisToTrisMap; - - return 1; - -fail: - MEM_freeN(dmeshes); - MEM_freeN(dtrisToPolysMap); - MEM_freeN(dtrisToTrisMap); - return 0; -} - - -int buildNavMeshDataByDerivedMesh(DerivedMesh *dm, int *vertsPerPoly, - int *nverts, float **verts, - int *ndtris, unsigned short **dtris, - int *npolys, unsigned short **dmeshes, - unsigned short **polys, int **dtrisToPolysMap, - int **dtrisToTrisMap, int **trisToFacesMap) -{ - int res; - int ntris = 0, *recastData = NULL; - unsigned short *tris = NULL; - - res = buildRawVertIndicesData(dm, nverts, verts, &ntris, &tris, trisToFacesMap, &recastData); - if (!res) { - printf("Converting navmesh: Error! Can't get raw vertices and indices from mesh\n"); - goto exit; - } - - res = buildNavMeshData(*nverts, *verts, ntris, tris, recastData, *trisToFacesMap, - ndtris, dtris, npolys, dmeshes, polys, vertsPerPoly, - dtrisToPolysMap, dtrisToTrisMap); - if (!res) { - printf("Converting navmesh: Error! Can't build navmesh data from mesh\n"); - goto exit; - } - -exit: - if (tris) - MEM_freeN(tris); - - return res; -} - -int polyFindVertex(const unsigned short *p, const int vertsPerPoly, unsigned short vertexIdx) -{ - int i, res = -1; - for (i = 0; i < vertsPerPoly; i++) { - if (p[i] == 0xffff) - break; - if (p[i] == vertexIdx) { - res = i; - break; - } - } - return res; -} diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index e239037df70..777c2a580fd 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 5d4b1ae8170..3b51ce9366f 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -75,6 +75,8 @@ #include "NOD_shader.h" #include "NOD_texture.h" +#include "DEG_depsgraph.h" + #define NODE_DEFAULT_MAX_WIDTH 700 /* Fallback types for undefined tree, nodes, sockets */ @@ -1987,9 +1989,6 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree) if (ntree) { bNodeTree *ltree; bNode *node; - AnimData *adt; - - bAction *action_backup = NULL, *tmpact_backup = NULL; BLI_spin_lock(&spin); if (!ntree->duplilock) { @@ -1999,23 +1998,16 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree) BLI_mutex_lock(ntree->duplilock); - /* Workaround for copying an action on each render! - * set action to NULL so animdata actions don't get copied */ - adt = BKE_animdata_from_id(&ntree->id); - - if (adt) { - action_backup = adt->action; - tmpact_backup = adt->tmpact; - - adt->action = NULL; - adt->tmpact = NULL; - } - /* Make full copy outside of Main database. * Note: previews are not copied here. */ - BKE_id_copy_ex(G.main, (ID *)ntree, (ID **)<ree, - LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT | LIB_ID_COPY_NO_PREVIEW, false); + BKE_id_copy_ex( + NULL, &ntree->id, (ID **)<ree, + (LIB_ID_CREATE_NO_MAIN | + LIB_ID_CREATE_NO_USER_REFCOUNT | + LIB_ID_COPY_NO_PREVIEW | + LIB_ID_COPY_NO_ANIMDATA), + false); ltree->flag |= NTREE_IS_LOCALIZED; for (node = ltree->nodes.first; node; node = node->next) { @@ -2024,31 +2016,19 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree) } } - if (adt) { - AnimData *ladt = BKE_animdata_from_id(<ree->id); - - adt->action = ladt->action = action_backup; - adt->tmpact = ladt->tmpact = tmpact_backup; - - if (action_backup) - id_us_plus(&action_backup->id); - if (tmpact_backup) - id_us_plus(&tmpact_backup->id); - - } - /* end animdata uglyness */ - /* ensures only a single output node is enabled */ ntreeSetOutput(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) ntree->typeinfo->localize(ltree, ntree); + ltree->id.tag |= LIB_TAG_LOCALIZED; + BLI_mutex_unlock(ntree->duplilock); return ltree; @@ -3118,77 +3098,6 @@ void nodeUpdateInternalLinks(bNodeTree *ntree, bNode *node) } -/* nodes that use ID data get synced with local data */ -void nodeSynchronizeID(bNode *node, bool copy_to_id) -{ - if (node->id == NULL) return; - - if (ELEM(node->type, SH_NODE_MATERIAL, SH_NODE_MATERIAL_EXT)) { - bNodeSocket *sock; - Material *ma = (Material *)node->id; - int a; - short check_flags = SOCK_UNAVAIL; - - if (!copy_to_id) - check_flags |= SOCK_HIDDEN; - - /* hrmf, case in loop isn't super fast, but we don't edit 100s of material at same time either! */ - for (a = 0, sock = node->inputs.first; sock; sock = sock->next, a++) { - if (!(sock->flag & check_flags)) { - if (copy_to_id) { - switch (a) { - case MAT_IN_COLOR: - copy_v3_v3(&ma->r, ((bNodeSocketValueRGBA *)sock->default_value)->value); break; - case MAT_IN_SPEC: - copy_v3_v3(&ma->specr, ((bNodeSocketValueRGBA *)sock->default_value)->value); break; - case MAT_IN_REFL: - ma->ref = ((bNodeSocketValueFloat *)sock->default_value)->value; break; - case MAT_IN_MIR: - copy_v3_v3(&ma->mirr, ((bNodeSocketValueRGBA *)sock->default_value)->value); break; - case MAT_IN_AMB: - ma->amb = ((bNodeSocketValueFloat *)sock->default_value)->value; break; - case MAT_IN_EMIT: - ma->emit = ((bNodeSocketValueFloat *)sock->default_value)->value; break; - case MAT_IN_SPECTRA: - ma->spectra = ((bNodeSocketValueFloat *)sock->default_value)->value; break; - case MAT_IN_RAY_MIRROR: - ma->ray_mirror = ((bNodeSocketValueFloat *)sock->default_value)->value; break; - case MAT_IN_ALPHA: - ma->alpha = ((bNodeSocketValueFloat *)sock->default_value)->value; break; - case MAT_IN_TRANSLUCENCY: - ma->translucency = ((bNodeSocketValueFloat *)sock->default_value)->value; break; - } - } - else { - switch (a) { - case MAT_IN_COLOR: - copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->r); break; - case MAT_IN_SPEC: - copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->specr); break; - case MAT_IN_REFL: - ((bNodeSocketValueFloat *)sock->default_value)->value = ma->ref; break; - case MAT_IN_MIR: - copy_v3_v3(((bNodeSocketValueRGBA *)sock->default_value)->value, &ma->mirr); break; - case MAT_IN_AMB: - ((bNodeSocketValueFloat *)sock->default_value)->value = ma->amb; break; - case MAT_IN_EMIT: - ((bNodeSocketValueFloat *)sock->default_value)->value = ma->emit; break; - case MAT_IN_SPECTRA: - ((bNodeSocketValueFloat *)sock->default_value)->value = ma->spectra; break; - case MAT_IN_RAY_MIRROR: - ((bNodeSocketValueFloat *)sock->default_value)->value = ma->ray_mirror; break; - case MAT_IN_ALPHA: - ((bNodeSocketValueFloat *)sock->default_value)->value = ma->alpha; break; - case MAT_IN_TRANSLUCENCY: - ((bNodeSocketValueFloat *)sock->default_value)->value = ma->translucency; break; - } - } - } - } - } -} - - /* ************* node type access ********** */ void nodeLabel(bNodeTree *ntree, bNode *node, char *label, int maxlen) @@ -3553,10 +3462,7 @@ static void registerShaderNodes(void) { register_node_type_sh_group(); - register_node_type_sh_output(); - register_node_type_sh_material(); register_node_type_sh_camera(); - register_node_type_sh_lamp(); register_node_type_sh_gamma(); register_node_type_sh_brightcontrast(); register_node_type_sh_value(); @@ -3567,9 +3473,7 @@ static void registerShaderNodes(void) register_node_type_sh_mix_rgb(); register_node_type_sh_valtorgb(); register_node_type_sh_rgbtobw(); - register_node_type_sh_texture(); register_node_type_sh_normal(); - register_node_type_sh_geom(); register_node_type_sh_mapping(); register_node_type_sh_curve_vec(); register_node_type_sh_curve_rgb(); @@ -3577,7 +3481,6 @@ static void registerShaderNodes(void) register_node_type_sh_vect_math(); register_node_type_sh_vect_transform(); register_node_type_sh_squeeze(); - register_node_type_sh_material_ext(); register_node_type_sh_invert(); register_node_type_sh_seprgb(); register_node_type_sh_combrgb(); @@ -3622,6 +3525,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(); @@ -3814,3 +3718,62 @@ 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(struct Depsgraph *depsgraph, + bNodeTree *ntree_dst, + const bNodeTree *ntree_src) +{ + DEG_debug_print_eval(depsgraph, __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 22a4db94d07..1798515658d 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -58,7 +58,7 @@ #include "DNA_view3d_types.h" #include "DNA_world_types.h" #include "DNA_object_types.h" -#include "DNA_property_types.h" +#include "DNA_lightprobe_types.h" #include "DNA_rigidbody_types.h" #include "BLI_blenlib.h" @@ -76,9 +76,7 @@ #include "BKE_idprop.h" #include "BKE_armature.h" #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 +89,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,12 +102,12 @@ #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_property.h" +#include "BKE_lightprobe.h" #include "BKE_rigidbody.h" -#include "BKE_sca.h" #include "BKE_scene.h" #include "BKE_sequencer.h" #include "BKE_speaker.h" @@ -118,6 +117,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,8 +132,6 @@ #include "CCGSubSurf.h" #include "atomic_ops.h" -#include "GPU_material.h" - /* Vertex parent modifies original BMesh which is not safe for threading. * Ideally such a modification should be handled as a separate DAG update * callback for mesh datablock, but for until it is actually supported use @@ -152,16 +153,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; @@ -179,14 +170,6 @@ void BKE_object_free_softbody(Object *ob) } } -void BKE_object_free_bulletsoftbody(Object *ob) -{ - if (ob->bsoft) { - bsbFree(ob->bsoft); - ob->bsoft = NULL; - } -} - void BKE_object_free_curve_cache(Object *ob) { if (ob->curve_cache) { @@ -356,7 +339,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 +395,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); } } @@ -419,6 +413,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; @@ -427,11 +422,6 @@ void BKE_object_free(Object *ob) animviz_free_motionpath(ob->mpath); ob->mpath = NULL; } - BKE_bproperty_free_list(&ob->prop); - - free_sensors(&ob->sensors); - free_controllers(&ob->controllers); - free_actuators(&ob->actuators); BKE_constraints_free_ex(&ob->constraints, false); @@ -443,11 +433,13 @@ void BKE_object_free(Object *ob) sbFree(ob->soft); ob->soft = NULL; } - if (ob->bsoft) { - bsbFree(ob->bsoft); - ob->bsoft = NULL; + + for (ObjectEngineData *oed = ob->drawdata.first; oed; oed = oed->next) { + if (oed->free != NULL) { + oed->free(oed); + } } - GPU_lamp_free(ob); + BLI_freelistN(&ob->drawdata); BKE_sculptsession_free(ob); @@ -465,6 +457,9 @@ 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 */ @@ -511,6 +506,15 @@ bool BKE_object_is_in_editmode(const Object *ob) return false; } +bool BKE_object_is_in_editmode_and_selected(const Object *ob) +{ + if ((ob->base_flag & BASE_SELECTED) && (BKE_object_is_in_editmode(ob))) { + return true; + } + return false; +} + + bool BKE_object_is_in_editmode_vgroup(const Object *ob) { return (OB_TYPE_SUPPORT_VGROUP(ob->type) && @@ -529,6 +533,66 @@ bool BKE_object_is_in_wpaint_select_vert(const Object *ob) return false; } +bool BKE_object_has_mode_data(const struct Object *ob, eObjectMode object_mode) +{ + if (object_mode & OB_MODE_EDIT) { + if (BKE_object_is_in_editmode(ob)) { + return true; + } + } + else if (object_mode & OB_MODE_VERTEX_PAINT) { + if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_VERTEX_PAINT)) { + return true; + } + } + else if (object_mode & OB_MODE_WEIGHT_PAINT) { + if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_WEIGHT_PAINT)) { + return true; + } + } + else if (object_mode & OB_MODE_SCULPT) { + if (ob->sculpt && (ob->sculpt->mode_type == OB_MODE_SCULPT)) { + return true; + } + } + else if (object_mode & OB_MODE_POSE) { + if (ob->pose != NULL) { + return true; + } + } + 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(const Object *obtest) { Object *ob; @@ -582,6 +646,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); @@ -633,26 +698,10 @@ void BKE_object_init(Object *ob) ob->dupsta = 1; ob->dupend = 100; ob->dupfacesca = 1.0; - /* Game engine defaults*/ - ob->mass = ob->inertia = 1.0f; - ob->formfactor = 0.4f; - ob->damping = 0.04f; - ob->rdamping = 0.1f; - ob->anisotropicFriction[0] = 1.0f; - ob->anisotropicFriction[1] = 1.0f; - ob->anisotropicFriction[2] = 1.0f; - ob->gameflag = OB_PROP | OB_COLLISION; - ob->margin = 0.04f; - ob->init_state = 1; - ob->state = 1; - ob->obstacleRad = 1.0f; - ob->step_height = 0.15f; - ob->jump_speed = 10.0f; - ob->fall_speed = 55.0f; - ob->max_jumps = 1; 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; @@ -673,6 +722,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; @@ -681,163 +733,66 @@ 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 */ -/* creates minimum required data, but without vertices etc. */ -Object *BKE_object_add( - Main *bmain, Scene *scene, - int type, const char *name) + +static Object *object_add_common(Main *bmain, ViewLayer *view_layer, int type, const char *name) { Object *ob; - Base *base; 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); - 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); - + DEG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME); return ob; } - -#ifdef WITH_GAMEENGINE - -void BKE_object_lod_add(Object *ob) -{ - LodLevel *lod = MEM_callocN(sizeof(LodLevel), "LoD Level"); - LodLevel *last = ob->lodlevels.last; - - /* If the lod list is empty, initialize it with the base lod level */ - if (!last) { - LodLevel *base = MEM_callocN(sizeof(LodLevel), "Base LoD Level"); - BLI_addtail(&ob->lodlevels, base); - base->flags = OB_LOD_USE_MESH | OB_LOD_USE_MAT; - base->source = ob; - base->obhysteresis = 10; - last = ob->currentlod = base; - } - - lod->distance = last->distance + 25.0f; - lod->obhysteresis = 10; - lod->flags = OB_LOD_USE_MESH | OB_LOD_USE_MAT; - - BLI_addtail(&ob->lodlevels, lod); -} - -static int lod_cmp(const void *a, const void *b) -{ - const LodLevel *loda = a; - const LodLevel *lodb = b; - - if (loda->distance < lodb->distance) return -1; - return loda->distance > lodb->distance; -} - -void BKE_object_lod_sort(Object *ob) -{ - BLI_listbase_sort(&ob->lodlevels, lod_cmp); -} - -bool BKE_object_lod_remove(Object *ob, int level) -{ - LodLevel *rem; - - if (level < 1 || level > BLI_listbase_count(&ob->lodlevels) - 1) - return false; - - rem = BLI_findlink(&ob->lodlevels, level); - - if (rem == ob->currentlod) { - ob->currentlod = rem->prev; - } - - BLI_remlink(&ob->lodlevels, rem); - MEM_freeN(rem); - - /* If there are no user defined lods, remove the base lod as well */ - if (BLI_listbase_is_single(&ob->lodlevels)) { - LodLevel *base = ob->lodlevels.first; - BLI_remlink(&ob->lodlevels, base); - MEM_freeN(base); - ob->currentlod = NULL; - } - - return true; -} - -static LodLevel *lod_level_select(Object *ob, const float camera_position[3]) +/** + * 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, ViewLayer *view_layer, + int type, const char *name) { - LodLevel *current = ob->currentlod; - float dist_sq; - - if (!current) return NULL; - - dist_sq = len_squared_v3v3(ob->obmat[3], camera_position); - - if (dist_sq < SQUARE(current->distance)) { - /* check for higher LoD */ - while (current->prev && dist_sq < SQUARE(current->distance)) { - current = current->prev; - } - } - else { - /* check for lower LoD */ - while (current->next && dist_sq > SQUARE(current->next->distance)) { - current = current->next; - } - } + Object *ob; + Base *base; + LayerCollection *layer_collection; - return current; -} + ob = object_add_common(bmain, view_layer, type, name); -bool BKE_object_lod_is_usable(Object *ob, Scene *scene) -{ - bool active = (scene) ? ob == OBACT : false; - return (ob->mode == OB_MODE_OBJECT || !active); -} + layer_collection = BKE_layer_collection_get_active_ensure(scene, view_layer); + BKE_collection_object_add(&scene->id, layer_collection->scene_collection, ob); -void BKE_object_lod_update(Object *ob, const float camera_position[3]) -{ - LodLevel *cur_level = ob->currentlod; - LodLevel *new_level = lod_level_select(ob, camera_position); + base = BKE_view_layer_base_find(view_layer, ob); + BKE_view_layer_base_select(view_layer, base); - if (new_level != cur_level) { - ob->currentlod = new_level; - } + return ob; } -static Object *lod_ob_get(Object *ob, Scene *scene, int flag) +/** + * 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) { - LodLevel *current = ob->currentlod; - - if (!current || !BKE_object_lod_is_usable(ob, scene)) - return ob; - - while (current->prev && (!(current->flags & flag) || !current->source || current->source->type != OB_MESH)) { - current = current->prev; - } + Object *ob; + Base *base; - return current->source; -} + ob = object_add_common(bmain, view_layer, type, name); + BKE_collection_object_add_from(scene, ob_src, ob); -struct Object *BKE_object_lod_meshob_get(Object *ob, Scene *scene) -{ - return lod_ob_get(ob, scene, OB_LOD_USE_MESH); -} + base = BKE_view_layer_base_find(view_layer, ob); + BKE_view_layer_base_select(view_layer, base); -struct Object *BKE_object_lod_matob_get(Object *ob, Scene *scene) -{ - return lod_ob_get(ob, scene, OB_LOD_USE_MAT); + return ob; } -#endif /* WITH_GAMEENGINE */ - - SoftBody *copy_softbody(const SoftBody *sb, const int flag) { SoftBody *sbn; @@ -883,17 +838,6 @@ SoftBody *copy_softbody(const SoftBody *sb, const int flag) return sbn; } -BulletSoftBody *copy_bulletsoftbody(const BulletSoftBody *bsb, const int UNUSED(flag)) -{ - BulletSoftBody *bsbn; - - if (bsb == NULL) - return NULL; - bsbn = MEM_dupallocN(bsb); - /* no pointer in this structure yet */ - return bsbn; -} - ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys, const int flag) { ParticleSystem *psysn; @@ -944,10 +888,10 @@ 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); - psysn->renderdata = NULL; /* XXX Never copy caches here? */ psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, flag & ~LIB_ID_COPY_CACHES); @@ -1084,12 +1028,103 @@ Object *BKE_object_pose_armature_get(Object *ob) ob = modifiers_isDeformedByArmature(ob); + /* Only use selected check when non-active. */ if (BKE_object_pose_context_check(ob)) 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; +} + +/** + * Access pose array with special check to get pose object when in weight paint mode. + */ +Object **BKE_object_pose_array_get_ex(ViewLayer *view_layer, uint *r_objects_len, bool unique) +{ + Object *ob_active = OBACT(view_layer); + Object *ob_pose = BKE_object_pose_armature_get(ob_active); + Object **objects = NULL; + if (ob_pose == ob_active) { + objects = BKE_view_layer_array_from_objects_in_mode( + view_layer, r_objects_len, { + .object_mode = OB_MODE_POSE, + .no_dup_data = unique}); + } + else if (ob_pose != NULL) { + *r_objects_len = 1; + objects = MEM_mallocN(sizeof(*objects), __func__); + objects[0] = ob_pose; + } + else { + *r_objects_len = 0; + objects = MEM_mallocN(0, __func__); + } + return objects; +} +Object **BKE_object_pose_array_get_unique(ViewLayer *view_layer, uint *r_objects_len) +{ + return BKE_object_pose_array_get_ex(view_layer, r_objects_len, true); +} +Object **BKE_object_pose_array_get(ViewLayer *view_layer, uint *r_objects_len) +{ + return BKE_object_pose_array_get_ex(view_layer, r_objects_len, false); +} + +Base **BKE_object_pose_base_array_get_ex(ViewLayer *view_layer, uint *r_bases_len, bool unique) +{ + Base *base_active = BASACT(view_layer); + Object *ob_pose = base_active ? BKE_object_pose_armature_get(base_active->object) : NULL; + Base *base_pose = NULL; + Base **bases = NULL; + + if (base_active) { + if (ob_pose == base_active->object) { + base_pose = base_active; + } + else { + base_pose = BKE_view_layer_base_find(view_layer, ob_pose); + } + } + + if (base_active && (base_pose == base_active)) { + bases = BKE_view_layer_array_from_bases_in_mode( + view_layer, r_bases_len, { + .object_mode = OB_MODE_POSE, + .no_dup_data = unique}); + } + else if (base_pose != NULL) { + *r_bases_len = 1; + bases = MEM_mallocN(sizeof(*bases), __func__); + bases[0] = base_pose; + } + else { + *r_bases_len = 0; + bases = MEM_mallocN(0, __func__); + } + return bases; +} +Base **BKE_object_pose_base_array_get_unique(ViewLayer *view_layer, uint *r_bases_len) +{ + return BKE_object_pose_base_array_get_ex(view_layer, r_bases_len, true); +} +Base **BKE_object_pose_base_array_get(ViewLayer *view_layer, uint *r_bases_len) +{ + return BKE_object_pose_base_array_get_ex(view_layer, r_bases_len, false); +} + void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src) { copy_v3_v3(ob_tar->loc, ob_src->loc); @@ -1136,11 +1171,6 @@ void BKE_object_copy_data(Main *UNUSED(bmain), Object *ob_dst, const Object *ob_ BLI_addtail(&ob_dst->modifiers, nmd); } - BLI_listbase_clear(&ob_dst->prop); - BKE_bproperty_copy_list(&ob_dst->prop, &ob_src->prop); - - BKE_sca_logic_copy(ob_dst, ob_src, flag_subdata); - if (ob_src->pose) { copy_object_pose(ob_dst, ob_src, flag_subdata); /* backwards compat... non-armatures can get poses in older files? */ @@ -1148,6 +1178,7 @@ 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; @@ -1160,7 +1191,6 @@ void BKE_object_copy_data(Main *UNUSED(bmain), Object *ob_dst, const Object *ob_ } } ob_dst->soft = copy_softbody(ob_src->soft, flag_subdata); - ob_dst->bsoft = copy_bulletsoftbody(ob_src->bsoft, flag_subdata); ob_dst->rigidbody_object = BKE_rigidbody_copy_object(ob_src, flag_subdata); ob_dst->rigidbody_constraint = BKE_rigidbody_copy_constraint(ob_src, flag_subdata); @@ -1170,6 +1200,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; @@ -1330,8 +1361,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 @@ -1674,13 +1705,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(depsgraph, scene, par, 0); } +#endif if (par->curve_cache->path == NULL) { return false; @@ -2061,8 +2095,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( + Depsgraph *depsgraph, Scene *scene, Object *ob, float ctime, + RigidBodyWorld *rbw, float r_originmat[3][3]) { if (ob == NULL) return; @@ -2097,7 +2132,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(depsgraph, &ob->constraints, cob, ctime); BKE_constraints_clear_evalob(cob); } @@ -2106,9 +2141,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(Depsgraph *depsgraph, 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(depsgraph, scene, ob, ctime, NULL, NULL); } /* get object transformation matrix without recalculating dependencies and @@ -2133,17 +2168,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(Depsgraph *depsgraph, 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(depsgraph, 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(Depsgraph *depsgraph, 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(depsgraph, 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(Depsgraph *depsgraph, Scene *scene, Object *ob, Object *workob) { BKE_object_workob_clear(workob); @@ -2165,7 +2200,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(depsgraph, scene, workob); } /* see BKE_pchan_apply_mat4() for the equivalent 'pchan' function */ @@ -2203,7 +2238,7 @@ void BKE_object_apply_mat4(Object *ob, float mat[4][4], const bool use_compat, c BoundBox *BKE_boundbox_alloc_unit(void) { BoundBox *bb; - const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {-1.0f, -1.0f, -1.0f}; + const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {1.0f, 1.0f, 1.0f}; bb = MEM_callocN(sizeof(BoundBox), "OB-BoundBox"); BKE_boundbox_init_from_minmax(bb, min, max); @@ -2421,7 +2456,7 @@ void BKE_object_empty_draw_type_set(Object *ob, const int value) } } -bool BKE_object_minmax_dupli(Scene *scene, Object *ob, float r_min[3], float r_max[3], const bool use_hidden) +bool BKE_object_minmax_dupli(Depsgraph *depsgraph, Scene *scene, Object *ob, float r_min[3], float r_max[3], const bool use_hidden) { bool ok = false; if ((ob->transflag & OB_DUPLI) == 0) { @@ -2430,7 +2465,7 @@ bool BKE_object_minmax_dupli(Scene *scene, Object *ob, float r_min[3], float r_m else { ListBase *lb; DupliObject *dob; - lb = object_duplilist(G.main->eval_ctx, scene, ob); + lb = object_duplilist(depsgraph, scene, ob); for (dob = lb->first; dob; dob = dob->next) { if ((use_hidden == false) && (dob->no_draw != 0)) { /* pass */ @@ -2490,14 +2525,14 @@ void BKE_object_foreach_display_point( } void BKE_scene_foreach_display_point( - Scene *scene, View3D *v3d, const short flag, + Depsgraph *depsgraph, 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) { @@ -2507,7 +2542,7 @@ void BKE_scene_foreach_display_point( ListBase *lb; DupliObject *dob; - lb = object_duplilist(G.main->eval_ctx, scene, ob); + lb = object_duplilist(depsgraph, scene, ob); for (dob = lb->first; dob; dob = dob->next) { if (dob->no_draw == 0) { BKE_object_foreach_display_point(dob->ob, dob->mat, func_cb, user_data); @@ -2530,7 +2565,7 @@ typedef struct ObTfmBack { float obmat[4][4]; /* final worldspace matrix with constraints & animsys applied */ float parentinv[4][4]; /* inverse result of parent, so that object doesn't 'stick' to parent */ float constinv[4][4]; /* inverse result of constraints. doesn't include effect of parent or object local transform */ - float imat[4][4]; /* inverse matrix of 'obmat' for during render, old game engine, temporally: ipokeys of transform */ + float imat[4][4]; /* inverse matrix of 'obmat' for during render, temporally: ipokeys of transform */ } ObTfmBack; void *BKE_object_tfm_backup(Object *ob) @@ -2587,7 +2622,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(Depsgraph *depsgraph, Scene *scene, Object *object, const bool do_proxy_update) @@ -2604,7 +2639,7 @@ static void object_handle_update_proxy(EvaluationContext *eval_ctx, if (object->proxy_group == NULL) { if (do_proxy_update) { // printf("call update, lib ob %s proxy %s\n", ob->proxy->id.name, ob->id.name); - BKE_object_handle_update(eval_ctx, scene, object->proxy); + BKE_object_handle_update(depsgraph, scene, object->proxy); } } } @@ -2617,13 +2652,18 @@ 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(Depsgraph *depsgraph, Scene *scene, Object *ob, RigidBodyWorld *rbw, const bool do_proxy_update) { - if ((ob->recalc & OB_RECALC_ALL) == 0) { - object_handle_update_proxy(eval_ctx, scene, ob, do_proxy_update); + 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(depsgraph, scene, ob, do_proxy_update); return; } /* Speed optimization for animation lookups. */ @@ -2633,7 +2673,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 @@ -2646,23 +2686,23 @@ 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_EVAL) { 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); + if (!BKE_object_eval_proxy_copy(depsgraph, ob)) { + BKE_object_where_is_calc_ex(depsgraph, scene, rbw, ob, NULL); } } - if (ob->recalc & OB_RECALC_DATA) { - BKE_object_handle_data_update(eval_ctx, scene, ob); + if (recalc_data) { + BKE_object_handle_data_update(depsgraph, scene, ob); } - ob->recalc &= ~OB_RECALC_ALL; + ob->id.recalc &= ID_RECALC_ALL; - object_handle_update_proxy(eval_ctx, scene, ob, do_proxy_update); + object_handle_update_proxy(depsgraph, scene, ob, do_proxy_update); } /* WARNING: "scene" here may not be the scene object actually resides in. @@ -2670,9 +2710,9 @@ 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(Depsgraph *depsgraph, Scene *scene, Object *ob) { - BKE_object_handle_update_ex(eval_ctx, scene, ob, NULL, true); + BKE_object_handle_update_ex(depsgraph, scene, ob, NULL, true); } void BKE_object_sculpt_modifiers_changed(Object *ob) @@ -2717,14 +2757,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: @@ -3291,33 +3324,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; @@ -3346,8 +3379,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)) { @@ -3391,18 +3424,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); } } @@ -3603,9 +3629,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( + Depsgraph *depsgraph, Scene *scene, Object *ob, bool update_mesh, + int parent_recursion, float frame, int type) { ModifierData *md = modifiers_findByType(ob, (ModifierType)type); bConstraint *con; @@ -3628,8 +3654,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(depsgraph, scene, ob->parent, 0, recursion, frame, type); + if (ob->track) no_update |= BKE_object_modifier_update_subframe(depsgraph, scene, ob->track, 0, recursion, frame, type); /* skip subframe if object is parented * to vertex of a dynamic paint canvas */ @@ -3646,7 +3672,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(depsgraph, scene, ct->tar, 0, recursion, frame, type); } /* free temp targets */ if (cti->flush_constraint_targets) @@ -3656,17 +3682,18 @@ 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 * to not mess up cache validity */ object_cacheIgnoreClear(ob, 1); - BKE_object_handle_update(G.main->eval_ctx, scene, ob); + BKE_object_handle_update(depsgraph, scene, ob); object_cacheIgnoreClear(ob, 0); } else - BKE_object_where_is_calc_time(scene, ob, frame); + BKE_object_where_is_calc_time(depsgraph, scene, ob, frame); /* for curve following objects, parented curve has to be updated too */ if (ob->type == OB_CURVE) { @@ -3677,7 +3704,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(depsgraph, scene, ob); } return false; diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c index 61533e13d7a..fb2e824b299 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..eafd2d95cf1 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,8 @@ #include "BKE_editmesh.h" #include "BKE_anim.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "BLI_strict_flags.h" #include "BLI_hash.h" @@ -69,15 +71,16 @@ /* Dupli-Geometry */ typedef struct DupliContext { - EvaluationContext *eval_ctx; + Depsgraph *depsgraph; bool do_update; bool animated; Group *group; /* XXX child objects are selected from this group if set, could be nicer */ + Object *obedit; /* Only to check if the object is in edit-mode. */ Scene *scene; + ViewLayer *view_layer; Object *object; float space_mat[4][4]; - unsigned int lay; int persistent_id[MAX_DUPLI_RECUR]; int level; @@ -96,21 +99,22 @@ 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, Depsgraph *depsgraph, Scene *scene, Object *ob, float space_mat[4][4], bool update) { - r_ctx->eval_ctx = eval_ctx; + r_ctx->depsgraph = depsgraph; r_ctx->scene = scene; + r_ctx->view_layer = DEG_get_evaluated_view_layer(depsgraph); /* 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->do_update = update && !(G.is_rendering && DEG_get_mode(depsgraph) != DAG_EVAL_RENDER); r_ctx->animated = false; r_ctx->group = NULL; r_ctx->object = ob; + r_ctx->obedit = OBEDIT_FROM_OBACT(ob); if (space_mat) 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 +147,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 +203,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; } @@ -235,35 +244,32 @@ static bool is_child(const Object *ob, const Object *parent) static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChildDuplisFunc make_child_duplis_cb) { Object *parent = ctx->object; - 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_BEGIN(ctx->group, base) + { + Object *ob = base->object; + if ((base->flag & BASE_VISIBLED) && ob != ctx->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 != ctx->obedit) && is_child(ob, parent)) { DupliContext pctx; copy_dupli_context(&pctx, ctx, ctx->object, NULL, baseid, false); @@ -283,13 +289,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; @@ -306,39 +311,23 @@ static void make_duplis_group(const DupliContext *ctx) if (ctx->do_update) { /* note: update is optional because we don't always need object * transformations to be correct. Also fixes bug [#29616]. */ - BKE_group_handle_recalc_and_update(ctx->eval_ctx, ctx->scene, ob, group); + BKE_group_handle_recalc_and_update(ctx->depsgraph, ctx->scene, ob, group); } 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 +366,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 +384,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->depsgraph, 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 +398,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->depsgraph, 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 +471,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]); @@ -535,7 +520,7 @@ static void make_duplis_verts(const DupliContext *ctx) { Scene *scene = ctx->scene; Object *parent = ctx->object; - bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); + bool use_texcoords = ELEM(DEG_get_mode(ctx->depsgraph), DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); VertexDupliData vdd; vdd.ctx = ctx; @@ -547,14 +532,14 @@ static void make_duplis_verts(const DupliContext *ctx) BMEditMesh *em = BKE_editmesh_from_object(parent); 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); + if (DEG_get_mode(ctx->depsgraph) == DAG_EVAL_RENDER) { + vdd.dm = mesh_create_derived_render(ctx->depsgraph, 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->depsgraph, scene, parent, em, dm_mask); } else { - vdd.dm = mesh_get_derived_final(scene, parent, dm_mask); + vdd.dm = mesh_get_derived_final(ctx->depsgraph, scene, parent, dm_mask); } vdd.edit_btmesh = me->edit_btmesh; @@ -671,7 +656,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); } } @@ -739,7 +724,7 @@ static void make_child_duplis_faces(const DupliContext *ctx, void *userdata, Obj float (*orco)[3] = fdd->orco; MLoopUV *mloopuv = fdd->mloopuv; int a, totface = fdd->totface; - bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); + bool use_texcoords = ELEM(DEG_get_mode(ctx->depsgraph), DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); float child_imat[4][4]; DupliObject *dob; @@ -777,7 +762,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; @@ -805,7 +790,7 @@ static void make_duplis_faces(const DupliContext *ctx) { Scene *scene = ctx->scene; Object *parent = ctx->object; - bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); + bool use_texcoords = ELEM(DEG_get_mode(ctx->depsgraph), DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); FaceDupliData fdd; fdd.use_scale = ((parent->transflag & OB_DUPLIFACES_SCALE) != 0); @@ -815,14 +800,14 @@ static void make_duplis_faces(const DupliContext *ctx) BMEditMesh *em = BKE_editmesh_from_object(parent); 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); + if (DEG_get_mode(ctx->depsgraph) == DAG_EVAL_RENDER) { + fdd.dm = mesh_create_derived_render(ctx->depsgraph, 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->depsgraph, scene, parent, em, dm_mask); } else { - fdd.dm = mesh_get_derived_final(scene, parent, dm_mask); + fdd.dm = mesh_get_derived_final(ctx->depsgraph, scene, parent, dm_mask); } if (use_texcoords) { @@ -857,10 +842,9 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem { Scene *scene = ctx->scene; Object *par = ctx->object; - bool for_render = ctx->eval_ctx->mode == DAG_EVAL_RENDER; - bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); + bool for_render = DEG_get_mode(ctx->depsgraph) == DAG_EVAL_RENDER; + bool use_texcoords = ELEM(DEG_get_mode(ctx->depsgraph), DAG_EVAL_RENDER, DAG_EVAL_PREVIEW); - GroupObject *go; Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL; DupliObject *dob; ParticleDupliWeight *dw; @@ -874,7 +858,6 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem float (*obmat)[4]; int a, b, hair = 0; int totpart, totchild, totgroup = 0 /*, pa_num */; - const bool dupli_type_hack = !BKE_scene_use_new_shading_nodes(scene); int no_draw_flag = PARS_UNEXIST; @@ -885,7 +868,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem if (part == NULL) return; - if (!psys_check_enabled(par, psys, (ctx->eval_ctx->mode == DAG_EVAL_RENDER))) + if (!psys_check_enabled(par, psys, (DEG_get_mode(ctx->depsgraph) == DAG_EVAL_RENDER))) return; if (!for_render) @@ -898,8 +881,9 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem BLI_srandom((unsigned int)(31415926 + psys->seed)); - if ((psys->renderdata || part->draw_as == PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) { + if ((for_render || part->draw_as == PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) { ParticleSimulationData sim = {NULL}; + sim.depsgraph = ctx->depsgraph; sim.scene = scene; sim.ob = par; sim.psys = psys; @@ -913,10 +897,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; } } @@ -940,7 +924,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem /* gather list of objects or single object */ if (part->ren_as == PART_DRAW_GR) { if (ctx->do_update) { - BKE_group_handle_recalc_and_update(ctx->eval_ctx, scene, par, part->dup_group); + BKE_group_handle_recalc_and_update(ctx->depsgraph, scene, par, part->dup_group); } if (part->draw & PART_DRAW_COUNT_GR) { @@ -948,8 +932,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_BEGIN(part->dup_group, object) + { + (void) object; totgroup++; + } + FOREACH_GROUP_OBJECT_END; } /* we also copy the actual objects to restore afterwards, since @@ -968,11 +956,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_BEGIN(part->dup_group, object) + { + oblist[a] = object; + obcopylist[a] = *object; + a++; + + if (a >= totgroup) { + continue; + } } + FOREACH_GROUP_OBJECT_END; } } else { @@ -1061,27 +1056,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_BEGIN(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->depsgraph, scene, ob, ctime - pa_time); copy_v3_v3(vec, obmat[3]); obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f; @@ -1122,14 +1127,10 @@ 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); - /* XXX blender internal needs this to be set to dupligroup to render - * groups correctly, but we don't want this hack for cycles */ - if (dupli_type_hack && ctx->group) - dob->type = OB_DUPLIGROUP; } } @@ -1185,7 +1186,7 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx) return NULL; /* Should the dupli's be generated for this object? - Respect restrict flags */ - if (ctx->eval_ctx->mode == DAG_EVAL_RENDER ? (restrictflag & OB_RESTRICT_RENDER) : (restrictflag & OB_RESTRICT_VIEW)) + if (DEG_get_mode(ctx->depsgraph) == DAG_EVAL_RENDER ? (restrictflag & OB_RESTRICT_RENDER) : (restrictflag & OB_RESTRICT_VIEW)) return NULL; if (transflag & OB_DUPLIPARTS) { @@ -1217,11 +1218,11 @@ 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(Depsgraph *depsgraph, Scene *scene, Object *ob, bool update) { ListBase *duplilist = MEM_callocN(sizeof(ListBase), "duplilist"); DupliContext ctx; - init_context(&ctx, eval_ctx, scene, ob, NULL, update); + init_context(&ctx, depsgraph, scene, ob, NULL, update); if (ctx.gen) { ctx.duplilist = duplilist; ctx.gen->make_duplis(&ctx); @@ -1232,13 +1233,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(Depsgraph *depsgraph, Scene *sce, Object *ob) { - return object_duplilist_ex(eval_ctx, sce, ob, true); + return object_duplilist_ex(depsgraph, 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 +1282,7 @@ int count_duplilist(Object *ob) return 1; } -DupliApplyData *duplilist_apply(Object *ob, Scene *scene, ListBase *duplilist) +DupliApplyData *duplilist_apply(Depsgraph *depsgraph, Object *ob, Scene *scene, ListBase *duplilist) { DupliApplyData *apply_data = NULL; int num_objects = BLI_listbase_count(duplilist); @@ -1289,7 +1298,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(depsgraph, 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..ef254864d2e --- /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 e2e28d4b251..e3d42f3ad60 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,22 +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" +#include "DEG_depsgraph_query.h" -static ThreadMutex material_lock = BLI_MUTEX_INITIALIZER; -void BKE_object_eval_local_transform(EvaluationContext *UNUSED(eval_ctx), - Object *ob) +void BKE_object_eval_local_transform(Depsgraph *depsgraph, Object *ob) { - DEG_debug_print_eval(__func__, ob->id.name, ob); + DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob); /* calculate local matrix */ BKE_object_to_mat4(ob, ob->obmat); @@ -74,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(Depsgraph *depsgraph, Scene *scene, Object *ob) { @@ -84,7 +88,7 @@ void BKE_object_eval_parent(EvaluationContext *UNUSED(eval_ctx), float tmat[4][4]; float locmat[4][4]; - DEG_debug_print_eval(__func__, ob->id.name, ob); + DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob); /* get local matrix (but don't calculate it, as that was done already!) */ // XXX: redundant? @@ -106,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(Depsgraph *depsgraph, Scene *scene, Object *ob) { bConstraintOb *cob; float ctime = BKE_scene_frame_get(scene); - DEG_debug_print_eval(__func__, ob->id.name, ob); + DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob); /* evaluate constraints stack */ /* TODO: split this into: @@ -125,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(depsgraph, &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(Depsgraph *depsgraph, Object *ob) { - DEG_debug_print_eval(__func__, ob->id.name, ob); + DEG_debug_print_eval(depsgraph, __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( + Depsgraph *depsgraph, + Scene *scene, + Object *ob) { ID *data_id = (ID *)ob->data; AnimData *adt = BKE_animdata_from_id(data_id); @@ -168,19 +173,27 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx, switch (ob->type) { case OB_MESH: { - BMEditMesh *em = (ob == scene->obedit) ? BKE_editmesh_from_object(ob) : NULL; +#if 0 + BMEditMesh *em = (ob->mode & OB_MODE_EDIT) ? BKE_editmesh_from_object(ob) : NULL; +#else + BMEditMesh *em = (ob->mode & OB_MODE_EDIT) ? ((Mesh *)ob->data)->edit_btmesh : NULL; + if (em && em->ob != ob) { + em = NULL; + } +#endif + uint64_t data_mask = scene->customdata_mask | CD_MASK_BAREMESH; #ifdef WITH_FREESTYLE /* make sure Freestyle edge/face marks appear in DM for render (see T40315) */ - if (eval_ctx->mode != DAG_EVAL_VIEWPORT) { + if (DEG_get_mode(depsgraph) != DAG_EVAL_VIEWPORT) { data_mask |= CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE; } #endif if (em) { - makeDerivedMesh(scene, ob, em, data_mask, false); /* was CD_MASK_BAREMESH */ + makeDerivedMesh(depsgraph, scene, ob, em, data_mask, false); /* was CD_MASK_BAREMESH */ } else { - makeDerivedMesh(scene, ob, NULL, data_mask, false); + makeDerivedMesh(depsgraph, scene, ob, NULL, data_mask, false); } break; } @@ -192,22 +205,22 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx, } } else { - BKE_pose_where_is(scene, ob); + BKE_pose_where_is(depsgraph, scene, ob); } break; case OB_MBALL: - BKE_displist_make_mball(eval_ctx, scene, ob); + BKE_displist_make_mball(depsgraph, scene, ob); break; case OB_CURVE: case OB_SURF: case OB_FONT: - BKE_displist_make_curveTypes(scene, ob, 0); + BKE_displist_make_curveTypes(depsgraph, scene, ob, 0); break; case OB_LATTICE: - BKE_lattice_modifiers_calc(scene, ob); + BKE_lattice_modifiers_calc(depsgraph, scene, ob); break; case OB_EMPTY: @@ -217,30 +230,9 @@ 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) { + if (!(ob->mode & OB_MODE_EDIT) && ob->particlesystem.first) { + const bool use_render_params = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); ParticleSystem *tpsys, *psys; DerivedMesh *dm; ob->transflag &= ~OB_DUPLIPARTS; @@ -251,16 +243,16 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx, psys_changed_type(ob, psys); } - if (psys_check_enabled(ob, psys, eval_ctx->mode == DAG_EVAL_RENDER)) { + if (psys_check_enabled(ob, psys, use_render_params)) { /* check use of dupli objects here */ - if (psys->part && (psys->part->draw_as == PART_DRAW_REND || eval_ctx->mode == DAG_EVAL_RENDER) && + if (psys->part && (psys->part->draw_as == PART_DRAW_REND || use_render_params) && ((psys->part->ren_as == PART_DRAW_OB && psys->part->dup_ob) || (psys->part->ren_as == PART_DRAW_GR && psys->part->dup_group))) { ob->transflag |= OB_DUPLIPARTS; } - particle_system_update(scene, ob, psys, (eval_ctx->mode == DAG_EVAL_RENDER)); + particle_system_update(depsgraph, scene, ob, psys, use_render_params); psys = psys->next; } else if (psys->flag & PSYS_DELETE) { @@ -273,12 +265,12 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx, psys = psys->next; } - if (eval_ctx->mode == DAG_EVAL_RENDER && ob->transflag & OB_DUPLIPARTS) { + if (use_render_params && ob->transflag & OB_DUPLIPARTS) { /* this is to make sure we get render level duplis in groups: * 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(depsgraph, scene, ob, data_mask); dm->release(dm); for (psys = ob->particlesystem.first; psys; psys = psys->next) @@ -289,7 +281,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(Depsgraph *UNUSED(depsgraph), Object *object) { /* Handle proxy copy for target, */ @@ -313,46 +305,171 @@ 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(Depsgraph *depsgraph, 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; - } + BKE_object_eval_proxy_copy(depsgraph, object); } -void BKE_object_eval_uber_data(EvaluationContext *eval_ctx, +void BKE_object_eval_uber_data(Depsgraph *depsgraph, Scene *scene, Object *ob) { - DEG_debug_print_eval(__func__, ob->id.name, ob); + DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob); BLI_assert(ob->type != OB_ARMATURE); - BKE_object_handle_data_update(eval_ctx, scene, ob); + BKE_object_handle_data_update(depsgraph, scene, ob); + + 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; + } - ob->recalc &= ~(OB_RECALC_DATA | OB_RECALC_TIME); + 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(Depsgraph *depsgraph, Scene *scene, Object *object) { - DEG_debug_print_eval(__func__, object->id.name, object); + DEG_debug_print_eval(depsgraph, __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(Depsgraph *depsgraph, Scene *scene, Object *object) { /* This mimics full transform update chain from new depsgraph. */ - BKE_object_eval_local_transform(eval_ctx, object); + BKE_object_eval_local_transform(depsgraph, object); if (object->parent != NULL) { - BKE_object_eval_parent(eval_ctx, scene, object); + BKE_object_eval_parent(depsgraph, scene, object); } if (!BLI_listbase_is_empty(&object->constraints)) { - BKE_object_eval_constraints(eval_ctx, scene, object); + BKE_object_eval_constraints(depsgraph, scene, object); + } + BKE_object_eval_uber_transform(depsgraph, object); + BKE_object_eval_done(depsgraph, object); +} + +void BKE_object_eval_update_shading(Depsgraph *depsgraph, Object *object) +{ + DEG_debug_print_eval(depsgraph, __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(Depsgraph *depsgraph, ID *object_data) +{ + DEG_debug_print_eval(depsgraph, __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(Depsgraph *depsgraph, + Scene *scene, const int view_layer_index, + Object *object, int base_index, + const bool is_from_set) +{ + /* TODO(sergey): Avoid list lookup. */ + BLI_assert(view_layer_index >= 0); + ViewLayer *view_layer = BLI_findlink(&scene->view_layers, view_layer_index); + BLI_assert(view_layer != NULL); + BLI_assert(view_layer->object_bases_array != NULL); + BLI_assert(base_index >= 0); + BLI_assert(base_index < MEM_allocN_len(view_layer->object_bases_array) / sizeof(Base *)); + Base *base = view_layer->object_bases_array[base_index]; + BLI_assert(base->object == object); + + DEG_debug_print_eval(depsgraph, __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); } - BKE_object_eval_uber_transform(eval_ctx, object); - BKE_object_eval_done(eval_ctx, object); + 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 9db9b2ddf54..9bbde607b80 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 144ec029db1..4056a15fe47 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,9 +76,9 @@ 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) +void BKE_paint_invalidate_overlay_tex(Scene *scene, ViewLayer *view_layer, const Tex *tex) { - Paint *p = BKE_paint_get_active(scene); + Paint *p = BKE_paint_get_active(scene, view_layer); Brush *br = p->brush; if (!br) @@ -88,9 +90,9 @@ void BKE_paint_invalidate_overlay_tex(Scene *scene, const Tex *tex) overlay_flags |= PAINT_INVALID_OVERLAY_TEXTURE_SECONDARY; } -void BKE_paint_invalidate_cursor_overlay(Scene *scene, CurveMapping *curve) +void BKE_paint_invalidate_cursor_overlay(Scene *scene, ViewLayer *view_layer, CurveMapping *curve) { - Paint *p = BKE_paint_get_active(scene); + Paint *p = BKE_paint_get_active(scene, view_layer); Brush *br = p->brush; if (br && br->curve == curve) @@ -156,13 +158,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) { - 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 (view_layer->basact->object->mode) { case OB_MODE_SCULPT: return &ts->sculpt->paint; case OB_MODE_VERTEX_PAINT: @@ -175,6 +177,8 @@ Paint *BKE_paint_get_active(Scene *sce) if (ts->use_uv_sculpt) return &ts->uvsculpt->paint; return &ts->imapaint.paint; + default: + break; } } @@ -188,14 +192,15 @@ 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) { 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) { @@ -209,7 +214,7 @@ Paint *BKE_paint_get_active_from_context(const bContext *C) } } else { - return BKE_paint_get_active(sce); + return BKE_paint_get_active(sce, view_layer); } } @@ -219,14 +224,15 @@ 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) { 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) { @@ -714,7 +720,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); } } @@ -724,7 +730,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. */ @@ -855,9 +861,19 @@ 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( + Depsgraph *depsgraph, Scene *scene, Sculpt *sd, Object *ob, + bool need_pmap, bool need_mask) { + if (depsgraph == NULL) { + /* Happens on file load. + * + * We do nothing in this case, it will be taken care about on depsgraph + * evaluation. + */ + return; + } + DerivedMesh *dm; SculptSession *ss = ob->sculpt; Mesh *me = ob->data; @@ -895,7 +911,7 @@ 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(depsgraph, scene, ob, CD_MASK_BAREMESH); /* VWPaint require mesh info for loop lookup, so require sculpt mode here */ if (mmd && ob->mode & OB_MODE_SCULPT) { @@ -930,7 +946,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(depsgraph, scene, ob, &ss->deform_imats, &ss->deform_cos); BKE_pbvh_apply_vertCos(ss->pbvh, ss->deform_cos); for (a = 0; a < me->totvert; ++a) { @@ -966,6 +982,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 7602523b97c..ae6028c742a 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,10 @@ #include "BKE_scene.h" #include "BKE_deform.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_build.h" +#include "DEG_depsgraph_query.h" + #include "RE_render_ext.h" #include "particle_private.h" @@ -249,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->depsgraph, 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; @@ -285,10 +288,19 @@ 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(Depsgraph *depsgraph, 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); + ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); + const bool use_render_params = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); + + return (view_layer->basact && + (view_layer->basact->object->mode & OB_MODE_PARTICLE_EDIT) && + psys == psys_get_current((view_layer->basact)->object) && + (psys->edit || psys->pointcache->edit) && + !use_render_params); } + bool psys_check_enabled(Object *ob, ParticleSystem *psys, const bool use_render_params) { ParticleSystemModifierData *psmd; @@ -297,7 +309,7 @@ bool psys_check_enabled(Object *ob, ParticleSystem *psys, const bool use_render_ return 0; psmd = psys_get_modifier(ob, psys); - if (psys->renderdata || use_render_params) { + if (use_render_params) { if (!(psmd->modifier.mode & eModifierMode_Render)) return 0; } @@ -318,18 +330,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; @@ -343,21 +354,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_BEGIN(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) { @@ -608,206 +619,10 @@ void psys_free(Object *ob, ParticleSystem *psys) MEM_freeN(psys->pdd); } - MEM_freeN(psys); - } -} - -/************************************************/ -/* Rendering */ -/************************************************/ -/* these functions move away particle data and bring it back after - * rendering, to make different render settings possible without - * removing the previous data. this should be solved properly once */ - -void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[4][4], float winmat[4][4], int winx, int winy, int timeoffset) -{ - ParticleRenderData *data; - ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); - - if (psys->renderdata) - return; - - data = MEM_callocN(sizeof(ParticleRenderData), "ParticleRenderData"); - - data->child = psys->child; - data->totchild = psys->totchild; - data->pathcache = psys->pathcache; - data->pathcachebufs.first = psys->pathcachebufs.first; - data->pathcachebufs.last = psys->pathcachebufs.last; - data->totcached = psys->totcached; - data->childcache = psys->childcache; - data->childcachebufs.first = psys->childcachebufs.first; - data->childcachebufs.last = psys->childcachebufs.last; - data->totchildcache = psys->totchildcache; - - if (psmd->dm_final) { - data->dm = CDDM_copy_with_tessface(psmd->dm_final); - } - data->totdmvert = psmd->totdmvert; - data->totdmedge = psmd->totdmedge; - data->totdmface = psmd->totdmface; - - psys->child = NULL; - psys->pathcache = NULL; - psys->childcache = NULL; - psys->totchild = psys->totcached = psys->totchildcache = 0; - BLI_listbase_clear(&psys->pathcachebufs); - BLI_listbase_clear(&psys->childcachebufs); - - copy_m4_m4(data->winmat, winmat); - mul_m4_m4m4(data->viewmat, viewmat, ob->obmat); - mul_m4_m4m4(data->mat, winmat, data->viewmat); - data->winx = winx; - data->winy = winy; - - data->timeoffset = timeoffset; - - psys->renderdata = data; - - /* Hair can and has to be recalculated if everything isn't displayed. */ - if (psys->part->disp != 100 && ELEM(psys->part->type, PART_HAIR, PART_FLUID)) { - psys->recalc |= PSYS_RECALC_RESET; - } -} - -void psys_render_restore(Object *ob, ParticleSystem *psys) -{ - ParticleRenderData *data; - ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); - float render_disp = psys_get_current_display_percentage(psys); - float disp; - - data = psys->renderdata; - if (!data) - return; - - if (data->elems) - MEM_freeN(data->elems); - - if (psmd->dm_final) { - psmd->dm_final->needsFree = 1; - psmd->dm_final->release(psmd->dm_final); - } - if (psmd->dm_deformed) { - psmd->dm_deformed->needsFree = 1; - psmd->dm_deformed->release(psmd->dm_deformed); - psmd->dm_deformed = NULL; - } - - psys_free_path_cache(psys, NULL); - - if (psys->child) { - MEM_freeN(psys->child); - psys->child = 0; - psys->totchild = 0; - } - - psys->child = data->child; - psys->totchild = data->totchild; - psys->pathcache = data->pathcache; - psys->pathcachebufs.first = data->pathcachebufs.first; - psys->pathcachebufs.last = data->pathcachebufs.last; - psys->totcached = data->totcached; - psys->childcache = data->childcache; - psys->childcachebufs.first = data->childcachebufs.first; - psys->childcachebufs.last = data->childcachebufs.last; - psys->totchildcache = data->totchildcache; - - psmd->dm_final = data->dm; - psmd->totdmvert = data->totdmvert; - psmd->totdmedge = data->totdmedge; - psmd->totdmface = data->totdmface; - psmd->flag &= ~eParticleSystemFlag_psys_updated; - - if (psmd->dm_final) { - if (!psmd->dm_final->deformedOnly) { - if (ob->derivedDeform) { - psmd->dm_deformed = CDDM_copy(ob->derivedDeform); - } - else { - psmd->dm_deformed = CDDM_from_mesh((Mesh *)ob->data); - } - DM_ensure_tessface(psmd->dm_deformed); - } - psys_calc_dmcache(ob, psmd->dm_final, psmd->dm_deformed, psys); - } - - MEM_freeN(data); - psys->renderdata = NULL; - - /* restore particle display percentage */ - disp = psys_get_current_display_percentage(psys); - - if (disp != render_disp) { - /* Hair can and has to be recalculated if everything isn't displayed. */ - if (ELEM(psys->part->type, PART_HAIR, PART_FLUID)) { - psys->recalc |= PSYS_RECALC_RESET; - } - else { - PARTICLE_P; - - LOOP_PARTICLES { - if (psys_frand(psys, p) > disp) - pa->flag |= PARS_NO_DISP; - else - pa->flag &= ~PARS_NO_DISP; - } - } - } -} - -bool psys_render_simplify_params(ParticleSystem *psys, ChildParticle *cpa, float *params) -{ - ParticleRenderData *data; - ParticleRenderElem *elem; - float x, w, scale, alpha, lambda, t, scalemin, scalemax; - int b; - - if (!(psys->renderdata && (psys->part->simplify_flag & PART_SIMPLIFY_ENABLE))) - return false; - - data = psys->renderdata; - if (!data->do_simplify) - return false; - b = (data->index_mf_to_mpoly) ? DM_origindex_mface_mpoly(data->index_mf_to_mpoly, data->index_mp_to_orig, cpa->num) : cpa->num; - if (b == ORIGINDEX_NONE) { - return false; - } + BKE_particle_batch_cache_free(psys); - elem = &data->elems[b]; - - lambda = elem->lambda; - t = elem->t; - scalemin = elem->scalemin; - scalemax = elem->scalemax; - - if (!elem->reduce) { - scale = scalemin; - alpha = 1.0f; - } - else { - x = (elem->curchild + 0.5f) / elem->totchild; - if (x < lambda - t) { - scale = scalemax; - alpha = 1.0f; - } - else if (x >= lambda + t) { - scale = scalemin; - alpha = 0.0f; - } - else { - w = (lambda + t - x) / (2.0f * t); - scale = scalemin + (scalemax - scalemin) * w; - alpha = w; - } + MEM_freeN(psys); } - - params[0] = scale; - params[1] = alpha; - - elem->curchild++; - - return 1; } /************************************************/ @@ -1216,7 +1031,7 @@ static void interpolate_pathcache(ParticleCacheKey *first, float t, ParticleCach /* interpolate a location on a face based on face coordinates */ void psys_interpolate_face(MVert *mvert, MFace *mface, MTFace *tface, float (*orcodata)[3], float w[4], float vec[3], float nor[3], float utan[3], float vtan[3], - float orco[3], float ornor[3]) + float orco[3]) { float *v1 = 0, *v2 = 0, *v3 = 0, *v4 = 0; float e1[3], e2[3], s1, s2, t1, t2; @@ -1314,21 +1129,13 @@ void psys_interpolate_face(MVert *mvert, MFace *mface, MTFace *tface, float (*or o4 = orcodata[mface->v4]; interp_v3_v3v3v3v3(orco, o1, o2, o3, o4, w); - - if (ornor) - normal_quad_v3(ornor, o1, o2, o3, o4); } else { interp_v3_v3v3v3(orco, o1, o2, o3, w); - - if (ornor) - normal_tri_v3(ornor, o1, o2, o3); } } else { copy_v3_v3(orco, vec); - if (ornor && nor) - copy_v3_v3(ornor, nor); } } } @@ -1608,7 +1415,7 @@ static int psys_map_index_on_dm(DerivedMesh *dm, int from, int index, int index_ /* interprets particle data to get a point on a mesh in object space */ void psys_particle_on_dm(DerivedMesh *dm_final, int from, int index, int index_dmcache, const float fw[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3], - float orco[3], float ornor[3]) + float orco[3]) { float tmpnor[3], mapfw[4]; float (*orcodata)[3]; @@ -1618,7 +1425,6 @@ void psys_particle_on_dm(DerivedMesh *dm_final, int from, int index, int index_d if (vec) { vec[0] = vec[1] = vec[2] = 0.0; } if (nor) { nor[0] = nor[1] = 0.0; nor[2] = 1.0; } if (orco) { orco[0] = orco[1] = orco[2] = 0.0; } - if (ornor) { ornor[0] = ornor[1] = 0.0; ornor[2] = 1.0; } if (utan) { utan[0] = utan[1] = utan[2] = 0.0; } if (vtan) { vtan[0] = vtan[1] = vtan[2] = 0.0; } @@ -1644,11 +1450,6 @@ void psys_particle_on_dm(DerivedMesh *dm_final, int from, int index, int index_d } } - if (ornor) { - dm_final->getVertNo(dm_final, mapindex, ornor); - normalize_v3(ornor); - } - if (utan && vtan) { utan[0] = utan[1] = utan[2] = 0.0f; vtan[0] = vtan[1] = vtan[2] = 0.0f; @@ -1667,7 +1468,7 @@ void psys_particle_on_dm(DerivedMesh *dm_final, int from, int index, int index_d mtface += mapindex; if (from == PART_FROM_VOLUME) { - psys_interpolate_face(mvert, mface, mtface, orcodata, mapfw, vec, tmpnor, utan, vtan, orco, ornor); + psys_interpolate_face(mvert, mface, mtface, orcodata, mapfw, vec, tmpnor, utan, vtan, orco); if (nor) copy_v3_v3(nor, tmpnor); @@ -1676,7 +1477,7 @@ void psys_particle_on_dm(DerivedMesh *dm_final, int from, int index, int index_d add_v3_v3(vec, tmpnor); } else - psys_interpolate_face(mvert, mface, mtface, orcodata, mapfw, vec, nor, utan, vtan, orco, ornor); + psys_interpolate_face(mvert, mface, mtface, orcodata, mapfw, vec, nor, utan, vtan, orco); } } @@ -1712,7 +1513,7 @@ ParticleSystemModifierData *psys_get_modifier(Object *ob, ParticleSystem *psys) /* ready for future use */ static void psys_particle_on_shape(int UNUSED(distr), int UNUSED(index), float *UNUSED(fuv), float vec[3], float nor[3], float utan[3], float vtan[3], - float orco[3], float ornor[3]) + float orco[3]) { /* TODO */ float zerovec[3] = {0.0f, 0.0f, 0.0f}; @@ -1731,9 +1532,6 @@ static void psys_particle_on_shape(int UNUSED(distr), int UNUSED(index), if (orco) { copy_v3_v3(orco, zerovec); } - if (ornor) { - copy_v3_v3(ornor, zerovec); - } } /************************************************/ /* Particles on emitter */ @@ -1776,7 +1574,7 @@ CustomDataMask psys_emitter_customdata_mask(ParticleSystem *psys) void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int index, int index_dmcache, float fuv[4], float foffset, float vec[3], float nor[3], float utan[3], float vtan[3], - float orco[3], float ornor[3]) + float orco[3]) { if (psmd && psmd->dm_final) { if (psmd->psys->part->distr == PART_DISTR_GRID && psmd->psys->part->from != PART_FROM_VERT) { @@ -1788,10 +1586,10 @@ void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int in return; } /* we cant use the num_dmcache */ - psys_particle_on_dm(psmd->dm_final, from, index, index_dmcache, fuv, foffset, vec, nor, utan, vtan, orco, ornor); + psys_particle_on_dm(psmd->dm_final, from, index, index_dmcache, fuv, foffset, vec, nor, utan, vtan, orco); } else - psys_particle_on_shape(from, index, fuv, vec, nor, utan, vtan, orco, ornor); + psys_particle_on_shape(from, index, fuv, vec, nor, utan, vtan, orco); } /************************************************/ @@ -1813,7 +1611,7 @@ void precalc_guides(ParticleSimulationData *sim, ListBase *effectors) return; LOOP_PARTICLES { - psys_particle_on_emitter(sim->psmd, sim->psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, state.co, 0, 0, 0, 0, 0); + psys_particle_on_emitter(sim->psmd, sim->psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, state.co, 0, 0, 0, 0); mul_m4_v3(sim->ob->obmat, state.co); mul_mat3_m4_v3(sim->ob->obmat, state.vel); @@ -1839,7 +1637,7 @@ void precalc_guides(ParticleSimulationData *sim, ListBase *effectors) } } -int do_guides(ParticleSettings *part, ListBase *effectors, ParticleKey *state, int index, float time) +int do_guides(Depsgraph *depsgraph, 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; @@ -1902,7 +1700,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(depsgraph, eff->scene, cu->taperobj, (int)(data->strength * guidetime * 100.0f), 100)); else { /* curve size*/ if (cu->flag & CU_PATH_RADIUS) { @@ -2041,7 +1839,7 @@ void psys_find_parents(ParticleSimulationData *sim, const bool use_render_params int from = PART_FROM_FACE; totparent = (int)(totchild * part->parents * 0.3f); - if ((sim->psys->renderdata || use_render_params) && part->child_nbr && part->ren_child_nbr) + if (use_render_params && part->child_nbr && part->ren_child_nbr) totparent *= (float)part->child_nbr / (float)part->ren_child_nbr; /* hard limit, workaround for it being ignored above */ @@ -2052,7 +1850,7 @@ void psys_find_parents(ParticleSimulationData *sim, const bool use_render_params tree = BLI_kdtree_new(totparent); for (p = 0, cpa = sim->psys->child; p < totparent; p++, cpa++) { - psys_particle_on_emitter(sim->psmd, from, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, co, 0, 0, 0, orco, 0); + psys_particle_on_emitter(sim->psmd, from, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, co, 0, 0, 0, orco); /* Check if particle doesn't exist because of texture influence. Insert only existing particles into kdtree. */ get_cpa_texture(sim->psmd->dm_final, psys, part, psys->particles + cpa->pa[0], p, cpa->num, cpa->fuv, orco, &ptex, PAMAP_DENS | PAMAP_CHILD, psys->cfra); @@ -2065,7 +1863,7 @@ void psys_find_parents(ParticleSimulationData *sim, const bool use_render_params BLI_kdtree_balance(tree); for (; p < totchild; p++, cpa++) { - psys_particle_on_emitter(sim->psmd, from, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, co, 0, 0, 0, orco, 0); + psys_particle_on_emitter(sim->psmd, from, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, co, 0, 0, 0, orco); cpa->parent = BLI_kdtree_find_nearest(tree, orco, NULL); } @@ -2085,10 +1883,10 @@ 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->depsgraph, psys)) { ParticleEditSettings *pset = &scene->toolsettings->particle; - if ((psys->renderdata == 0 && use_render_params == 0) && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0) + if ((use_render_params == 0) && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0) totchild = 0; segments = 1 << pset->draw_step; @@ -2097,14 +1895,14 @@ static bool psys_thread_context_init_path( if (totchild && part->childtype == PART_CHILD_FACES) { totparent = (int)(totchild * part->parents * 0.3f); - if ((psys->renderdata || use_render_params) && part->child_nbr && part->ren_child_nbr) + if (use_render_params && part->child_nbr && part->ren_child_nbr) totparent *= (float)part->child_nbr / (float)part->ren_child_nbr; /* part->parents could still be 0 so we can't test with totparent */ between = 1; } - if (psys->renderdata || use_render_params) + if (use_render_params) segments = 1 << part->ren_step; else { totchild = (int)((float)totchild * (float)part->disp / 100.0f); @@ -2182,11 +1980,11 @@ 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.depsgraph, psys) && psys->edit ? psys->edit->pathcache : psys->pathcache; ParticleCacheKey *child, *key[4]; ParticleTexture ptex; float *cpa_fuv = 0, *par_rot = 0, rot[4]; - float orco[3], ornor[3], hairmat[4][4], dvec[3], off1[4][3], off2[4][3]; + float orco[3], hairmat[4][4], dvec[3], off1[4][3], off2[4][3]; float eff_length, eff_vec[3], weight[4]; int k, cpa_num; short cpa_from; @@ -2282,7 +2080,7 @@ static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cp cpa_fuv = cpa->fuv; cpa_from = PART_FROM_FACE; - psys_particle_on_emitter(ctx->sim.psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa->fuv, foffset, co, ornor, 0, 0, orco, 0); + psys_particle_on_emitter(ctx->sim.psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa->fuv, foffset, co, 0, 0, orco, 0); mul_m4_v3(ob->obmat, co); @@ -2324,7 +2122,7 @@ static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cp cpa_num = 0; cpa_fuv = pa->fuv; - psys_particle_on_emitter(ctx->sim.psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa_fuv, pa->foffset, co, ornor, 0, 0, orco, 0); + psys_particle_on_emitter(ctx->sim.psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa_fuv, pa->foffset, co, 0, 0, orco, 0); psys_mat_hair_to_global(ob, ctx->sim.psmd->dm_final, psys->part->from, pa, hairmat); } @@ -2432,9 +2230,9 @@ static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cp BLI_listbase_clear(&modifiers); psys_particle_on_emitter(ctx->sim.psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, - par_co, NULL, NULL, NULL, par_orco, NULL); + par_co, NULL, NULL, NULL, par_orco); - psys_apply_child_modifiers(ctx, &modifiers, cpa, &ptex, orco, ornor, hairmat, child_keys, par, par_orco); + psys_apply_child_modifiers(ctx, &modifiers, cpa, &ptex, orco, hairmat, child_keys, par, par_orco); } else zero_v3(par_orco); @@ -2571,7 +2369,9 @@ static void cache_key_incremental_rotation(ParticleCacheKey *key0, ParticleCache void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_render_params) { PARTICLE_PSMD; +#if 0 ParticleEditSettings *pset = &sim->scene->toolsettings->particle; +#endif ParticleSystem *psys = sim->psys; ParticleSettings *part = psys->part; ParticleCacheKey *ca, **cache; @@ -2592,7 +2392,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re float prev_tangent[3] = {0.0f, 0.0f, 0.0f}, hairmat[4][4]; float rotmat[3][3]; int k; - int segments = (int)pow(2.0, (double)((psys->renderdata || use_render_params) ? part->ren_step : part->draw_step)); + int segments = (int)pow(2.0, (double)((use_render_params) ? part->ren_step : part->draw_step)); int totpart = psys->totpart; float length, vec[3]; float *vg_effector = NULL; @@ -2603,9 +2403,11 @@ 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->renderdata == 0 && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0) +#if 0 /* TODO(mai): something is very wrong with these conditionals, they dont make sense and the cache isnt updating */ + if (psys_in_edit_mode(sim->depsgraph, psys)) + if ((psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0) return; +#endif keyed = psys->flag & PSYS_KEYED; baked = psys->pointcache->mem_cache.first && psys->part->type != PART_HAIR; @@ -2723,7 +2525,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->depsgraph, 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 */ @@ -2771,7 +2573,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(Depsgraph *depsgraph, Scene *scene, Object *ob, PTCacheEdit *edit, float cfra, const bool use_render_params) { ParticleCacheKey *ca, **cache = edit->pathcache; ParticleEditSettings *pset = &scene->toolsettings->particle; @@ -2799,7 +2601,7 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf if (!cache || edit->totpoint != edit->totcached) { /* clear out old and create new empty path cache */ - psys_free_path_cache(edit->psys, edit); + psys_free_path_cache(NULL, edit); cache = edit->pathcache = psys_alloc_path_cache_buffers(&edit->pathcachebufs, totpart, segments + 1); /* set flag for update (child particles check this too) */ @@ -2972,6 +2774,7 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf if (psys) { ParticleSimulationData sim = {0}; + sim.depsgraph = depsgraph; sim.scene = scene; sim.ob = ob; sim.psys = psys; @@ -3108,7 +2911,7 @@ void psys_mat_hair_to_object(Object *UNUSED(ob), DerivedMesh *dm, short from, Pa } psys_face_mat(0, dm, pa, hairmat, 0); - psys_particle_on_dm(dm, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, vec, 0, 0, 0, 0, 0); + psys_particle_on_dm(dm, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, vec, 0, 0, 0, 0); copy_v3_v3(hairmat[3], vec); } @@ -3117,7 +2920,7 @@ void psys_mat_hair_to_orco(Object *ob, DerivedMesh *dm, short from, ParticleData float vec[3], orco[3]; psys_face_mat(ob, dm, pa, hairmat, 1); - psys_particle_on_dm(dm, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, vec, 0, 0, 0, orco, 0); + psys_particle_on_dm(dm, from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, vec, 0, 0, 0, orco); /* see psys_face_mat for why this function is called */ if (DM_get_vert_data_layer(dm, CD_ORIGINDEX)) @@ -3186,8 +2989,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; } @@ -3232,8 +3035,8 @@ void object_remove_particle_system(Scene *UNUSED(scene), Object *ob) 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) @@ -3296,7 +3099,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; @@ -3308,16 +3111,12 @@ static void default_particle_settings(ParticleSettings *part) part->color_vec_max = 1.f; part->draw_col = PART_DRAW_COL_MAT; - part->simplify_refsize = 1920; - part->simplify_rate = 1.0f; - part->simplify_transition = 0.1f; - part->simplify_viewport = 0.8; - if (!part->effector_weights) part->effector_weights = BKE_add_effector_weights(NULL); part->omat = 1; part->use_modifier_stack = false; + part->draw_size = 0.1f; } @@ -3626,7 +3425,7 @@ void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTex /* no break, failed to get uv's, so let's try orco's */ ATTR_FALLTHROUGH; case TEXCO_ORCO: - psys_particle_on_emitter(sim->psmd, sim->psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co, 0, 0, 0, texvec, 0); + psys_particle_on_emitter(sim->psmd, sim->psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co, 0, 0, 0, texvec); if (me->bb == NULL || (me->bb->flag & BOUNDBOX_DIRTY)) { BKE_mesh_texspace_calc(me); @@ -3822,7 +3621,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->depsgraph, psys) ? NULL : psys->hair_out_dm; init_particle_interpolation(sim->ob, psys, pa, &pind); do_particle_interpolation(psys, p, pa, t, &pind, state); @@ -3837,7 +3636,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->depsgraph, sim->psys->part, sim->psys->effectors, state, p, state->time); /* TODO: proper velocity handling */ } @@ -3888,7 +3687,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey * cpa_fuv = cpa->fuv; cpa_from = PART_FROM_FACE; - psys_particle_on_emitter(psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa->fuv, foffset, co, 0, 0, 0, orco, 0); + psys_particle_on_emitter(psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa->fuv, foffset, co, 0, 0, 0, orco); /* we need to save the actual root position of the child for positioning it accurately to the surface of the emitter */ //copy_v3_v3(cpa_1st, co); @@ -3897,7 +3696,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey * pa = psys->particles + cpa->parent; - psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, par_co, 0, 0, 0, par_orco, 0); + psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, par_co, 0, 0, 0, par_orco); if (part->type == PART_HAIR) psys_mat_hair_to_global(sim->ob, sim->psmd->dm_final, psys->part->from, pa, hairmat); else @@ -3917,9 +3716,9 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey * cpa_num = pa->num; cpa_fuv = pa->fuv; - psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, par_co, 0, 0, 0, par_orco, 0); + psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, par_co, 0, 0, 0, par_orco); if (part->type == PART_HAIR) { - psys_particle_on_emitter(psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa_fuv, pa->foffset, co, 0, 0, 0, orco, 0); + psys_particle_on_emitter(psmd, cpa_from, cpa_num, DMCACHE_ISCHILD, cpa_fuv, pa->foffset, co, 0, 0, 0, orco); psys_mat_hair_to_global(sim->ob, sim->psmd->dm_final, psys->part->from, pa, hairmat); } else { @@ -4204,7 +4003,7 @@ void psys_get_dupli_texture(ParticleSystem *psys, ParticleSettings *part, psys_interpolate_uvs(mtface, mface->v4, cpa->fuv, uv); } - psys_particle_on_emitter(psmd, PART_FROM_FACE, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, loc, 0, 0, 0, orco, 0); + psys_particle_on_emitter(psmd, PART_FROM_FACE, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, loc, 0, 0, 0, orco); return; } else { @@ -4235,7 +4034,7 @@ void psys_get_dupli_texture(ParticleSystem *psys, ParticleSettings *part, } } - psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, loc, 0, 0, 0, orco, 0); + psys_particle_on_emitter(psmd, part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, loc, 0, 0, 0, orco); } void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa, ChildParticle *cpa, ParticleCacheKey *cache, float mat[4][4], float *scale) @@ -4253,9 +4052,9 @@ void psys_get_dupli_path_transform(ParticleSimulationData *sim, ParticleData *pa pa = psys->particles + cpa->pa[0]; if (pa) - psys_particle_on_emitter(psmd, sim->psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, loc, nor, 0, 0, 0, 0); + psys_particle_on_emitter(psmd, sim->psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, loc, nor, 0, 0, 0); else - psys_particle_on_emitter(psmd, PART_FROM_FACE, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, loc, nor, 0, 0, 0, 0); + psys_particle_on_emitter(psmd, PART_FROM_FACE, cpa->num, DMCACHE_ISCHILD, cpa->fuv, cpa->foffset, loc, nor, 0, 0, 0); if (psys->part->rotmode == PART_ROT_VEL) { transpose_m3_m4(nmat, ob->imat); @@ -4387,9 +4186,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(Depsgraph *depsgraph, Scene *scene, Object *ob, ParticleSystem *psys) { ParticleSimulationData sim = {0}; + sim.depsgraph = depsgraph; sim.scene = scene; sim.ob = ob; sim.psys = psys; @@ -4422,3 +4222,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 c921e1ea107..7cfad93224d 100644 --- a/source/blender/blenkernel/intern/particle_child.c +++ b/source/blender/blenkernel/intern/particle_child.c @@ -39,40 +39,6 @@ #include "particle_private.h" -struct Material; - -static void get_strand_normal(Material *ma, const float surfnor[3], float surfdist, float nor[3]) -{ - float cross[3], nstrand[3], vnor[3], blend; - - if (!((ma->mode & MA_STR_SURFDIFF) || (ma->strand_surfnor > 0.0f))) - return; - - if (ma->mode & MA_STR_SURFDIFF) { - cross_v3_v3v3(cross, surfnor, nor); - cross_v3_v3v3(nstrand, nor, cross); - - blend = dot_v3v3(nstrand, surfnor); - CLAMP(blend, 0.0f, 1.0f); - - interp_v3_v3v3(vnor, nstrand, surfnor, blend); - normalize_v3(vnor); - } - else { - copy_v3_v3(vnor, nor); - } - - if (ma->strand_surfnor > 0.0f) { - if (ma->strand_surfnor > surfdist) { - blend = (ma->strand_surfnor - surfdist) / ma->strand_surfnor; - interp_v3_v3v3(vnor, vnor, surfnor, blend); - normalize_v3(vnor); - } - } - - copy_v3_v3(nor, vnor); -} - /* ------------------------------------------------------------------------- */ typedef struct ParticlePathIterator { @@ -320,7 +286,7 @@ static bool check_path_length(int k, ParticleCacheKey *keys, ParticleCacheKey *k } void psys_apply_child_modifiers(ParticleThreadContext *ctx, struct ListBase *modifiers, - ChildParticle *cpa, ParticleTexture *ptex, const float orco[3], const float ornor[3], float hairmat[4][4], + ChildParticle *cpa, ParticleTexture *ptex, const float orco[3], float hairmat[4][4], ParticleCacheKey *keys, ParticleCacheKey *parent_keys, const float parent_orco[3]) { struct ParticleSettings *part = ctx->sim.psys->part; @@ -389,9 +355,6 @@ void psys_apply_child_modifiers(ParticleThreadContext *ctx, struct ListBase *mod if (k >= 2) { sub_v3_v3v3((key-1)->vel, key->co, (key-2)->co); mul_v3_fl((key-1)->vel, 0.5); - - if (ma && draw_col_ma) - get_strand_normal(ma, ornor, cur_length, (key-1)->vel); } if (use_length_check && k > 0) { @@ -413,7 +376,6 @@ void psys_apply_child_modifiers(ParticleThreadContext *ctx, struct ListBase *mod if (ma && draw_col_ma) { copy_v3_v3(key->col, &ma->r); - get_strand_normal(ma, ornor, cur_length, key->vel); } } } @@ -816,7 +778,7 @@ void do_child_modifiers(const ParticleChildModifierContext *modifier_ctx, 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->depsgraph, 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 d1c6dbe421c..bf21e18f4b9 100644 --- a/source/blender/blenkernel/intern/particle_distribute.c +++ b/source/blender/blenkernel/intern/particle_distribute.c @@ -57,7 +57,7 @@ #include "BKE_object.h" #include "BKE_particle.h" -static int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot); +#include "DEG_depsgraph_query.h" static void alloc_child_particles(ParticleSystem *psys, int tot) { @@ -80,12 +80,12 @@ static void alloc_child_particles(ParticleSystem *psys, int tot) } } -static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, DerivedMesh *deformdm, ParticleSystem *psys) +static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, DerivedMesh *deformdm, ParticleSystem *psys, const bool use_render_params) { ChildParticle *cpa = NULL; int i, p; - int child_nbr= psys_get_child_number(scene, psys); - int totpart= psys_get_tot_child(scene, psys); + int child_nbr= psys_get_child_number(scene, psys, use_render_params); + int totpart= psys_get_tot_child(scene, psys, use_render_params); alloc_child_particles(psys, totpart); @@ -314,19 +314,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); @@ -577,7 +574,7 @@ static void distribute_from_volume_exec(ParticleTask *thread, ParticleData *pa, /* experimental */ tot=dm->getNumTessFaces(dm); - psys_interpolate_face(mvert,mface,0,0,pa->fuv,co,nor,0,0,0,0); + psys_interpolate_face(mvert,mface,0,0,pa->fuv,co,nor,0,0,0); normalize_v3(nor); negate_v3(nor); @@ -664,7 +661,7 @@ static void distribute_children_exec(ParticleTask *thread, ChildParticle *cpa, i int parent[10]; float pweight[10]; - psys_particle_on_dm(dm,cfrom,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co1,nor1,NULL,NULL,orco1,NULL); + psys_particle_on_dm(dm,cfrom,cpa->num,DMCACHE_ISCHILD,cpa->fuv,cpa->foffset,co1,nor1,NULL,NULL,orco1); BKE_mesh_orco_verts_transform((Mesh*)ob->data, &orco1, 1, 1); maxw = BLI_kdtree_find_nearest_n(ctx->tree,orco1,ptn,3); @@ -743,16 +740,10 @@ static void exec_distribute_child(TaskPool * __restrict UNUSED(pool), void *task /* RNG skipping at the beginning */ cpa = psys->child; for (p = 0; p < task->begin; ++p, ++cpa) { - if (task->ctx->skip) /* simplification skip */ - BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->ctx->skip[p]); - BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP); } for (; p < task->end; ++p, ++cpa) { - if (task->ctx->skip) /* simplification skip */ - BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->ctx->skip[p]); - distribute_children_exec(task, cpa, p); } } @@ -779,11 +770,15 @@ static int distribute_compare_orig_index(const void *p1, const void *p2, void *u return 1; } -static void distribute_invalid(Scene *scene, ParticleSystem *psys, int from) +static void distribute_invalid(ParticleSimulationData *sim, int from) { + Scene *scene = sim->scene; + ParticleSystem *psys = sim->psys; + const bool use_render_params = (DEG_get_mode(sim->depsgraph) == DAG_EVAL_RENDER); + if (from == PART_FROM_CHILD) { ChildParticle *cpa; - int p, totchild = psys_get_tot_child(scene, psys); + int p, totchild = psys_get_tot_child(scene, psys, use_render_params); if (psys->child && totchild) { for (p=0,cpa=psys->child; p<totchild; p++,cpa++) { @@ -846,13 +841,15 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti */ psys_thread_context_init(ctx, sim); + + const bool use_render_params = (DEG_get_mode(sim->depsgraph) == DAG_EVAL_RENDER); /* First handle special cases */ if (from == PART_FROM_CHILD) { /* Simple children */ if (part->childtype != PART_CHILD_FACES) { BLI_srandom(31415926 + psys->seed + psys->child_seed); - distribute_simple_children(scene, ob, finaldm, sim->psmd->dm_deformed, psys); + distribute_simple_children(scene, ob, finaldm, sim->psmd->dm_deformed, psys, use_render_params); return 0; } } @@ -893,14 +890,14 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti tree=BLI_kdtree_new(totpart); for (p=0,pa=psys->particles; p<totpart; p++,pa++) { - psys_particle_on_dm(dm,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,nor,0,0,orco,NULL); + psys_particle_on_dm(dm,part->from,pa->num,pa->num_dmcache,pa->fuv,pa->foffset,co,nor,0,0,orco); BKE_mesh_orco_verts_transform((Mesh*)ob->data, &orco, 1, 1); BLI_kdtree_insert(tree, p, orco); } BLI_kdtree_balance(tree); - totpart = psys_get_tot_child(scene, psys); + totpart = psys_get_tot_child(scene, psys, use_render_params); cfrom = from = PART_FROM_FACE; } else { @@ -943,7 +940,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti totelem = (from == PART_FROM_VERT) ? dm->getNumVerts(dm) : dm->getNumTessFaces(dm); if (totelem == 0) { - distribute_invalid(scene, psys, children ? PART_FROM_CHILD : 0); + distribute_invalid(sim, children ? PART_FROM_CHILD : 0); if (G.debug & G_DEBUG) fprintf(stderr,"Particle distribution error: Nothing to emit from!\n"); @@ -1087,7 +1084,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti totmapped = i_mapped; /* Finally assign elements to particles */ - if ((part->flag & PART_TRAND) || (part->simplify_flag & PART_SIMPLIFY_ENABLE)) { + if (part->flag & PART_TRAND) { for (p = 0; p < totpart; p++) { /* In theory element_sum[totmapped - 1] should be 1.0, * but due to float errors this is not necessarily always true, so scale pos accordingly. */ @@ -1181,7 +1178,6 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti ctx->tpars= tpars; if (children) { - totpart= psys_render_simplify_distribution(ctx, totpart); alloc_child_particles(psys, totpart); } @@ -1240,7 +1236,7 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from) /* ready for future use, to emit particles without geometry */ static void distribute_particles_on_shape(ParticleSimulationData *sim, int UNUSED(from)) { - distribute_invalid(sim->scene, sim->psys, 0); + distribute_invalid(sim, 0); fprintf(stderr,"Shape emission not yet possible!\n"); } @@ -1260,250 +1256,8 @@ void distribute_particles(ParticleSimulationData *sim, int from) distribute_particles_on_shape(sim, from); if (distr_error) { - distribute_invalid(sim->scene, sim->psys, from); + distribute_invalid(sim, from); fprintf(stderr,"Particle distribution error!\n"); } } - -/* ======== Simplify ======== */ - -static float psys_render_viewport_falloff(double rate, float dist, float width) -{ - return pow(rate, dist / width); -} - -static float psys_render_projected_area(ParticleSystem *psys, const float center[3], float area, double vprate, float *viewport) -{ - ParticleRenderData *data = psys->renderdata; - float co[4], view[3], ortho1[3], ortho2[3], w, dx, dy, radius; - - /* transform to view space */ - copy_v3_v3(co, center); - co[3] = 1.0f; - mul_m4_v4(data->viewmat, co); - - /* compute two vectors orthogonal to view vector */ - normalize_v3_v3(view, co); - ortho_basis_v3v3_v3(ortho1, ortho2, view); - - /* compute on screen minification */ - w = co[2] * data->winmat[2][3] + data->winmat[3][3]; - dx = data->winx * ortho2[0] * data->winmat[0][0]; - dy = data->winy * ortho2[1] * data->winmat[1][1]; - w = sqrtf(dx * dx + dy * dy) / w; - - /* w squared because we are working with area */ - area = area * w * w; - - /* viewport of the screen test */ - - /* project point on screen */ - mul_m4_v4(data->winmat, co); - if (co[3] != 0.0f) { - co[0] = 0.5f * data->winx * (1.0f + co[0] / co[3]); - co[1] = 0.5f * data->winy * (1.0f + co[1] / co[3]); - } - - /* screen space radius */ - radius = sqrtf(area / (float)M_PI); - - /* make smaller using fallof once over screen edge */ - *viewport = 1.0f; - - if (co[0] + radius < 0.0f) - *viewport *= psys_render_viewport_falloff(vprate, -(co[0] + radius), data->winx); - else if (co[0] - radius > data->winx) - *viewport *= psys_render_viewport_falloff(vprate, (co[0] - radius) - data->winx, data->winx); - - if (co[1] + radius < 0.0f) - *viewport *= psys_render_viewport_falloff(vprate, -(co[1] + radius), data->winy); - else if (co[1] - radius > data->winy) - *viewport *= psys_render_viewport_falloff(vprate, (co[1] - radius) - data->winy, data->winy); - - return area; -} - -/* BMESH_TODO, for orig face data, we need to use MPoly */ -static int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot) -{ - DerivedMesh *dm = ctx->dm; - Mesh *me = (Mesh *)(ctx->sim.ob->data); - MFace *mf, *mface; - MVert *mvert; - ParticleRenderData *data; - ParticleRenderElem *elems, *elem; - ParticleSettings *part = ctx->sim.psys->part; - float *facearea, (*facecenter)[3], size[3], fac, powrate, scaleclamp; - float co1[3], co2[3], co3[3], co4[3], lambda, arearatio, t, area, viewport; - double vprate; - int *facetotvert; - int a, b, totorigface, totface, newtot, skipped; - - /* double lookup */ - const int *index_mf_to_mpoly; - const int *index_mp_to_orig; - - if (part->ren_as != PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND)) - return tot; - if (!ctx->sim.psys->renderdata) - return tot; - - data = ctx->sim.psys->renderdata; - if (data->timeoffset) - return 0; - if (!(part->simplify_flag & PART_SIMPLIFY_ENABLE)) - return tot; - - mvert = dm->getVertArray(dm); - mface = dm->getTessFaceArray(dm); - totface = dm->getNumTessFaces(dm); - totorigface = me->totpoly; - - if (totface == 0 || totorigface == 0) - return tot; - - index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); - index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX); - if (index_mf_to_mpoly == NULL) { - index_mp_to_orig = NULL; - } - - facearea = MEM_callocN(sizeof(float) * totorigface, "SimplifyFaceArea"); - facecenter = MEM_callocN(sizeof(float[3]) * totorigface, "SimplifyFaceCenter"); - facetotvert = MEM_callocN(sizeof(int) * totorigface, "SimplifyFaceArea"); - elems = MEM_callocN(sizeof(ParticleRenderElem) * totorigface, "SimplifyFaceElem"); - - if (data->elems) - MEM_freeN(data->elems); - - data->do_simplify = true; - data->elems = elems; - data->index_mf_to_mpoly = index_mf_to_mpoly; - data->index_mp_to_orig = index_mp_to_orig; - - /* compute number of children per original face */ - for (a = 0; a < tot; a++) { - b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, ctx->index[a]) : ctx->index[a]; - if (b != ORIGINDEX_NONE) { - elems[b].totchild++; - } - } - - /* compute areas and centers of original faces */ - for (mf = mface, a = 0; a < totface; a++, mf++) { - b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a; - - if (b != ORIGINDEX_NONE) { - copy_v3_v3(co1, mvert[mf->v1].co); - copy_v3_v3(co2, mvert[mf->v2].co); - copy_v3_v3(co3, mvert[mf->v3].co); - - add_v3_v3(facecenter[b], co1); - add_v3_v3(facecenter[b], co2); - add_v3_v3(facecenter[b], co3); - - if (mf->v4) { - copy_v3_v3(co4, mvert[mf->v4].co); - add_v3_v3(facecenter[b], co4); - facearea[b] += area_quad_v3(co1, co2, co3, co4); - facetotvert[b] += 4; - } - else { - facearea[b] += area_tri_v3(co1, co2, co3); - facetotvert[b] += 3; - } - } - } - - for (a = 0; a < totorigface; a++) - if (facetotvert[a] > 0) - mul_v3_fl(facecenter[a], 1.0f / facetotvert[a]); - - /* for conversion from BU area / pixel area to reference screen size */ - BKE_mesh_texspace_get(me, 0, 0, size); - fac = ((size[0] + size[1] + size[2]) / 3.0f) / part->simplify_refsize; - fac = fac * fac; - - powrate = log(0.5f) / log(part->simplify_rate * 0.5f); - if (part->simplify_flag & PART_SIMPLIFY_VIEWPORT) - vprate = pow(1.0f - part->simplify_viewport, 5.0); - else - vprate = 1.0; - - /* set simplification parameters per original face */ - for (a = 0, elem = elems; a < totorigface; a++, elem++) { - area = psys_render_projected_area(ctx->sim.psys, facecenter[a], facearea[a], vprate, &viewport); - arearatio = fac * area / facearea[a]; - - if ((arearatio < 1.0f || viewport < 1.0f) && elem->totchild) { - /* lambda is percentage of elements to keep */ - lambda = (arearatio < 1.0f) ? powf(arearatio, powrate) : 1.0f; - lambda *= viewport; - - lambda = MAX2(lambda, 1.0f / elem->totchild); - - /* compute transition region */ - t = part->simplify_transition; - elem->t = (lambda - t < 0.0f) ? lambda : (lambda + t > 1.0f) ? 1.0f - lambda : t; - elem->reduce = 1; - - /* scale at end and beginning of the transition region */ - elem->scalemax = (lambda + t < 1.0f) ? 1.0f / lambda : 1.0f / (1.0f - elem->t * elem->t / t); - elem->scalemin = (lambda + t < 1.0f) ? 0.0f : elem->scalemax * (1.0f - elem->t / t); - - elem->scalemin = sqrtf(elem->scalemin); - elem->scalemax = sqrtf(elem->scalemax); - - /* clamp scaling */ - scaleclamp = (float)min_ii(elem->totchild, 10); - elem->scalemin = MIN2(scaleclamp, elem->scalemin); - elem->scalemax = MIN2(scaleclamp, elem->scalemax); - - /* extend lambda to include transition */ - lambda = lambda + elem->t; - if (lambda > 1.0f) - lambda = 1.0f; - } - else { - lambda = arearatio; - - elem->scalemax = 1.0f; //sqrt(lambda); - elem->scalemin = 1.0f; //sqrt(lambda); - elem->reduce = 0; - } - - elem->lambda = lambda; - elem->scalemin = sqrtf(elem->scalemin); - elem->scalemax = sqrtf(elem->scalemax); - elem->curchild = 0; - } - - MEM_freeN(facearea); - MEM_freeN(facecenter); - MEM_freeN(facetotvert); - - /* move indices and set random number skipping */ - ctx->skip = MEM_callocN(sizeof(int) * tot, "SimplificationSkip"); - - skipped = 0; - for (a = 0, newtot = 0; a < tot; a++) { - b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, ctx->index[a]) : ctx->index[a]; - - if (b != ORIGINDEX_NONE) { - if (elems[b].curchild++ < ceil(elems[b].lambda * elems[b].totchild)) { - ctx->index[newtot] = ctx->index[a]; - ctx->skip[newtot] = skipped; - skipped = 0; - newtot++; - } - else skipped++; - } - else skipped++; - } - - for (a = 0, elem = elems; a < totorigface; a++, elem++) - elem->curchild = 0; - - return newtot; -} diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c index 94c1dd0c7c3..ab307ebdbe8 100644 --- a/source/blender/blenkernel/intern/particle_system.c +++ b/source/blender/blenkernel/intern/particle_system.c @@ -77,6 +77,7 @@ #include "BKE_library_query.h" #include "BKE_particle.h" +#include "BKE_collection.h" #include "BKE_DerivedMesh.h" #include "BKE_object.h" #include "BKE_material.h" @@ -87,12 +88,16 @@ #include "BKE_modifier.h" #include "BKE_scene.h" #include "BKE_bvhutils.h" -#include "BKE_depsgraph.h" + +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" #include "PIL_time.h" #include "RE_shader_ext.h" -#include "DEG_depsgraph.h" + +/* FIXME: BAD LEVEL CALL. */ +#include "../../editors/include/ED_particle.h" /* fluid sim particle import */ #ifdef WITH_MOD_FLUID @@ -120,11 +125,11 @@ static int particles_are_dynamic(ParticleSystem *psys) return ELEM(psys->part->phystype, PART_PHYS_NEWTON, PART_PHYS_BOIDS, PART_PHYS_FLUID); } -float psys_get_current_display_percentage(ParticleSystem *psys) +float psys_get_current_display_percentage(ParticleSystem *psys, const bool use_render_params) { ParticleSettings *part=psys->part; - if ((psys->renderdata && !particles_are_dynamic(psys)) || /* non-dynamic particles can be rendered fully */ + if ((use_render_params && !particles_are_dynamic(psys)) || /* non-dynamic particles can be rendered fully */ (part->child_nbr && part->childtype) || /* display percentage applies to children */ (psys->pointcache->flag & PTCACHE_BAKING)) /* baking is always done with full amount */ { @@ -284,24 +289,24 @@ static void realloc_particles(ParticleSimulationData *sim, int new_totpart) } } -int psys_get_child_number(Scene *scene, ParticleSystem *psys) +int psys_get_child_number(Scene *scene, ParticleSystem *psys, const bool use_render_params) { int nbr; if (!psys->part->childtype) return 0; - if (psys->renderdata) + if (use_render_params) nbr= psys->part->ren_child_nbr; else nbr= psys->part->child_nbr; - return get_render_child_particle_number(&scene->r, nbr, psys->renderdata != NULL); + return get_render_child_particle_number(&scene->r, nbr, use_render_params); } -int psys_get_tot_child(Scene *scene, ParticleSystem *psys) +int psys_get_tot_child(Scene *scene, ParticleSystem *psys, const bool use_render_params) { - return psys->totpart*psys_get_child_number(scene, psys); + return psys->totpart*psys_get_child_number(scene, psys, use_render_params); } /************************************************/ @@ -510,7 +515,6 @@ void psys_thread_context_free(ParticleThreadContext *ctx) if (ctx->jitoff) MEM_freeN(ctx->jitoff); if (ctx->weight) MEM_freeN(ctx->weight); if (ctx->index) MEM_freeN(ctx->index); - if (ctx->skip) MEM_freeN(ctx->skip); if (ctx->seams) MEM_freeN(ctx->seams); //if (ctx->vertpart) MEM_freeN(ctx->vertpart); BLI_kdtree_free(ctx->tree); @@ -701,9 +705,9 @@ void psys_get_birth_coords(ParticleSimulationData *sim, ParticleData *pa, Partic /* get birth location from object */ if (use_tangents) - psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0,0); + psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0); else - psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0,0); + psys_particle_on_emitter(sim->psmd, part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,0,0,0); /* get possible textural influence */ psys_get_texture(sim, pa, &ptex, PAMAP_IVEL, cfra); @@ -987,14 +991,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(struct Depsgraph *depsgraph, Scene *scene, Object *ob, float cfra) { if (ob->parent) - evaluate_emitter_anim(scene, ob->parent, cfra); + evaluate_emitter_anim(depsgraph, 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(depsgraph, scene, ob, cfra); } /* sets particle to the emitter surface with initial velocity & rotation */ @@ -1008,7 +1012,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->depsgraph, sim->scene, sim->ob, pa->time); psys->flag |= PSYS_OB_ANIM_RESTORE; } @@ -1142,7 +1146,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.depsgraph = sim->depsgraph; + ksim.scene = sim->scene; /* no proper targets so let's clear and bail out */ if (psys->totkeyed==0) { @@ -1303,7 +1308,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->depsgraph, sim->scene, sim->ob, sim->psys, sim->psys->part->effector_weights, true); precalc_guides(sim, sim->psys->effectors); } @@ -2124,7 +2129,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->depsgraph, 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); @@ -2905,10 +2910,9 @@ 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) + if ((psys->part->childtype && psys->totchild != psys_get_tot_child(sim->scene, psys, use_render_params)) || 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))) @@ -2918,7 +2922,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons if (alloc) realloc_particles(sim, sim->psys->totpart); - if (psys_get_tot_child(sim->scene, psys)) { + if (psys_get_tot_child(sim->scene, psys, use_render_params)) { /* don't generate children while computing the hair keys */ if (!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) { distribute_particles(sim, PART_FROM_CHILD); @@ -2935,23 +2939,27 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons skip = 1; /* only hair, keyed and baked stuff can have paths */ else if (part->ren_as != PART_DRAW_PATH && !(part->type==PART_HAIR && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR))) skip = 1; /* particle visualization must be set as path */ - else if (!psys->renderdata) { + else { if (part->draw_as != PART_DRAW_REND) 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->depsgraph, psys)) { if ((pset->flag & PE_DRAW_PART)==0) skip = 1; +#if 0 /* TODO(mai): something is very wrong with these conditionals, they dont make sense and the cache isnt updating */ else if (part->childtype==0 && (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED)==0) skip = 1; /* in edit mode paths are needed for child particles and dynamic hair */ +#endif } } /* 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_BEGIN(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)) { @@ -2960,6 +2968,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); @@ -3205,7 +3214,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->depsgraph, sim->scene, sim->ob, psys->hair_in_dm, deformedVerts); CDDM_apply_vert_coords(psys->hair_out_dm, deformedVerts); @@ -3219,7 +3228,7 @@ static void hair_step(ParticleSimulationData *sim, float cfra, const bool use_re ParticleSystem *psys = sim->psys; ParticleSettings *part = psys->part; PARTICLE_P; - float disp = psys_get_current_display_percentage(psys); + float disp = psys_get_current_display_percentage(psys, use_render_params); LOOP_PARTICLES { pa->size = part->size; @@ -3735,13 +3744,13 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra) free_collider_cache(&sim->colliders); BLI_rng_free(rng); } -static void update_children(ParticleSimulationData *sim) +static void update_children(ParticleSimulationData *sim, const bool use_render_params) { if ((sim->psys->part->type == PART_HAIR) && (sim->psys->flag & PSYS_HAIR_DONE)==0) /* don't generate children while growing hair - waste of time */ psys_free_children(sim->psys); else if (sim->psys->part->childtype) { - if (sim->psys->totchild != psys_get_tot_child(sim->scene, sim->psys)) + if (sim->psys->totchild != psys_get_tot_child(sim->scene, sim->psys, use_render_params)) distribute_particles(sim, PART_FROM_CHILD); else { /* Children are up to date, nothing to do. */ @@ -3751,7 +3760,7 @@ static void update_children(ParticleSimulationData *sim) psys_free_children(sim->psys); } /* updates cached particles' alive & other flags etc..*/ -static void cached_step(ParticleSimulationData *sim, float cfra) +static void cached_step(ParticleSimulationData *sim, float cfra, const bool use_render_params) { ParticleSystem *psys = sim->psys; ParticleSettings *part = psys->part; @@ -3761,7 +3770,7 @@ static void cached_step(ParticleSimulationData *sim, float cfra) psys_update_effectors(sim); - disp= psys_get_current_display_percentage(psys); + disp= psys_get_current_display_percentage(psys, use_render_params); LOOP_PARTICLES { psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra); @@ -3983,8 +3992,8 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_ int cache_result = BKE_ptcache_read(pid, cache_cfra, true); if (ELEM(cache_result, PTCACHE_READ_EXACT, PTCACHE_READ_INTERPOLATED)) { - cached_step(sim, cfra); - update_children(sim); + cached_step(sim, cfra, use_render_params); + update_children(sim, use_render_params); psys_update_path_cache(sim, cfra, use_render_params); BKE_ptcache_validate(cache, (int)cache_cfra); @@ -4001,7 +4010,7 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_ } else if (cache_result == PTCACHE_READ_OLD) { psys->cfra = (float)cache->simframe; - cached_step(sim, psys->cfra); + cached_step(sim, psys->cfra, use_render_params); } /* if on second frame, write cache for first frame */ @@ -4013,7 +4022,7 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_ /* 3. do dynamics */ /* set particles to be not calculated TODO: can't work with pointcache */ - disp= psys_get_current_display_percentage(psys); + disp= psys_get_current_display_percentage(psys, use_render_params); LOOP_PARTICLES { if (psys_frand(psys, p) > disp) @@ -4069,7 +4078,7 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_ BKE_ptcache_write(pid, (int)cache_cfra); } - update_children(sim); + update_children(sim, use_render_params); /* cleanup */ if (psys->lattice_deform_data) { @@ -4205,7 +4214,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(struct Depsgraph *depsgraph, Scene *scene, Object *ob, ParticleSystem *psys, const bool use_render_params) { ParticleSimulationData sim= {0}; ParticleSettings *part = psys->part; @@ -4219,10 +4228,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.depsgraph = depsgraph; + 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) { @@ -4311,7 +4321,7 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys, cons case PART_PHYS_KEYED: { PARTICLE_P; - float disp = psys_get_current_display_percentage(psys); + float disp = psys_get_current_display_percentage(psys, use_render_params); bool free_unexisting = false; /* Particles without dynamics haven't been reset yet because they don't use pointcache */ @@ -4365,7 +4375,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(depsgraph, scene, ob, cfra); psys->flag &= ~PSYS_OB_ANIM_RESTORE; } @@ -4373,8 +4383,25 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys, cons psys->recalc = 0; /* 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); + invert_m4_m4(psys->imat, ob->obmat); + + if (ob->mode & OB_MODE_PARTICLE_EDIT && ob == OBACT(DEG_get_evaluated_view_layer(depsgraph))) { + PTCacheEdit *edit = PE_create_current(depsgraph, scene, ob); + + if (edit && edit->psys == psys) { + if (edit->psys && edit->psys->flag & PSYS_HAIR_UPDATED) { + PE_update_object(depsgraph, scene, ob, 0); + } + + /* create path and child path cache if it doesn't exist already */ + if (edit->pathcache == NULL) { + psys_cache_edit_paths(depsgraph, scene, ob, edit, DEG_get_ctime(depsgraph), DEG_get_mode(depsgraph) == DAG_EVAL_RENDER); + + } + } + } + + BKE_particle_batch_cache_dirty(psys, BKE_PARTICLE_BATCH_DIRTY_ALL); } /* ID looper */ @@ -4405,10 +4432,16 @@ 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_eval_init(struct Depsgraph *depsgraph, Scene *scene, Object *ob) { - DEG_debug_print_eval(__func__, ob->id.name, ob); + DEG_debug_print_eval(depsgraph, __func__, ob->id.name, ob); + for (ParticleSystem *psys = ob->particlesystem.first; + psys != NULL; + psys = psys->next) + { + psys->recalc |= (psys->part->id.recalc & DEG_TAG_PSYS_ALL); + } 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 51d50b061de..7b53c5f8811 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" @@ -1185,19 +1186,6 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode) } } -void BKE_pbvh_draw_BB(PBVH *bvh) -{ - GPU_pbvh_BB_draw_init(); - - 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_end(); -} - static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag) { int update = 0; @@ -2006,42 +1994,6 @@ bool BKE_pbvh_node_find_nearest_to_ray( return hit; } -typedef struct { - DMSetMaterial setMaterial; - bool wireframe; - bool fast; -} PBVHNodeDrawData; - -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, - data->wireframe, - data->fast); - } -} - typedef enum { ISECT_INSIDE, ISECT_OUTSIDE, @@ -2110,6 +2062,8 @@ static void pbvh_node_check_diffuse_changed(PBVH *bvh, PBVHNode *node) node->flag |= PBVH_UpdateDrawBuffers; } +/* TODO: not needed anymore in 2.8? */ +#if 0 static void pbvh_node_check_mask_changed(PBVH *bvh, PBVHNode *node) { if (!node->draw_buffers) { @@ -2119,18 +2073,44 @@ static void pbvh_node_check_mask_changed(PBVH *bvh, PBVHNode *node) node->flag |= PBVH_UpdateDrawBuffers; } } +#endif -void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*fnors)[3], - DMSetMaterial setMaterial, bool wireframe, bool fast) +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) { - PBVHNodeDrawData draw_data = {setMaterial, wireframe, fast}; + 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++) { + for (int a = 0; a < bvh->totnode; a++) pbvh_node_check_diffuse_changed(bvh, &bvh->nodes[a]); - pbvh_node_check_mask_changed(bvh, &bvh->nodes[a]); - } BKE_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(PBVH_UpdateNormals | PBVH_UpdateDrawBuffers), &nodes, &totnode); @@ -2141,15 +2121,19 @@ void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*fnors)[3], if (nodes) MEM_freeN(nodes); if (planes) { - BKE_pbvh_search_callback(bvh, BKE_pbvh_node_planes_contain_AABB, - planes, BKE_pbvh_node_draw, &draw_data); + 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, BKE_pbvh_node_draw, &draw_data); + BKE_pbvh_search_callback( + bvh, NULL, + NULL, pbvh_node_draw_cb, &draw_data); } - +#if 0 if (G.debug_value == 14) - BKE_pbvh_draw_BB(bvh); + pbvh_draw_BB(bvh); +#endif } void BKE_pbvh_grids_update(PBVH *bvh, CCGElem **grids, void **gridfaces, @@ -2361,24 +2345,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 89885bdca26..3ab17b083db 100644 --- a/source/blender/blenkernel/intern/pointcache.c +++ b/source/blender/blenkernel/intern/pointcache.c @@ -38,6 +38,7 @@ #include "DNA_ID.h" #include "DNA_dynamicpaint_types.h" +#include "DNA_group_types.h" #include "DNA_modifier_types.h" #include "DNA_object_types.h" #include "DNA_object_force_types.h" @@ -1647,6 +1648,25 @@ void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *r pid->file_type = PTCACHE_FILE_PTCACHE; } +PTCacheID BKE_ptcache_id_find(Object *ob, Scene *scene, PointCache *cache) +{ + PTCacheID result = {0}; + + ListBase pidlist; + BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR); + + for (PTCacheID *pid = pidlist.first; pid; pid = pid->next) { + if (pid->cache == cache) { + result = *pid; + break; + } + } + + BLI_freelistN(&pidlist); + + return result; +} + void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis) { PTCacheID *pid; @@ -1715,22 +1735,19 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup BLI_addtail(lb, pid); } - if (scene && (duplis-- > 0) && (ob->transflag & OB_DUPLI)) { - ListBase *lb_dupli_ob; - /* don't update the dupli groups, we only want their pid's */ - if ((lb_dupli_ob = object_duplilist_ex(G.main->eval_ctx, scene, ob, false))) { - DupliObject *dob; - for (dob= lb_dupli_ob->first; dob; dob= dob->next) { - if (dob->ob != ob) { /* avoids recursive loops with dupliframes: bug 22988 */ - ListBase lb_dupli_pid; - BKE_ptcache_ids_from_object(&lb_dupli_pid, dob->ob, scene, duplis); - BLI_movelisttolist(lb, &lb_dupli_pid); - if (lb_dupli_pid.first) - printf("Adding Dupli\n"); - } - } + /* Consider all object in dupli groups to be part of the same object, + * for baking with linking dupligroups. Once we have better overrides + * this can be revisited so users select the local objects directly. */ + if (scene && (duplis-- > 0) && (ob->dup_group)) { + Group *group = ob->dup_group; + Base *base = group->view_layer->object_bases.first; - free_object_duplilist(lb_dupli_ob); /* does restore */ + for (; base; base = base->next) { + if (base->object != ob) { + ListBase lb_dupli_pid; + BKE_ptcache_ids_from_object(&lb_dupli_pid, base->object, scene, duplis); + BLI_movelisttolist(lb, &lb_dupli_pid); + } } } } @@ -3510,13 +3527,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; @@ -3542,6 +3560,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; @@ -3604,7 +3624,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); @@ -3660,7 +3680,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(depsgraph, bmain); if (baker->update_progress) { float progress = ((float)(CFRA - startframe)/(float)(endframe - startframe)); @@ -3715,7 +3735,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) { @@ -3746,7 +3766,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(depsgraph, bmain); } /* TODO: call redraw all windows somehow */ diff --git a/source/blender/blenkernel/intern/property.c b/source/blender/blenkernel/intern/property.c deleted file mode 100644 index b163f623d21..00000000000 --- a/source/blender/blenkernel/intern/property.c +++ /dev/null @@ -1,267 +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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): ton roosendaal - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/blenkernel/intern/property.c - * \ingroup bke - * - * This module deals with bProperty only, - * they are used on blender objects in the game engine - * (where they get converted into C++ classes - CValue and subclasses) - */ - -#include <stdio.h> -#include <stdlib.h> -#include <stddef.h> -#include <string.h> -#include <ctype.h> - -#include "MEM_guardedalloc.h" - -#include "DNA_property_types.h" -#include "DNA_object_types.h" - -#include "BLI_blenlib.h" - -#include "BKE_property.h" - -void BKE_bproperty_free(bProperty *prop) -{ - - if (prop->poin && prop->poin != &prop->data) MEM_freeN(prop->poin); - MEM_freeN(prop); - -} - -void BKE_bproperty_free_list(ListBase *lb) -{ - bProperty *prop; - - while ((prop = BLI_pophead(lb))) { - BKE_bproperty_free(prop); - } -} - -bProperty *BKE_bproperty_copy(const bProperty *prop) -{ - bProperty *propn; - - propn = MEM_dupallocN(prop); - if (prop->poin && prop->poin != &prop->data) { - propn->poin = MEM_dupallocN(prop->poin); - } - else { - propn->poin = &propn->data; - } - - return propn; -} - -void BKE_bproperty_copy_list(ListBase *lbn, const ListBase *lbo) -{ - bProperty *prop, *propn; - BKE_bproperty_free_list(lbn); /* in case we are copying to an object with props */ - prop = lbo->first; - while (prop) { - propn = BKE_bproperty_copy(prop); - BLI_addtail(lbn, propn); - prop = prop->next; - } - - -} - -void BKE_bproperty_init(bProperty *prop) -{ - /* also use when property changes type */ - - if (prop->poin && prop->poin != &prop->data) MEM_freeN(prop->poin); - prop->poin = NULL; - - prop->data = 0; - - switch (prop->type) { - case GPROP_BOOL: - case GPROP_INT: - case GPROP_FLOAT: - case GPROP_TIME: - prop->poin = &prop->data; - break; - case GPROP_STRING: - prop->poin = MEM_callocN(MAX_PROPSTRING, "property string"); - break; - } -} - - -bProperty *BKE_bproperty_new(int type) -{ - bProperty *prop; - - prop = MEM_callocN(sizeof(bProperty), "property"); - prop->type = type; - - BKE_bproperty_init(prop); - - strcpy(prop->name, "prop"); - - return prop; -} - - -bProperty *BKE_bproperty_object_get(Object *ob, const char *name) -{ - return BLI_findstring(&ob->prop, name, offsetof(bProperty, name)); -} - -void BKE_bproperty_object_set(Object *ob, bProperty *propc) -{ - bProperty *prop; - prop = BKE_bproperty_object_get(ob, propc->name); - if (prop) { - BLI_remlink(&ob->prop, prop); - BKE_bproperty_free(prop); - } - BLI_addtail(&ob->prop, BKE_bproperty_copy(propc)); -} - -/* negative: prop is smaller - * positive: prop is larger - */ -#if 0 /* UNUSED */ -int BKE_bproperty_cmp(bProperty *prop, const char *str) -{ -// extern int Gdfra; /* sector.c */ - float fvalue, ftest; - - switch (prop->type) { - case GPROP_BOOL: - if (BLI_strcasecmp(str, "true") == 0) { - if (prop->data == 1) return 0; - else return 1; - } - else if (BLI_strcasecmp(str, "false") == 0) { - if (prop->data == 0) return 0; - else return 1; - } - /* no break, do GPROP_int too! */ - - case GPROP_INT: - return prop->data - atoi(str); - - case GPROP_FLOAT: - case GPROP_TIME: - /* WARNING: untested for GPROP_TIME - * function isn't used currently */ - fvalue = *((float *)&prop->data); - ftest = (float)atof(str); - if (fvalue > ftest) return 1; - else if (fvalue < ftest) return -1; - return 0; - - case GPROP_STRING: - return strcmp(prop->poin, str); - } - - return 0; -} -#endif - -void BKE_bproperty_set(bProperty *prop, const char *str) -{ -// extern int Gdfra; /* sector.c */ - - switch (prop->type) { - case GPROP_BOOL: - if (BLI_strcasecmp(str, "true") == 0) prop->data = 1; - else if (BLI_strcasecmp(str, "false") == 0) prop->data = 0; - else prop->data = (atoi(str) != 0); - break; - case GPROP_INT: - prop->data = atoi(str); - break; - case GPROP_FLOAT: - case GPROP_TIME: - *((float *)&prop->data) = (float)atof(str); - break; - case GPROP_STRING: - strcpy(prop->poin, str); /* TODO - check size? */ - break; - } - -} - -void BKE_bproperty_add(bProperty *prop, const char *str) -{ -// extern int Gdfra; /* sector.c */ - - switch (prop->type) { - case GPROP_BOOL: - case GPROP_INT: - prop->data += atoi(str); - break; - case GPROP_FLOAT: - case GPROP_TIME: - *((float *)&prop->data) += (float)atof(str); - break; - case GPROP_STRING: - /* strcpy(prop->poin, str); */ - break; - } -} - -/* reads value of property, sets it in chars in str */ -void BKE_bproperty_set_valstr(bProperty *prop, char str[MAX_PROPSTRING]) -{ -// extern int Gdfra; /* sector.c */ - - if (str == NULL) return; - - switch (prop->type) { - case GPROP_BOOL: - case GPROP_INT: - sprintf(str, "%d", prop->data); - break; - case GPROP_FLOAT: - case GPROP_TIME: - sprintf(str, "%f", *((float *)&prop->data)); - break; - case GPROP_STRING: - BLI_strncpy(str, prop->poin, MAX_PROPSTRING); - break; - } -} - -#if 0 /* UNUSED */ -void cp_property(bProperty *prop1, bProperty *prop2) -{ - char str[128]; - - BKE_bproperty_set_valstr(prop2, str); - - BKE_bproperty_set(prop1, str); -} -#endif diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c index b8873cca0fb..1c16d57ab12 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" @@ -93,26 +93,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_BEGIN(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_BEGIN(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); @@ -1020,8 +1024,8 @@ RigidBodyOb *BKE_rigidbody_create_object(Scene *scene, Object *ob, short type) rbo->lin_sleep_thresh = 0.4f; /* 0.4 is half of Bullet default */ rbo->ang_sleep_thresh = 0.5f; /* 0.5 is half of Bullet default */ - rbo->lin_damping = 0.04f; /* 0.04 is game engine default */ - rbo->ang_damping = 0.1f; /* 0.1 is game engine default */ + rbo->lin_damping = 0.04f; + rbo->ang_damping = 0.1f; rbo->col_groups = 1; @@ -1133,7 +1137,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) { @@ -1153,8 +1156,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_BEGIN(rbw->constraints, obt) + { if (obt && obt->rigidbody_constraint) { rbc = obt->rigidbody_constraint; if (ELEM(ob, rbc->ob1, rbc->ob2)) { @@ -1162,6 +1165,7 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob) } } } + FOREACH_GROUP_OBJECT_END; } } @@ -1195,20 +1199,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_BEGIN(rbw->group, object) + { + rbw->objects[i] = object; + i++; } + FOREACH_GROUP_OBJECT_END; } static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw) @@ -1231,7 +1237,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(struct Depsgraph *depsgraph, Scene *scene, RigidBodyWorld *rbw, Object *ob, RigidBodyOb *rbo) { float loc[3]; float rot[4]; @@ -1279,7 +1285,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(depsgraph, 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]; @@ -1320,10 +1326,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(struct Depsgraph *depsgraph, Scene *scene, RigidBodyWorld *rbw, bool rebuild) { - GroupObject *go; - /* update world */ if (rebuild) BKE_rigidbody_validate_sim_world(scene, rbw, true); @@ -1336,28 +1340,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_BEGIN(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_BEGIN(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(depsgraph, scene, ob); if (rbo == NULL) { /* Since this object is included in the sim group but doesn't have @@ -1391,65 +1393,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(depsgraph, 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_BEGIN(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(depsgraph, 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_BEGIN(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) @@ -1564,7 +1563,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(struct Depsgraph *depsgraph, Scene *scene, float ctime) { RigidBodyWorld *rbw = scene->rigidbody_world; PointCache *cache; @@ -1576,14 +1575,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(depsgraph, scene, rbw, true); BKE_ptcache_validate(cache, (int)ctime); cache->last_exact = 0; cache->flag &= ~PTCACHE_REDO_NEEDED; @@ -1592,7 +1591,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(struct Depsgraph *depsgraph, Scene *scene, float ctime) { float timestep; RigidBodyWorld *rbw = scene->rigidbody_world; @@ -1630,14 +1629,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(depsgraph, scene, rbw, false); /* calculate how much time elapsed since last step in seconds */ timestep = 1.0f / (float)FPS * (ctime - rbw->ltime) * rbw->time_scale; @@ -1681,8 +1680,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(struct Depsgraph *depsgraph, Scene *scene, float ctime) {} +void BKE_rigidbody_do_simulation(struct Depsgraph *depsgraph, Scene *scene, float ctime) {} #ifdef __GNUC__ # pragma GCC diagnostic pop @@ -1693,35 +1692,35 @@ 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(struct Depsgraph *depsgraph, Scene *scene) { float ctime = BKE_scene_frame_get(scene); - DEG_debug_print_eval_time(__func__, scene->id.name, scene, ctime); + DEG_debug_print_eval_time(depsgraph, __func__, scene->id.name, scene, ctime); /* 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(depsgraph, scene, ctime); } } -void BKE_rigidbody_eval_simulation(EvaluationContext *UNUSED(eval_ctx), +void BKE_rigidbody_eval_simulation(struct Depsgraph *depsgraph, Scene *scene) { float ctime = BKE_scene_frame_get(scene); - DEG_debug_print_eval_time(__func__, scene->id.name, scene, ctime); + DEG_debug_print_eval_time(depsgraph, __func__, scene->id.name, scene, ctime); /* evaluate rigidbody sim */ if (BKE_scene_check_rigidbody_active(scene)) { - BKE_rigidbody_do_simulation(scene, ctime); + BKE_rigidbody_do_simulation(depsgraph, scene, ctime); } } -void BKE_rigidbody_object_sync_transforms(EvaluationContext *UNUSED(eval_ctx), +void BKE_rigidbody_object_sync_transforms(struct Depsgraph *depsgraph, Scene *scene, Object *ob) { RigidBodyWorld *rbw = scene->rigidbody_world; float ctime = BKE_scene_frame_get(scene); - DEG_debug_print_eval_time(__func__, ob->id.name, ob, ctime); + DEG_debug_print_eval_time(depsgraph, __func__, ob->id.name, ob, ctime); /* read values pushed into RBO from sim/cache... */ BKE_rigidbody_sync_transforms(rbw, ob, ctime); } diff --git a/source/blender/blenkernel/intern/sca.c b/source/blender/blenkernel/intern/sca.c deleted file mode 100644 index fb81ed4d47f..00000000000 --- a/source/blender/blenkernel/intern/sca.c +++ /dev/null @@ -1,1179 +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) 2001-2002 by NaN Holding BV. - * All rights reserved. - * - * The Original Code is: all of this file. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - * these all are linked to objects (listbase) - * all data is 'direct data', not Blender lib data. - */ - -/** \file blender/blenkernel/intern/sca.c - * \ingroup bke - */ - - -#include <stdio.h> -#include <string.h> -#include <float.h> - -#include "MEM_guardedalloc.h" - -#include "DNA_controller_types.h" -#include "DNA_sensor_types.h" -#include "DNA_actuator_types.h" -#include "DNA_object_types.h" - -#include "BLI_blenlib.h" -#include "BLI_ghash.h" -#include "BLI_math.h" - -#include "BKE_global.h" -#include "BKE_main.h" -#include "BKE_library.h" -#include "BKE_library_query.h" -#include "BKE_sca.h" - -/* ******************* SENSORS ************************ */ - -void free_sensor(bSensor *sens) -{ - if (sens->links) MEM_freeN(sens->links); - if (sens->data) MEM_freeN(sens->data); - MEM_freeN(sens); - -} - -void free_sensors(ListBase *lb) -{ - bSensor *sens; - - while ((sens = BLI_pophead(lb))) { - free_sensor(sens); - } -} - -bSensor *copy_sensor(bSensor *sens, const int UNUSED(flag)) -{ - bSensor *sensn; - - sensn= MEM_dupallocN(sens); - sensn->flag |= SENS_NEW; - if (sens->data) { - sensn->data= MEM_dupallocN(sens->data); - } - - if (sens->links) sensn->links= MEM_dupallocN(sens->links); - - return sensn; -} - -void copy_sensors(ListBase *lbn, const ListBase *lbo, const int flag) -{ - bSensor *sens, *sensn; - - lbn->first= lbn->last= NULL; - sens= lbo->first; - while (sens) { - sensn= copy_sensor(sens, flag); - BLI_addtail(lbn, sensn); - sens= sens->next; - } -} - -void init_sensor(bSensor *sens) -{ - /* also use when sensor changes type */ - bNearSensor *ns; - bMouseSensor *ms; - bJoystickSensor *js; - bRaySensor *rs; - - if (sens->data) MEM_freeN(sens->data); - sens->data= NULL; - sens->pulse = 0; - - switch (sens->type) { - case SENS_ALWAYS: - sens->pulse = 0; - break; - case SENS_NEAR: - ns=sens->data= MEM_callocN(sizeof(bNearSensor), "nearsens"); - ns->dist= 1.0; - ns->resetdist= 2.0; - break; - case SENS_KEYBOARD: - sens->data= MEM_callocN(sizeof(bKeyboardSensor), "keysens"); - break; - case SENS_PROPERTY: - sens->data= MEM_callocN(sizeof(bPropertySensor), "propsens"); - break; - case SENS_ARMATURE: - sens->data= MEM_callocN(sizeof(bArmatureSensor), "armsens"); - break; - case SENS_ACTUATOR: - sens->data= MEM_callocN(sizeof(bActuatorSensor), "actsens"); - break; - case SENS_DELAY: - sens->data= MEM_callocN(sizeof(bDelaySensor), "delaysens"); - break; - case SENS_MOUSE: - ms=sens->data= MEM_callocN(sizeof(bMouseSensor), "mousesens"); - ms->type= 1; // LEFTMOUSE workaround because Mouse Sensor types enum starts in 1 - break; - case SENS_COLLISION: - sens->data= MEM_callocN(sizeof(bCollisionSensor), "colsens"); - break; - case SENS_RADAR: - sens->data= MEM_callocN(sizeof(bRadarSensor), "radarsens"); - break; - case SENS_RANDOM: - sens->data= MEM_callocN(sizeof(bRandomSensor), "randomsens"); - break; - case SENS_RAY: - sens->data= MEM_callocN(sizeof(bRaySensor), "raysens"); - rs = sens->data; - rs->range = 0.01f; - break; - case SENS_MESSAGE: - sens->data= MEM_callocN(sizeof(bMessageSensor), "messagesens"); - break; - case SENS_JOYSTICK: - sens->data= MEM_callocN(sizeof(bJoystickSensor), "joysticksens"); - js= sens->data; - js->hatf = SENS_JOY_HAT_UP; - js->axis = 1; - js->hat = 1; - break; - default: - ; /* this is very severe... I cannot make any memory for this */ - /* logic brick... */ - } -} - -bSensor *new_sensor(int type) -{ - bSensor *sens; - - sens= MEM_callocN(sizeof(bSensor), "Sensor"); - sens->type= type; - sens->flag= SENS_SHOW; - - init_sensor(sens); - - strcpy(sens->name, "sensor"); -// XXX make_unique_prop_names(sens->name); - - return sens; -} - -/* ******************* CONTROLLERS ************************ */ - -void unlink_controller(bController *cont) -{ - bSensor *sens; - Object *ob; - - /* check for controller pointers in sensors */ - ob= G.main->object.first; - while (ob) { - sens= ob->sensors.first; - while (sens) { - unlink_logicbricks((void **)&cont, (void ***)&(sens->links), &sens->totlinks); - sens= sens->next; - } - ob= ob->id.next; - } -} - -void unlink_controllers(ListBase *lb) -{ - bController *cont; - - for (cont= lb->first; cont; cont= cont->next) - unlink_controller(cont); -} - -void free_controller(bController *cont) -{ - if (cont->links) MEM_freeN(cont->links); - - /* the controller itself */ - if (cont->data) MEM_freeN(cont->data); - MEM_freeN(cont); - -} - -void free_controllers(ListBase *lb) -{ - bController *cont; - - while ((cont = BLI_pophead(lb))) { - if (cont->slinks) - MEM_freeN(cont->slinks); - free_controller(cont); - } -} - -bController *copy_controller(bController *cont, const int UNUSED(flag)) -{ - bController *contn; - - cont->mynew=contn= MEM_dupallocN(cont); - contn->flag |= CONT_NEW; - if (cont->data) { - contn->data= MEM_dupallocN(cont->data); - } - - if (cont->links) contn->links= MEM_dupallocN(cont->links); - contn->slinks= NULL; - contn->totslinks= 0; - - return contn; -} - -void copy_controllers(ListBase *lbn, const ListBase *lbo, const int flag) -{ - bController *cont, *contn; - - lbn->first= lbn->last= NULL; - cont= lbo->first; - while (cont) { - contn= copy_controller(cont, flag); - BLI_addtail(lbn, contn); - cont= cont->next; - } -} - -void init_controller(bController *cont) -{ - /* also use when controller changes type, leave actuators... */ - - if (cont->data) MEM_freeN(cont->data); - cont->data= NULL; - - switch (cont->type) { - case CONT_EXPRESSION: - cont->data= MEM_callocN(sizeof(bExpressionCont), "expcont"); - break; - case CONT_PYTHON: - cont->data= MEM_callocN(sizeof(bPythonCont), "pycont"); - break; - } -} - -bController *new_controller(int type) -{ - bController *cont; - - cont= MEM_callocN(sizeof(bController), "Controller"); - cont->type= type; - cont->flag= CONT_SHOW; - - init_controller(cont); - - strcpy(cont->name, "cont"); -// XXX make_unique_prop_names(cont->name); - - return cont; -} - -/* ******************* ACTUATORS ************************ */ - -void unlink_actuator(bActuator *act) -{ - bController *cont; - Object *ob; - - /* check for actuator pointers in controllers */ - ob= G.main->object.first; - while (ob) { - cont= ob->controllers.first; - while (cont) { - unlink_logicbricks((void **)&act, (void ***)&(cont->links), &cont->totlinks); - cont= cont->next; - } - ob= ob->id.next; - } -} - -void unlink_actuators(ListBase *lb) -{ - bActuator *act; - - for (act= lb->first; act; act= act->next) - unlink_actuator(act); -} - -void free_actuator(bActuator *act) -{ - if (act->data) { - switch (act->type) { - case ACT_ACTION: - case ACT_SHAPEACTION: - { - bActionActuator *aa = (bActionActuator *)act->data; - if (aa->act) - id_us_min((ID *)aa->act); - break; - } - case ACT_SOUND: - { - bSoundActuator *sa = (bSoundActuator *) act->data; - if (sa->sound) - id_us_min((ID *)sa->sound); - break; - } - } - - MEM_freeN(act->data); - } - MEM_freeN(act); -} - -void free_actuators(ListBase *lb) -{ - bActuator *act; - - while ((act = BLI_pophead(lb))) { - free_actuator(act); - } -} - -bActuator *copy_actuator(bActuator *act, const int flag) -{ - bActuator *actn; - - act->mynew=actn= MEM_dupallocN(act); - actn->flag |= ACT_NEW; - if (act->data) { - actn->data= MEM_dupallocN(act->data); - } - - switch (act->type) { - case ACT_ACTION: - case ACT_SHAPEACTION: - { - bActionActuator *aa = (bActionActuator *)act->data; - if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { - id_us_plus((ID *)aa->act); - } - break; - } - case ACT_SOUND: - { - bSoundActuator *sa = (bSoundActuator *)act->data; - if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { - id_us_plus((ID *)sa->sound); - } - break; - } - } - return actn; -} - -void copy_actuators(ListBase *lbn, const ListBase *lbo, const int flag) -{ - bActuator *act, *actn; - - lbn->first= lbn->last= NULL; - act= lbo->first; - while (act) { - actn= copy_actuator(act, flag); - BLI_addtail(lbn, actn); - act= act->next; - } -} - -void init_actuator(bActuator *act) -{ - /* also use when actuator changes type */ - bCameraActuator *ca; - bObjectActuator *oa; - bRandomActuator *ra; - bSoundActuator *sa; - bSteeringActuator *sta; - bArmatureActuator *arma; - bMouseActuator *ma; - bEditObjectActuator *eoa; - - if (act->data) MEM_freeN(act->data); - act->data= NULL; - - switch (act->type) { - case ACT_ACTION: - case ACT_SHAPEACTION: - act->data= MEM_callocN(sizeof(bActionActuator), "actionact"); - break; - case ACT_SOUND: - sa = act->data= MEM_callocN(sizeof(bSoundActuator), "soundact"); - sa->volume = 1.0f; - sa->sound3D.rolloff_factor = 1.0f; - sa->sound3D.reference_distance = 1.0f; - sa->sound3D.max_gain = 1.0f; - sa->sound3D.cone_inner_angle = DEG2RADF(360.0f); - sa->sound3D.cone_outer_angle = DEG2RADF(360.0f); - sa->sound3D.max_distance = FLT_MAX; - break; - case ACT_OBJECT: - act->data= MEM_callocN(sizeof(bObjectActuator), "objectact"); - oa= act->data; - oa->flag= 15; - break; - case ACT_PROPERTY: - act->data= MEM_callocN(sizeof(bPropertyActuator), "propact"); - break; - case ACT_CAMERA: - act->data= MEM_callocN(sizeof(bCameraActuator), "camact"); - ca = act->data; - ca->axis = OB_POSX; - ca->damping = 1.0/32.0; - break; - case ACT_EDIT_OBJECT: - act->data= MEM_callocN(sizeof(bEditObjectActuator), "editobact"); - eoa = act->data; - eoa->upflag= ACT_TRACK_UP_Z; - eoa->trackflag= ACT_TRACK_TRAXIS_Y; - break; - case ACT_CONSTRAINT: - act->data= MEM_callocN(sizeof(bConstraintActuator), "cons act"); - break; - case ACT_SCENE: - act->data= MEM_callocN(sizeof(bSceneActuator), "scene act"); - break; - case ACT_GROUP: - act->data= MEM_callocN(sizeof(bGroupActuator), "group act"); - break; - case ACT_RANDOM: - act->data= MEM_callocN(sizeof(bRandomActuator), "random act"); - ra=act->data; - ra->float_arg_1 = 0.1f; - break; - case ACT_MESSAGE: - act->data= MEM_callocN(sizeof(bMessageActuator), "message act"); - break; - case ACT_GAME: - act->data= MEM_callocN(sizeof(bGameActuator), "game act"); - break; - case ACT_VISIBILITY: - act->data= MEM_callocN(sizeof(bVisibilityActuator), "visibility act"); - break; - case ACT_2DFILTER: - act->data = MEM_callocN(sizeof( bTwoDFilterActuator ), "2d filter act"); - break; - case ACT_PARENT: - act->data = MEM_callocN(sizeof( bParentActuator ), "parent act"); - break; - case ACT_STATE: - act->data = MEM_callocN(sizeof( bStateActuator ), "state act"); - break; - case ACT_ARMATURE: - act->data = MEM_callocN(sizeof( bArmatureActuator ), "armature act"); - arma = act->data; - arma->influence = 1.f; - break; - case ACT_STEERING: - act->data = MEM_callocN(sizeof( bSteeringActuator), "steering act"); - sta = act->data; - sta->acceleration = 3.f; - sta->turnspeed = 120.f; - sta->dist = 1.f; - sta->velocity= 3.f; - sta->flag = ACT_STEERING_AUTOMATICFACING | ACT_STEERING_LOCKZVEL; - sta->facingaxis = 1; - break; - case ACT_MOUSE: - ma = act->data = MEM_callocN(sizeof( bMouseActuator ), "mouse act"); - ma->flag = ACT_MOUSE_VISIBLE|ACT_MOUSE_USE_AXIS_X|ACT_MOUSE_USE_AXIS_Y|ACT_MOUSE_RESET_X|ACT_MOUSE_RESET_Y|ACT_MOUSE_LOCAL_Y; - ma->sensitivity[0] = ma->sensitivity[1] = 2.f; - ma->object_axis[0] = ACT_MOUSE_OBJECT_AXIS_Z; - ma->object_axis[1] = ACT_MOUSE_OBJECT_AXIS_X; - ma->limit_y[0] = DEG2RADF(-90.0f); - ma->limit_y[1] = DEG2RADF(90.0f); - break; - default: - ; /* this is very severe... I cannot make any memory for this */ - /* logic brick... */ - } -} - -bActuator *new_actuator(int type) -{ - bActuator *act; - - act= MEM_callocN(sizeof(bActuator), "Actuator"); - act->type= type; - act->flag= ACT_SHOW; - - init_actuator(act); - - strcpy(act->name, "act"); -// XXX make_unique_prop_names(act->name); - - return act; -} - -/* ******************** GENERAL ******************* */ -void clear_sca_new_poins_ob(Object *ob) -{ - bSensor *sens; - bController *cont; - bActuator *act; - - sens= ob->sensors.first; - while (sens) { - sens->flag &= ~SENS_NEW; - sens= sens->next; - } - cont= ob->controllers.first; - while (cont) { - cont->mynew= NULL; - cont->flag &= ~CONT_NEW; - cont= cont->next; - } - act= ob->actuators.first; - while (act) { - act->mynew= NULL; - act->flag &= ~ACT_NEW; - act= act->next; - } -} - -void clear_sca_new_poins(void) -{ - Object *ob; - - ob= G.main->object.first; - while (ob) { - clear_sca_new_poins_ob(ob); - ob= ob->id.next; - } -} - -void set_sca_new_poins_ob(Object *ob) -{ - bSensor *sens; - bController *cont; - bActuator *act; - int a; - - sens= ob->sensors.first; - while (sens) { - if (sens->flag & SENS_NEW) { - for (a=0; a<sens->totlinks; a++) { - if (sens->links[a] && sens->links[a]->mynew) - sens->links[a] = sens->links[a]->mynew; - } - } - sens= sens->next; - } - - cont= ob->controllers.first; - while (cont) { - if (cont->flag & CONT_NEW) { - for (a=0; a<cont->totlinks; a++) { - if ( cont->links[a] && cont->links[a]->mynew) - cont->links[a] = cont->links[a]->mynew; - } - } - cont= cont->next; - } - - - act= ob->actuators.first; - while (act) { - if (act->flag & ACT_NEW) { - if (act->type==ACT_EDIT_OBJECT) { - bEditObjectActuator *eoa= act->data; - ID_NEW_REMAP(eoa->ob); - } - else if (act->type==ACT_SCENE) { - bSceneActuator *sca= act->data; - ID_NEW_REMAP(sca->camera); - } - else if (act->type==ACT_CAMERA) { - bCameraActuator *ca= act->data; - ID_NEW_REMAP(ca->ob); - } - else if (act->type==ACT_OBJECT) { - bObjectActuator *oa= act->data; - ID_NEW_REMAP(oa->reference); - } - else if (act->type==ACT_MESSAGE) { - bMessageActuator *ma= act->data; - ID_NEW_REMAP(ma->toObject); - } - else if (act->type==ACT_PARENT) { - bParentActuator *para = act->data; - ID_NEW_REMAP(para->ob); - } - else if (act->type==ACT_ARMATURE) { - bArmatureActuator *aa = act->data; - ID_NEW_REMAP(aa->target); - ID_NEW_REMAP(aa->subtarget); - } - else if (act->type==ACT_PROPERTY) { - bPropertyActuator *pa= act->data; - ID_NEW_REMAP(pa->ob); - } - else if (act->type==ACT_STEERING) { - bSteeringActuator *sta = act->data; - ID_NEW_REMAP(sta->navmesh); - ID_NEW_REMAP(sta->target); - } - } - act= act->next; - } -} - - -void set_sca_new_poins(void) -{ - Object *ob; - - ob= G.main->object.first; - while (ob) { - set_sca_new_poins_ob(ob); - ob= ob->id.next; - } -} - -/** - * Try to remap logic links to new object... Very, *very* weak. - */ -/* XXX Logick bricks... I don't have words to say what I think about this behavior. - * They have silent hidden ugly inter-objects dependencies (a sensor can link into any other - * object's controllers, and same between controllers and actuators, without *any* explicit reference - * to data-block involved). - * This is bad, bad, bad!!! - * ...and forces us to add yet another very ugly hack to get remapping with logic bricks working. */ -void BKE_sca_logic_links_remap(Main *bmain, Object *ob_old, Object *ob_new) -{ - if (ob_new == NULL || (ob_old->controllers.first == NULL && ob_old->actuators.first == NULL)) { - /* Nothing to do here... */ - return; - } - - GHash *controllers_map = ob_old->controllers.first ? - BLI_ghash_ptr_new_ex(__func__, BLI_listbase_count(&ob_old->controllers)) : NULL; - GHash *actuators_map = ob_old->actuators.first ? - BLI_ghash_ptr_new_ex(__func__, BLI_listbase_count(&ob_old->actuators)) : NULL; - - /* We try to remap old controllers/actuators to new ones - in a very basic way. */ - for (bController *cont_old = ob_old->controllers.first, *cont_new = ob_new->controllers.first; - cont_old; - cont_old = cont_old->next) - { - bController *cont_new2 = cont_new; - - if (cont_old->mynew != NULL) { - cont_new2 = cont_old->mynew; - if (!(cont_new2 == cont_new || BLI_findindex(&ob_new->controllers, cont_new2) >= 0)) { - cont_new2 = NULL; - } - } - else if (cont_new && cont_old->type != cont_new->type) { - cont_new2 = NULL; - } - - BLI_ghash_insert(controllers_map, cont_old, cont_new2); - - if (cont_new) { - cont_new = cont_new->next; - } - } - - for (bActuator *act_old = ob_old->actuators.first, *act_new = ob_new->actuators.first; - act_old; - act_old = act_old->next) - { - bActuator *act_new2 = act_new; - - if (act_old->mynew != NULL) { - act_new2 = act_old->mynew; - if (!(act_new2 == act_new || BLI_findindex(&ob_new->actuators, act_new2) >= 0)) { - act_new2 = NULL; - } - } - else if (act_new && act_old->type != act_new->type) { - act_new2 = NULL; - } - - BLI_ghash_insert(actuators_map, act_old, act_new2); - - if (act_new) { - act_new = act_new->next; - } - } - - for (Object *ob = bmain->object.first; ob; ob = ob->id.next) { - if (controllers_map != NULL) { - for (bSensor *sens = ob->sensors.first; sens; sens = sens->next) { - for (int a = 0; a < sens->totlinks; a++) { - if (sens->links[a]) { - bController *old_link = sens->links[a]; - bController **new_link_p = (bController **)BLI_ghash_lookup_p(controllers_map, old_link); - - if (new_link_p == NULL) { - /* old_link is *not* in map's keys (i.e. not to any ob_old->controllers), - * which means we ignore it totally here. */ - } - else if (*new_link_p == NULL) { - unlink_logicbricks((void **)&old_link, (void ***)&(sens->links), &sens->totlinks); - a--; - } - else { - sens->links[a] = *new_link_p; - } - } - } - } - } - - if (actuators_map != NULL) { - for (bController *cont = ob->controllers.first; cont; cont = cont->next) { - for (int a = 0; a < cont->totlinks; a++) { - if (cont->links[a]) { - bActuator *old_link = cont->links[a]; - bActuator **new_link_p = (bActuator **)BLI_ghash_lookup_p(actuators_map, old_link); - - if (new_link_p == NULL) { - /* old_link is *not* in map's keys (i.e. not to any ob_old->actuators), - * which means we ignore it totally here. */ - } - else if (*new_link_p == NULL) { - unlink_logicbricks((void **)&old_link, (void ***)&(cont->links), &cont->totlinks); - a--; - } - else { - cont->links[a] = *new_link_p; - } - } - } - } - } - } - - if (controllers_map) { - BLI_ghash_free(controllers_map, NULL, NULL); - } - if (actuators_map) { - BLI_ghash_free(actuators_map, NULL, NULL); - } -} - -/** - * Handle the copying of logic data into a new object, including internal logic links update. - * External links (links between logic bricks of different objects) must be handled separately. - */ -void BKE_sca_logic_copy(Object *ob_new, const Object *ob, const int flag) -{ - copy_sensors(&ob_new->sensors, &ob->sensors, flag); - copy_controllers(&ob_new->controllers, &ob->controllers, flag); - copy_actuators(&ob_new->actuators, &ob->actuators, flag); - - for (bSensor *sens = ob_new->sensors.first; sens; sens = sens->next) { - if (sens->flag & SENS_NEW) { - for (int a = 0; a < sens->totlinks; a++) { - if (sens->links[a] && sens->links[a]->mynew) { - sens->links[a] = sens->links[a]->mynew; - } - } - } - } - - for (bController *cont = ob_new->controllers.first; cont; cont = cont->next) { - if (cont->flag & CONT_NEW) { - for (int a = 0; a < cont->totlinks; a++) { - if (cont->links[a] && cont->links[a]->mynew) { - cont->links[a] = cont->links[a]->mynew; - } - } - } - } -} - -/* ******************** INTERFACE ******************* */ -void sca_move_sensor(bSensor *sens_to_move, Object *ob, int move_up) -{ - bSensor *sens, *tmp; - - int val; - val = move_up ? 1 : 2; - - /* make sure this sensor belongs to this object */ - sens= ob->sensors.first; - while (sens) { - if (sens == sens_to_move) break; - sens= sens->next; - } - if (!sens) return; - - /* move up */ - if (val == 1 && sens->prev) { - for (tmp=sens->prev; tmp; tmp=tmp->prev) { - if (tmp->flag & SENS_VISIBLE) - break; - } - if (tmp) { - BLI_remlink(&ob->sensors, sens); - BLI_insertlinkbefore(&ob->sensors, tmp, sens); - } - } - /* move down */ - else if (val == 2 && sens->next) { - for (tmp=sens->next; tmp; tmp=tmp->next) { - if (tmp->flag & SENS_VISIBLE) - break; - } - if (tmp) { - BLI_remlink(&ob->sensors, sens); - BLI_insertlinkafter(&ob->sensors, tmp, sens); - } - } -} - -void sca_move_controller(bController *cont_to_move, Object *ob, int move_up) -{ - bController *cont, *tmp; - - int val; - val = move_up ? 1 : 2; - - /* make sure this controller belongs to this object */ - cont= ob->controllers.first; - while (cont) { - if (cont == cont_to_move) break; - cont= cont->next; - } - if (!cont) return; - - /* move up */ - if (val == 1 && cont->prev) { - /* locate the controller that has the same state mask but is earlier in the list */ - tmp = cont->prev; - while (tmp) { - if (tmp->state_mask & cont->state_mask) - break; - tmp = tmp->prev; - } - if (tmp) { - BLI_remlink(&ob->controllers, cont); - BLI_insertlinkbefore(&ob->controllers, tmp, cont); - } - } - - /* move down */ - else if (val == 2 && cont->next) { - tmp = cont->next; - while (tmp) { - if (tmp->state_mask & cont->state_mask) - break; - tmp = tmp->next; - } - BLI_remlink(&ob->controllers, cont); - BLI_insertlinkafter(&ob->controllers, tmp, cont); - } -} - -void sca_move_actuator(bActuator *act_to_move, Object *ob, int move_up) -{ - bActuator *act, *tmp; - int val; - - val = move_up ? 1 : 2; - - /* make sure this actuator belongs to this object */ - act= ob->actuators.first; - while (act) { - if (act == act_to_move) break; - act= act->next; - } - if (!act) return; - - /* move up */ - if (val == 1 && act->prev) { - /* locate the first visible actuators before this one */ - for (tmp = act->prev; tmp; tmp=tmp->prev) { - if (tmp->flag & ACT_VISIBLE) - break; - } - if (tmp) { - BLI_remlink(&ob->actuators, act); - BLI_insertlinkbefore(&ob->actuators, tmp, act); - } - } - /* move down */ - else if (val == 2 && act->next) { - /* locate the first visible actuators after this one */ - for (tmp=act->next; tmp; tmp=tmp->next) { - if (tmp->flag & ACT_VISIBLE) - break; - } - if (tmp) { - BLI_remlink(&ob->actuators, act); - BLI_insertlinkafter(&ob->actuators, tmp, act); - } - } -} - -void link_logicbricks(void **poin, void ***ppoin, short *tot, short size) -{ - void **old_links= NULL; - - int ibrick; - - /* check if the bricks are already linked */ - for (ibrick=0; ibrick < *tot; ibrick++) { - if ((*ppoin)[ibrick] == *poin) - return; - } - - if (*ppoin) { - old_links= *ppoin; - - (*tot) ++; - *ppoin = MEM_callocN((*tot)*size, "new link"); - - for (ibrick=0; ibrick < *(tot) - 1; ibrick++) { - (*ppoin)[ibrick] = old_links[ibrick]; - } - (*ppoin)[ibrick] = *poin; - - if (old_links) MEM_freeN(old_links); - } - else { - (*tot) = 1; - *ppoin = MEM_callocN((*tot)*size, "new link"); - (*ppoin)[0] = *poin; - } -} - -void unlink_logicbricks(void **poin, void ***ppoin, short *tot) -{ - int ibrick, removed; - - removed= 0; - for (ibrick=0; ibrick < *tot; ibrick++) { - if (removed) (*ppoin)[ibrick - removed] = (*ppoin)[ibrick]; - else if ((*ppoin)[ibrick] == *poin) removed = 1; - } - - if (removed) { - (*tot) --; - - if (*tot == 0) { - MEM_freeN(*ppoin); - (*ppoin)= NULL; - } - return; - } -} - -void BKE_sca_sensors_id_loop(ListBase *senslist, SCASensorIDFunc func, void *userdata) -{ - bSensor *sensor; - - for (sensor = senslist->first; sensor; sensor = sensor->next) { - func(sensor, (ID **)&sensor->ob, userdata, IDWALK_CB_NOP); - - switch (sensor->type) { - case SENS_TOUCH: /* DEPRECATED */ - { - bTouchSensor *ts = sensor->data; - func(sensor, (ID **)&ts->ma, userdata, IDWALK_CB_NOP); - break; - } - case SENS_MESSAGE: - { - bMessageSensor *ms = sensor->data; - func(sensor, (ID **)&ms->fromObject, userdata, IDWALK_CB_NOP); - break; - } - case SENS_ALWAYS: - case SENS_NEAR: - case SENS_KEYBOARD: - case SENS_PROPERTY: - case SENS_MOUSE: - case SENS_COLLISION: - case SENS_RADAR: - case SENS_RANDOM: - case SENS_RAY: - case SENS_JOYSTICK: - case SENS_ACTUATOR: - case SENS_DELAY: - case SENS_ARMATURE: - default: - break; - } - } -} - -void BKE_sca_controllers_id_loop(ListBase *contlist, SCAControllerIDFunc func, void *userdata) -{ - bController *controller; - - for (controller = contlist->first; controller; controller = controller->next) { - switch (controller->type) { - case CONT_PYTHON: - { - bPythonCont *pc = controller->data; - func(controller, (ID **)&pc->text, userdata, IDWALK_CB_NOP); - break; - } - case CONT_LOGIC_AND: - case CONT_LOGIC_OR: - case CONT_EXPRESSION: - case CONT_LOGIC_NAND: - case CONT_LOGIC_NOR: - case CONT_LOGIC_XOR: - case CONT_LOGIC_XNOR: - default: - break; - } - } -} - -void BKE_sca_actuators_id_loop(ListBase *actlist, SCAActuatorIDFunc func, void *userdata) -{ - bActuator *actuator; - - for (actuator = actlist->first; actuator; actuator = actuator->next) { - func(actuator, (ID **)&actuator->ob, userdata, IDWALK_CB_NOP); - - switch (actuator->type) { - case ACT_ADD_OBJECT: /* DEPRECATED */ - { - bAddObjectActuator *aoa = actuator->data; - func(actuator, (ID **)&aoa->ob, userdata, IDWALK_CB_NOP); - break; - } - case ACT_ACTION: - { - bActionActuator *aa = actuator->data; - func(actuator, (ID **)&aa->act, userdata, IDWALK_CB_NOP); - break; - } - case ACT_SOUND: - { - bSoundActuator *sa = actuator->data; - func(actuator, (ID **)&sa->sound, userdata, IDWALK_CB_NOP); - break; - } - case ACT_EDIT_OBJECT: - { - bEditObjectActuator *eoa = actuator->data; - func(actuator, (ID **)&eoa->ob, userdata, IDWALK_CB_NOP); - func(actuator, (ID **)&eoa->me, userdata, IDWALK_CB_NOP); - break; - } - case ACT_SCENE: - { - bSceneActuator *sa = actuator->data; - func(actuator, (ID **)&sa->scene, userdata, IDWALK_CB_NOP); - func(actuator, (ID **)&sa->camera, userdata, IDWALK_CB_NOP); - break; - } - case ACT_PROPERTY: - { - bPropertyActuator *pa = actuator->data; - func(actuator, (ID **)&pa->ob, userdata, IDWALK_CB_NOP); - break; - } - case ACT_OBJECT: - { - bObjectActuator *oa = actuator->data; - func(actuator, (ID **)&oa->reference, userdata, IDWALK_CB_NOP); - break; - } - case ACT_CAMERA: - { - bCameraActuator *ca = actuator->data; - func(actuator, (ID **)&ca->ob, userdata, IDWALK_CB_NOP); - break; - } - case ACT_MESSAGE: - { - bMessageActuator *ma = actuator->data; - func(actuator, (ID **)&ma->toObject, userdata, IDWALK_CB_NOP); - break; - } - case ACT_2DFILTER: - { - bTwoDFilterActuator *tdfa = actuator->data; - func(actuator, (ID **)&tdfa->text, userdata, IDWALK_CB_NOP); - break; - } - case ACT_PARENT: - { - bParentActuator *pa = actuator->data; - func(actuator, (ID **)&pa->ob, userdata, IDWALK_CB_NOP); - break; - } - case ACT_ARMATURE: - { - bArmatureActuator *aa = actuator->data; - func(actuator, (ID **)&aa->target, userdata, IDWALK_CB_NOP); - func(actuator, (ID **)&aa->subtarget, userdata, IDWALK_CB_NOP); - break; - } - case ACT_STEERING: - { - bSteeringActuator *sa = actuator->data; - func(actuator, (ID **)&sa->target, userdata, IDWALK_CB_NOP); - func(actuator, (ID **)&sa->navmesh, userdata, IDWALK_CB_NOP); - break; - } - /* Note: some types seems to be non-implemented? ACT_LAMP, ACT_MATERIAL... */ - case ACT_LAMP: - case ACT_MATERIAL: - case ACT_END_OBJECT: /* DEPRECATED */ - case ACT_CONSTRAINT: - case ACT_GROUP: - case ACT_RANDOM: - case ACT_GAME: - case ACT_VISIBILITY: - case ACT_SHAPEACTION: - case ACT_STATE: - case ACT_MOUSE: - default: - break; - } - } -} - -const char *sca_state_name_get(Object *ob, short bit) -{ - bController *cont; - unsigned int mask; - - mask = (1<<bit); - cont = ob->controllers.first; - while (cont) { - if (cont->state_mask & mask) { - return cont->name; - } - cont = cont->next; - } - return NULL; -} - diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 9b3299bdbc5..a11c7320da5 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" @@ -105,8 +111,9 @@ #include "bmesh.h" -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_BLENDER_WORKBENCH = "BLENDER_WORKBENCH"; const char *RE_engine_id_CYCLES = "CYCLES"; void free_avicodecdata(AviCodecData *acd) @@ -234,25 +241,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->obedit = NULL; - sce_dst->stats = NULL; + sce_dst->depsgraph_hash = 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)); @@ -267,17 +286,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); @@ -331,20 +339,16 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type) /* TODO this should/could most likely be replaced by call to more generic code at some point... * But for now, let's keep it well isolated here. */ if (type == SCE_COPY_EMPTY) { - 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->r.views = rv; sce_copy->unit = sce->unit; sce_copy->physics_settings = sce->physics_settings; - sce_copy->gm = sce->gm; sce_copy->audio = sce->audio; if (sce->id.properties) @@ -399,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); @@ -452,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); @@ -490,27 +490,15 @@ 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); BKE_toolsettings_free(sce->toolsettings); 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); @@ -519,6 +507,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) @@ -533,7 +552,7 @@ void BKE_scene_init(Scene *sce) sce->lay = sce->layact = 1; - sce->r.mode = R_GAMMA | R_OSA | R_SHADOW | R_SSS | R_ENVMAP | R_RAYTRACE; + sce->r.mode = R_OSA; sce->r.cfra = 1; sce->r.sfra = 1; sce->r.efra = 250; @@ -544,8 +563,6 @@ void BKE_scene_init(Scene *sce) sce->r.yasp = 1; sce->r.tilex = 256; sce->r.tiley = 256; - sce->r.mblur_samples = 1; - sce->r.filtertype = R_FILTER_MITCH; sce->r.size = 50; sce->r.im_format.planes = R_IMF_PLANES_RGBA; @@ -561,8 +578,6 @@ void BKE_scene_init(Scene *sce) sce->r.blurfac = 0.5; sce->r.frs_sec = 24; sce->r.frs_sec_base = 1; - sce->r.edgeint = 10; - sce->r.ocres = 128; /* OCIO_TODO: for forwards compatibility only, so if no tonecurve are used, * images would look in the same way as in current blender @@ -571,18 +586,9 @@ void BKE_scene_init(Scene *sce) */ sce->r.color_mgt_flag |= R_COLOR_MANAGEMENT; - sce->r.gauss = 1.0; - - /* deprecated but keep for upwards compat */ - sce->r.postgamma = 1.0; - sce->r.posthue = 0.0; - sce->r.postsat = 1.0; - - sce->r.bake_mode = 1; /* prevent to include render stuff here */ + sce->r.bake_mode = 0; sce->r.bake_filter = 16; - sce->r.bake_osa = 5; sce->r.bake_flag = R_BAKE_CLEAR; - sce->r.bake_normal_space = R_BAKE_SPACE_TANGENT; sce->r.bake_samples = 256; sce->r.bake_biasdist = 0.001; @@ -610,7 +616,6 @@ void BKE_scene_init(Scene *sce) sce->r.fg_stamp[3] = 1.0f; sce->r.bg_stamp[0] = sce->r.bg_stamp[1] = sce->r.bg_stamp[2] = 0.0f; sce->r.bg_stamp[3] = 0.25f; - sce->r.raytrace_options = R_RAYTRACE_USE_INSTANCES; sce->r.seq_prev_type = OB_SOLID; sce->r.seq_rend_type = OB_SOLID; @@ -620,8 +625,6 @@ void BKE_scene_init(Scene *sce) sce->r.simplify_subsurf = 6; sce->r.simplify_particles = 1.0f; - sce->r.simplify_shadowsamples = 16; - sce->r.simplify_aosss = 1.0f; sce->r.border.xmin = 0.0f; sce->r.border.ymin = 0.0f; @@ -655,21 +658,6 @@ void BKE_scene_init(Scene *sce) sce->toolsettings->snap_node_mode = SCE_SNAP_MODE_GRID; - sce->toolsettings->skgen_resolution = 100; - sce->toolsettings->skgen_threshold_internal = 0.01f; - sce->toolsettings->skgen_threshold_external = 0.01f; - sce->toolsettings->skgen_angle_limit = 45.0f; - sce->toolsettings->skgen_length_ratio = 1.3f; - sce->toolsettings->skgen_length_limit = 1.5f; - sce->toolsettings->skgen_correlation_limit = 0.98f; - sce->toolsettings->skgen_symmetry_limit = 0.1f; - sce->toolsettings->skgen_postpro = SKGEN_SMOOTH; - sce->toolsettings->skgen_postpro_passes = 1; - sce->toolsettings->skgen_options = SKGEN_FILTER_INTERNAL | SKGEN_FILTER_EXTERNAL | SKGEN_FILTER_SMART | SKGEN_HARMONIC | SKGEN_SUB_CORRELATION | SKGEN_STICK_TO_EMBEDDING; - sce->toolsettings->skgen_subdivisions[0] = SKGEN_SUB_CORRELATION; - sce->toolsettings->skgen_subdivisions[1] = SKGEN_SUB_LENGTH; - sce->toolsettings->skgen_subdivisions[2] = SKGEN_SUB_ANGLE; - sce->toolsettings->curve_paint_settings.curve_type = CU_BEZIER; sce->toolsettings->curve_paint_settings.flag |= CURVE_PAINT_FLAG_CORNERS_DETECT; sce->toolsettings->curve_paint_settings.error_threshold = 8; @@ -723,12 +711,13 @@ 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)); + BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_EEVEE, sizeof(sce->r.engine)); sce->audio.distance_model = 2.0f; sce->audio.doppler_factor = 1.0f; sce->audio.speed_of_sound = 343.3f; sce->audio.volume = 1.0f; + sce->audio.flag = AUDIO_SYNC; BLI_strncpy(sce->r.pic, U.renderdir, sizeof(sce->r.pic)); @@ -736,7 +725,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); @@ -747,59 +735,6 @@ void BKE_scene_init(Scene *sce) srv = sce->r.views.last; BLI_strncpy(srv->suffix, STEREO_RIGHT_SUFFIX, sizeof(srv->suffix)); - /* game data */ - sce->gm.stereoflag = STEREO_NOSTEREO; - sce->gm.stereomode = STEREO_ANAGLYPH; - sce->gm.eyeseparation = 0.10; - - sce->gm.dome.angle = 180; - sce->gm.dome.mode = DOME_FISHEYE; - sce->gm.dome.res = 4; - sce->gm.dome.resbuf = 1.0f; - sce->gm.dome.tilt = 0; - - sce->gm.xplay = 640; - sce->gm.yplay = 480; - sce->gm.freqplay = 60; - sce->gm.depth = 32; - - sce->gm.gravity = 9.8f; - sce->gm.physicsEngine = WOPHY_BULLET; - sce->gm.mode = 32; //XXX ugly harcoding, still not sure we should drop mode. 32 == 1 << 5 == use_occlusion_culling - sce->gm.occlusionRes = 128; - sce->gm.ticrate = 60; - sce->gm.maxlogicstep = 5; - sce->gm.physubstep = 1; - sce->gm.maxphystep = 5; - sce->gm.lineardeactthreshold = 0.8f; - sce->gm.angulardeactthreshold = 1.0f; - sce->gm.deactivationtime = 0.0f; - - sce->gm.flag = GAME_DISPLAY_LISTS; - sce->gm.matmode = GAME_MAT_MULTITEX; - - sce->gm.obstacleSimulation = OBSTSIMULATION_NONE; - sce->gm.levelHeight = 2.f; - - sce->gm.recastData.cellsize = 0.3f; - sce->gm.recastData.cellheight = 0.2f; - sce->gm.recastData.agentmaxslope = M_PI_4; - sce->gm.recastData.agentmaxclimb = 0.9f; - sce->gm.recastData.agentheight = 2.0f; - sce->gm.recastData.agentradius = 0.6f; - sce->gm.recastData.edgemaxlen = 12.0f; - sce->gm.recastData.edgemaxerror = 1.3f; - sce->gm.recastData.regionminsize = 8.f; - sce->gm.recastData.regionmergesize = 20.f; - sce->gm.recastData.vertsperpoly = 6; - sce->gm.recastData.detailsampledist = 6.0f; - sce->gm.recastData.detailsamplemaxerror = 1.0f; - - sce->gm.lodflag = SCE_LOD_USE_HYST; - sce->gm.scehysteresis = 10; - - sce->gm.exitkey = 218; // Blender key code for ESC - BKE_sound_create_scene(sce); /* color management */ @@ -869,6 +804,22 @@ 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; + + sce->orientation_index_custom = -1; + + /* 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) @@ -884,75 +835,64 @@ 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; - /* deselect objects (for dataselect) */ for (ob = bmain->object.first; ob; ob = ob->id.next) ob->flag &= ~(SELECT | OB_FROMGROUP); /* 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_BEGIN(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) */ } @@ -972,8 +912,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( + Depsgraph *depsgraph, SceneBaseIter *iter, + Scene **scene, int val, Base **base, Object **ob) { bool run_again = true; @@ -991,17 +932,21 @@ 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 = (depsgraph) ? + DEG_get_evaluated_view_layer(depsgraph) : + BKE_view_layer_context_active_PLACEHOLDER(*scene); + *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_default_render((*scene)); + if (view_layer_set->object_bases.first) { + *base = view_layer_set->object_bases.first; *ob = (*base)->object; iter->phase = F_SCENE; break; @@ -1020,8 +965,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_default_render((*scene)); + if (view_layer_set->object_bases.first) { + *base = view_layer_set->object_bases.first; *ob = (*base)->object; break; } @@ -1036,12 +982,12 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter, } else { if (iter->phase != F_DUPLI) { - if ( (*base)->object->transflag & OB_DUPLI) { + if (depsgraph && (*base)->object->transflag & OB_DUPLI) { /* groups cannot be duplicated for mballs yet, * this enters eternal loop because of * makeDispListMBall getting called inside of group_duplilist */ if ((*base)->object->dup_group == NULL) { - iter->duplilist = object_duplilist_ex(eval_ctx, (*scene), (*base)->object, false); + iter->duplilist = object_duplilist_ex(depsgraph, (*scene), (*base)->object, false); iter->dupob = iter->duplilist->first; @@ -1055,7 +1001,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; @@ -1074,7 +1020,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. */ @@ -1099,13 +1045,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; } @@ -1207,49 +1155,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 */ @@ -1301,109 +1214,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 @@ -1419,7 +1229,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) { @@ -1432,368 +1242,20 @@ 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 - - int num_threads; - - /* 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_EVAL) { - 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) -{ - double finish_time; - - if ((G.debug & G_DEBUG_DEPSGRAPH_EVAL) == 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(); - int total_objects = 0; - - for (int i = 0; i < state->num_threads; 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_EVAL) { - 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(); - state.num_threads = tot_thread; - } - -#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_EVAL) { - 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; - ScrArea *area; - for (area = screen->areabase.first; area != NULL; area = area->next) { + const bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook); + Scene *scene = window->scene; + RenderEngineType *type = RE_engines_find(scene->r.engine); + + if (type->draw_engine || !type->render_to_view) { + continue; + } + + for (ScrArea *area = screen->areabase.first; area != NULL; area = area->next) { View3D *v3d = area->spacedata.first; if (area->spacetype != SPACE_VIEW3D) { continue; @@ -1806,7 +1268,10 @@ static bool check_rendered_viewport_visible(Main *bmain) return false; } -static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene) +/* TODO(campbell): shouldn't we be able to use 'DEG_get_view_layer' here? + * Currently this is NULL on load, so don't. */ +static void prepare_mesh_for_viewport_render( + Main *bmain, const ViewLayer *view_layer) { /* This is needed to prepare mesh to be used by the render * engine from the viewport rendering. We do loading here @@ -1817,7 +1282,7 @@ static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene) * call loading of the edit data for the mesh objects. */ - Object *obedit = scene->obedit; + Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer); if (obedit) { Mesh *mesh = obedit->data; if ((obedit->type == OB_MESH) && @@ -1831,318 +1296,84 @@ static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene) (&(struct BMeshToMeshParams){ .calc_object_remap = true, })); - 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) +/* TODO(sergey): This actually should become view_layer_graph or so. + * Same applies to update_for_newframe. + */ +void BKE_scene_graph_update_tagged(Depsgraph *depsgraph, + Main *bmain) { - 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 */ - prepare_mesh_for_viewport_render(bmain, scene); + Scene *scene = DEG_get_input_scene(depsgraph); + ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph); - /* 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] + /* TODO(sergey): Some functions here are changing global state, + * for example, clearing update tags from bmain. */ - 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) */ - 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. + /* (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, view_layer); + /* 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. */ -#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); - + DEG_evaluate_on_refresh(depsgraph); + /* Update sound system animation (TODO, move to depsgraph). */ + BKE_sound_update_scene(bmain, scene); /* 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) +void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph, + Main *bmain) { - 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); + Scene *scene = DEG_get_input_scene(depsgraph); + ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph); - /* 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 + /* 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(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 */ @@ -2209,37 +1440,34 @@ int get_render_child_particle_number(const RenderData *r, int num, bool for_rend } } -int get_render_shadow_samples(const RenderData *r, int samples) -{ - if ((r->mode & R_SIMPLIFY) && samples > 0) - return min_ii(r->simplify_shadowsamples, samples); - else - return samples; -} - -float get_render_aosss_error(const RenderData *r, float error) -{ - if (r->mode & R_SIMPLIFY) - return ((1.0f - r->simplify_aosss) * 10.0f + 1.0f) * error; - else - 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_default_render((*sce_iter)); + base = (Base *)view_layer_set->object_bases.first; + if (base) { return base; } @@ -2249,58 +1477,67 @@ Base *_setlooper_base_step(Scene **sce_iter, Base *base) return NULL; } -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); -} - 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); } -bool BKE_scene_use_world_space_shading(Scene *scene) -{ - const RenderEngineType *type = RE_engines_find(scene->r.engine); - 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); } -bool BKE_scene_uses_blender_internal(const Scene *scene) +bool BKE_scene_uses_blender_eevee(const Scene *scene) { - return STREQ(scene->r.engine, RE_engine_id_BLENDER_RENDER); + return STREQ(scene->r.engine, RE_engine_id_BLENDER_EEVEE); } -bool BKE_scene_uses_blender_game(const Scene *scene) +bool BKE_scene_uses_cycles(const Scene *scene) { - return STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME); + return STREQ(scene->r.engine, RE_engine_id_CYCLES); } -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; } } @@ -2669,3 +1906,146 @@ 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(scene, view_layer, DAG_EVAL_VIEWPORT); + /* TODO(sergey): Would be cool to avoid string format print, + * but is a bit tricky because we can't know in advance whether + * we will ever enable debug messages for this depsgraph. + */ + char name[1024]; + BLI_snprintf(name, sizeof(name), "%s :: %s", scene->id.name, view_layer->name); + DEG_debug_name_set(*depsgraph_ptr, name); + } + depsgraph = *depsgraph_ptr; + } + else { + depsgraph = BLI_ghash_lookup(scene->depsgraph_hash, &key); + } + return depsgraph; +} + +/* -------------------------------------------------------------------- */ +/** \name Scene Orientation + * \{ */ + +void BKE_scene_transform_orientation_remove( + Scene *scene, TransformOrientation *orientation) +{ + const int orientation_index = BKE_scene_transform_orientation_get_index(scene, orientation); + if (scene->orientation_index_custom == orientation_index) { + /* could also use orientation_index-- */ + scene->orientation_type = V3D_MANIP_GLOBAL; + scene->orientation_index_custom = -1; + } + BLI_freelinkN(&scene->transform_spaces, orientation); +} + +TransformOrientation *BKE_scene_transform_orientation_find( + const Scene *scene, const int index) +{ + return BLI_findlink(&scene->transform_spaces, index); +} + +/** + * \return the index that \a orientation has within \a scene's transform-orientation list or -1 if not found. + */ +int BKE_scene_transform_orientation_get_index( + const Scene *scene, const TransformOrientation *orientation) +{ + return BLI_findindex(&scene->transform_spaces, orientation); +} + +/** \} */ diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c index 2b1cf0a01df..ece68884f5c 100644 --- a/source/blender/blenkernel/intern/screen.c +++ b/source/blender/blenkernel/intern/screen.c @@ -39,19 +39,20 @@ #include "MEM_guardedalloc.h" -#include "GPU_compositing.h" - #include "DNA_scene_types.h" #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 ************** */ @@ -179,9 +180,11 @@ ARegion *BKE_area_region_copy(SpaceType *st, ARegion *ar) BLI_listbase_clear(&newar->panels_category); BLI_listbase_clear(&newar->panels_category_active); BLI_listbase_clear(&newar->ui_lists); - newar->swinid = 0; + newar->visible = 0; + newar->manipulator_map = NULL; newar->regiontimer = NULL; newar->headerstr = NULL; + newar->draw_buffer = NULL; /* use optional regiondata callback */ if (ar->regiondata) { @@ -289,6 +292,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 +378,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); @@ -353,6 +398,7 @@ void BKE_screen_area_free(ScrArea *sa) for (ar = sa->regionbase.first; ar; ar = ar->next) BKE_area_region_free(st, ar); + MEM_SAFE_FREE(sa->global); BLI_freelistN(&sa->regionbase); BKE_spacedata_freelist(&sa->spacedata); @@ -360,10 +406,21 @@ void BKE_screen_area_free(ScrArea *sa) BLI_freelistN(&sa->actionzones); } +void BKE_screen_area_map_free(ScrAreaMap *area_map) +{ + for (ScrArea *area = area_map->areabase.first, *area_next; area; area = area_next) { + area_next = area->next; + BKE_screen_area_free(area); + } + + BLI_freelistN(&area_map->vertbase); + BLI_freelistN(&area_map->edgebase); + BLI_freelistN(&area_map->areabase); +} + /** Free (or release) any data used by this screen (does not free the screen itself). */ void BKE_screen_free(bScreen *sc) { - ScrArea *sa, *san; ARegion *ar; /* No animdata here. */ @@ -372,15 +429,10 @@ void BKE_screen_free(bScreen *sc) BKE_area_region_free(NULL, ar); BLI_freelistN(&sc->regionbase); - - for (sa = sc->areabase.first; sa; sa = san) { - san = sa->next; - BKE_screen_area_free(sa); - } - - BLI_freelistN(&sc->vertbase); - BLI_freelistN(&sc->edgebase); - BLI_freelistN(&sc->areabase); + + BKE_screen_area_map_free(AREAMAP_FROM_SCREEN(sc)); + + BKE_previewimg_free(&sc->preview); /* Region and timer are freed by the window manager. */ MEM_SAFE_FREE(sc->tool_tip); @@ -405,6 +457,174 @@ unsigned int BKE_screen_visible_layers(bScreen *screen, Scene *scene) return layer; } + +/* ***************** Screen edges & verts ***************** */ + +ScrEdge *BKE_screen_find_edge(bScreen *sc, ScrVert *v1, ScrVert *v2) +{ + ScrEdge *se; + + BKE_screen_sort_scrvert(&v1, &v2); + for (se = sc->edgebase.first; se; se = se->next) { + if (se->v1 == v1 && se->v2 == v2) { + return se; + } + } + + return NULL; +} + +void BKE_screen_sort_scrvert(ScrVert **v1, ScrVert **v2) +{ + ScrVert *tmp; + + if (*v1 > *v2) { + tmp = *v1; + *v1 = *v2; + *v2 = tmp; + } +} + +void BKE_screen_remove_double_scrverts(bScreen *sc) +{ + ScrVert *v1, *verg; + ScrEdge *se; + ScrArea *sa; + + verg = sc->vertbase.first; + while (verg) { + if (verg->newv == NULL) { /* !!! */ + v1 = verg->next; + while (v1) { + if (v1->newv == NULL) { /* !?! */ + if (v1->vec.x == verg->vec.x && v1->vec.y == verg->vec.y) { + /* printf("doublevert\n"); */ + v1->newv = verg; + } + } + v1 = v1->next; + } + } + verg = verg->next; + } + + /* replace pointers in edges and faces */ + se = sc->edgebase.first; + while (se) { + if (se->v1->newv) se->v1 = se->v1->newv; + if (se->v2->newv) se->v2 = se->v2->newv; + /* edges changed: so.... */ + BKE_screen_sort_scrvert(&(se->v1), &(se->v2)); + se = se->next; + } + sa = sc->areabase.first; + while (sa) { + if (sa->v1->newv) sa->v1 = sa->v1->newv; + if (sa->v2->newv) sa->v2 = sa->v2->newv; + if (sa->v3->newv) sa->v3 = sa->v3->newv; + if (sa->v4->newv) sa->v4 = sa->v4->newv; + sa = sa->next; + } + + /* remove */ + verg = sc->vertbase.first; + while (verg) { + v1 = verg->next; + if (verg->newv) { + BLI_remlink(&sc->vertbase, verg); + MEM_freeN(verg); + } + verg = v1; + } + +} + +void BKE_screen_remove_double_scredges(bScreen *sc) +{ + ScrEdge *verg, *se, *sn; + + /* compare */ + verg = sc->edgebase.first; + while (verg) { + se = verg->next; + while (se) { + sn = se->next; + if (verg->v1 == se->v1 && verg->v2 == se->v2) { + BLI_remlink(&sc->edgebase, se); + MEM_freeN(se); + } + se = sn; + } + verg = verg->next; + } +} + +void BKE_screen_remove_unused_scredges(bScreen *sc) +{ + ScrEdge *se, *sen; + ScrArea *sa; + int a = 0; + + /* sets flags when edge is used in area */ + sa = sc->areabase.first; + while (sa) { + se = BKE_screen_find_edge(sc, sa->v1, sa->v2); + if (se == NULL) printf("error: area %d edge 1 doesn't exist\n", a); + else se->flag = 1; + se = BKE_screen_find_edge(sc, sa->v2, sa->v3); + if (se == NULL) printf("error: area %d edge 2 doesn't exist\n", a); + else se->flag = 1; + se = BKE_screen_find_edge(sc, sa->v3, sa->v4); + if (se == NULL) printf("error: area %d edge 3 doesn't exist\n", a); + else se->flag = 1; + se = BKE_screen_find_edge(sc, sa->v4, sa->v1); + if (se == NULL) printf("error: area %d edge 4 doesn't exist\n", a); + else se->flag = 1; + sa = sa->next; + a++; + } + se = sc->edgebase.first; + while (se) { + sen = se->next; + if (se->flag == 0) { + BLI_remlink(&sc->edgebase, se); + MEM_freeN(se); + } + else { + se->flag = 0; + } + se = sen; + } +} + +void BKE_screen_remove_unused_scrverts(bScreen *sc) +{ + ScrVert *sv, *svn; + ScrEdge *se; + + /* we assume edges are ok */ + + se = sc->edgebase.first; + while (se) { + se->v1->flag = 1; + se->v2->flag = 1; + se = se->next; + } + + sv = sc->vertbase.first; + while (sv) { + svn = sv->next; + if (sv->flag == 0) { + BLI_remlink(&sc->vertbase, sv); + MEM_freeN(sv); + } + else { + sv->flag = 0; + } + sv = svn; + } +} + /* ***************** Utilities ********************** */ /* Find a region of the specified type from the given area */ @@ -583,7 +803,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,56 +812,7 @@ 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); - } - } - } -} - -void BKE_screen_view3d_main_sync(ListBase *screen_lb, Scene *scene) -{ - bScreen *sc; - ScrArea *sa; - SpaceLink *sl; - - /* 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 (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); - } - } + BKE_screen_view3d_sync(v3d, scene); } } } @@ -665,25 +836,12 @@ float BKE_screen_view3d_zoom_from_fac(float zoomfac) return ((sqrtf(4.0f * zoomfac) - (float)M_SQRT2) * 50.0f); } -void BKE_screen_gpu_fx_validate(GPUFXSettings *fx_settings) +bool BKE_screen_is_fullscreen_area(const bScreen *screen) { - /* currently we use DOF from the camera _only_, - * so we never allocate this, only copy from the Camera */ -#if 0 - if ((fx_settings->dof == NULL) && - (fx_settings->fx_flag & GPU_FX_FLAG_DOF)) - { - GPUDOFSettings *fx_dof; - fx_dof = fx_settings->dof = MEM_callocN(sizeof(GPUDOFSettings), __func__); - } -#endif - - if ((fx_settings->ssao == NULL) && - (fx_settings->fx_flag & GPU_FX_FLAG_SSAO)) - { - GPUSSAOSettings *fx_ssao; - fx_ssao = fx_settings->ssao = MEM_callocN(sizeof(GPUSSAOSettings), __func__); + return ELEM(screen->state, SCREENMAXIMIZED, SCREENFULL); +} - GPU_fx_compositor_init_ssao_settings(fx_ssao); - } +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 0cc151c3645..a282f535df6 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,9 @@ #include "BKE_library.h" #include "BKE_idprop.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + #include "RNA_access.h" #include "RE_pipeline.h" @@ -89,8 +92,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 */ @@ -588,17 +593,16 @@ void BKE_sequencer_pixel_from_sequencer_space_v4(struct Scene *scene, float pixe /*********************** sequencer pipeline functions *************************/ void BKE_sequencer_new_render_data( - EvaluationContext *eval_ctx, Main *bmain, Scene *scene, int rectx, int recty, - int preview_render_size, + int preview_render_size, int for_render, SeqRenderData *r_context) { - r_context->eval_ctx = eval_ctx; r_context->bmain = bmain; r_context->scene = scene; r_context->rectx = rectx; r_context->recty = recty; r_context->preview_render_size = preview_render_size; + r_context->for_render = for_render; r_context->motion_blur_samples = 0; r_context->motion_blur_shutter = 0; r_context->skip_cache = false; @@ -2031,9 +2035,10 @@ void BKE_sequencer_proxy_rebuild(SeqIndexBuildContext *context, short *stop, sho /* fail safe code */ BKE_sequencer_new_render_data( - bmain->eval_ctx, bmain, context->scene, + bmain, context->scene, (scene->r.size * (float) scene->r.xsch) / 100.0f + 0.5f, (scene->r.size * (float) scene->r.ysch) / 100.0f + 0.5f, 100, + false, &render_context); render_context.skip_cache = true; @@ -2753,17 +2758,12 @@ static ImBuf *seq_render_effect_strip_impl( if (seq->flag & SEQ_USE_EFFECT_DEFAULT_FADE) { sh.get_default_fac(seq, cfra, &fac, &facf); - - if ((scene->r.mode & R_FIELDS) == 0) - facf = fac; + facf = fac; } else { fcu = id_data_find_fcurve(&scene->id, seq, &RNA_Sequence, "effect_fader", 0, NULL); if (fcu) { fac = facf = evaluate_fcurve(fcu, cfra); - if (scene->r.mode & R_FIELDS) { - facf = evaluate_fcurve(fcu, cfra + 0.5f); - } } else { fac = facf = seq->effect_fader; @@ -3268,6 +3268,11 @@ 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 view layer for the strip. */ + ViewLayer *view_layer = BKE_view_layer_default_render(scene); + /* Depsgraph will be NULL when doing rendering. */ + Depsgraph *depsgraph = NULL; + orig_data.scemode = scene->r.scemode; orig_data.cfra = scene->r.cfra; orig_data.subframe = scene->r.subframe; @@ -3323,12 +3328,16 @@ 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); + depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true); + BKE_scene_graph_update_for_newframe(depsgraph, context->bmain); 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, + depsgraph, scene, + context->scene->r.seq_prev_type, + camera, width, height, IB_rect, + draw_flags, scene->r.alphamode, context->gpu_samples, viewname, - context->gpu_fx, context->gpu_offscreen, err_out); + context->gpu_offscreen, err_out); if (ibuf == NULL) { fprintf(stderr, "seq_render_scene_strip failed to get opengl buffer: %s\n", err_out); } @@ -3349,12 +3358,11 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq * When rendering from command line renderer is called from main thread, in this * case it's always safe to render scene here */ - if (!is_thread_main || is_rendering == false || is_background || context->eval_ctx->mode == DAG_EVAL_RENDER) { + if (!is_thread_main || is_rendering == false || is_background || context->for_render) { if (re == NULL) re = RE_NewSceneRender(scene); - BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay); - RE_BlenderFrame(re, context->bmain, scene, NULL, camera, scene->lay, frame, false); + RE_BlenderFrame(re, context->bmain, scene, view_layer, camera, scene->lay, frame, false); /* restore previous state after it was toggled on & off by RE_BlenderFrame */ G.is_rendering = is_rendering; @@ -3412,8 +3420,8 @@ finally: scene->r.cfra = orig_data.cfra; scene->r.subframe = orig_data.subframe; - if (is_frame_update) { - BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay); + if (is_frame_update && (depsgraph != NULL)) { + BKE_scene_graph_update_for_newframe(depsgraph, context->bmain); } #ifdef DURIAN_CAMERA_SWITCH diff --git a/source/blender/blenkernel/intern/sketch.c b/source/blender/blenkernel/intern/sketch.c deleted file mode 100644 index 6f5c264f658..00000000000 --- a/source/blender/blenkernel/intern/sketch.c +++ /dev/null @@ -1,555 +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. - * - * Contributor(s): none yet. - * - * ***** END GPL LICENSE BLOCK ***** - */ - -/** \file blender/blenkernel/intern/sketch.c - * \ingroup bke - */ - - -#include <string.h> -#include <math.h> -#include <float.h> - -#include "MEM_guardedalloc.h" - -#include "BLI_blenlib.h" -#include "BLI_math.h" -#include "BLI_utildefines.h" - -#include "BKE_sketch.h" - - -#include "DNA_userdef_types.h" - -void freeSketch(SK_Sketch *sketch) -{ - SK_Stroke *stk, *next; - - for (stk = sketch->strokes.first; stk; stk = next) { - next = stk->next; - - sk_freeStroke(stk); - } - - MEM_freeN(sketch); -} - -SK_Sketch *createSketch(void) -{ - SK_Sketch *sketch; - - sketch = MEM_callocN(sizeof(SK_Sketch), "SK_Sketch"); - - sketch->active_stroke = NULL; - sketch->gesture = NULL; - - BLI_listbase_clear(&sketch->strokes); - - return sketch; -} - -void sk_initPoint(SK_Point *pt, SK_DrawData *dd, const float no[3]) -{ - if (no) { - normalize_v3_v3(pt->no, no); - } - else { - pt->no[0] = 0.0f; - pt->no[1] = 0.0f; - pt->no[2] = 1.0f; - } - pt->p2d[0] = dd->mval[0]; - pt->p2d[1] = dd->mval[1]; - - pt->size = 0.0f; - pt->type = PT_CONTINUOUS; - pt->mode = PT_SNAP; - /* more init code here */ -} - -void sk_copyPoint(SK_Point *dst, SK_Point *src) -{ - memcpy(dst, src, sizeof(SK_Point)); -} - -void sk_allocStrokeBuffer(SK_Stroke *stk) -{ - stk->points = MEM_callocN(sizeof(SK_Point) * stk->buf_size, "SK_Point buffer"); -} - -void sk_freeStroke(SK_Stroke *stk) -{ - MEM_freeN(stk->points); - MEM_freeN(stk); -} - -SK_Stroke *sk_createStroke(void) -{ - SK_Stroke *stk; - - stk = MEM_callocN(sizeof(SK_Stroke), "SK_Stroke"); - - stk->selected = 0; - stk->nb_points = 0; - stk->buf_size = SK_Stroke_BUFFER_INIT_SIZE; - - sk_allocStrokeBuffer(stk); - - return stk; -} - -void sk_shrinkStrokeBuffer(SK_Stroke *stk) -{ - if (stk->nb_points < stk->buf_size) { - SK_Point *old_points = stk->points; - - stk->buf_size = stk->nb_points; - - sk_allocStrokeBuffer(stk); - - memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points); - - MEM_freeN(old_points); - } -} - -void sk_growStrokeBuffer(SK_Stroke *stk) -{ - if (stk->nb_points == stk->buf_size) { - SK_Point *old_points = stk->points; - - stk->buf_size *= 2; - - sk_allocStrokeBuffer(stk); - - memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points); - - MEM_freeN(old_points); - } -} - -void sk_growStrokeBufferN(SK_Stroke *stk, int n) -{ - if (stk->nb_points + n > stk->buf_size) { - SK_Point *old_points = stk->points; - - while (stk->nb_points + n > stk->buf_size) { - stk->buf_size *= 2; - } - - sk_allocStrokeBuffer(stk); - - memcpy(stk->points, old_points, sizeof(SK_Point) * stk->nb_points); - - MEM_freeN(old_points); - } -} - - -void sk_replaceStrokePoint(SK_Stroke *stk, SK_Point *pt, int n) -{ - memcpy(stk->points + n, pt, sizeof(SK_Point)); -} - -void sk_insertStrokePoint(SK_Stroke *stk, SK_Point *pt, int n) -{ - int size = stk->nb_points - n; - - sk_growStrokeBuffer(stk); - - memmove(stk->points + n + 1, stk->points + n, size * sizeof(SK_Point)); - - memcpy(stk->points + n, pt, sizeof(SK_Point)); - - stk->nb_points++; -} - -void sk_appendStrokePoint(SK_Stroke *stk, SK_Point *pt) -{ - sk_growStrokeBuffer(stk); - - memcpy(stk->points + stk->nb_points, pt, sizeof(SK_Point)); - - stk->nb_points++; -} - -void sk_insertStrokePoints(SK_Stroke *stk, SK_Point *pts, int len, int start, int end) -{ - int size = end - start; - - sk_growStrokeBufferN(stk, len - size); - - if (len != size) { - int tail_size = stk->nb_points - end; - - memmove(stk->points + start + len, stk->points + end, tail_size * sizeof(SK_Point)); - } - - memcpy(stk->points + start, pts, len * sizeof(SK_Point)); - - stk->nb_points += len - size; -} - -void sk_trimStroke(SK_Stroke *stk, int start, int end) -{ - int size = end - start + 1; - - if (start > 0) { - memmove(stk->points, stk->points + start, size * sizeof(SK_Point)); - } - - stk->nb_points = size; -} - -void sk_straightenStroke(SK_Stroke *stk, int start, int end, float p_start[3], float p_end[3]) -{ - SK_Point pt1, pt2; - SK_Point *prev, *next; - float delta_p[3]; - int i, total; - - total = end - start; - - sub_v3_v3v3(delta_p, p_end, p_start); - - prev = stk->points + start; - next = stk->points + end; - - copy_v3_v3(pt1.p, p_start); - copy_v3_v3(pt1.no, prev->no); - pt1.mode = prev->mode; - pt1.type = prev->type; - - copy_v3_v3(pt2.p, p_end); - copy_v3_v3(pt2.no, next->no); - pt2.mode = next->mode; - pt2.type = next->type; - - sk_insertStrokePoint(stk, &pt1, start + 1); /* insert after start */ - sk_insertStrokePoint(stk, &pt2, end + 1); /* insert before end (since end was pushed back already) */ - - for (i = 1; i < total; i++) { - float delta = (float)i / (float)total; - float *p = stk->points[start + 1 + i].p; - - mul_v3_v3fl(p, delta_p, delta); - add_v3_v3(p, p_start); - } -} - -void sk_polygonizeStroke(SK_Stroke *stk, int start, int end) -{ - int offset; - int i; - - /* find first exact points outside of range */ - for (; start > 0; start--) { - if (stk->points[start].type == PT_EXACT) { - break; - } - } - - for (; end < stk->nb_points - 1; end++) { - if (stk->points[end].type == PT_EXACT) { - break; - } - } - - offset = start + 1; - - for (i = start + 1; i < end; i++) { - if (stk->points[i].type == PT_EXACT) { - if (offset != i) { - memcpy(stk->points + offset, stk->points + i, sizeof(SK_Point)); - } - - offset++; - } - } - - /* some points were removes, move end of array */ - if (offset < end) { - int size = stk->nb_points - end; - memmove(stk->points + offset, stk->points + end, size * sizeof(SK_Point)); - stk->nb_points = offset + size; - } -} - -void sk_flattenStroke(SK_Stroke *stk, int start, int end) -{ - float normal[3], distance[3]; - float limit; - int i, total; - - total = end - start + 1; - - copy_v3_v3(normal, stk->points[start].no); - - sub_v3_v3v3(distance, stk->points[end].p, stk->points[start].p); - project_v3_v3v3(normal, distance, normal); - limit = normalize_v3(normal); - - for (i = 1; i < total - 1; i++) { - float d = limit * i / total; - float offset[3]; - float *p = stk->points[start + i].p; - - sub_v3_v3v3(distance, p, stk->points[start].p); - project_v3_v3v3(distance, distance, normal); - - copy_v3_v3(offset, normal); - mul_v3_fl(offset, d); - - sub_v3_v3(p, distance); - add_v3_v3(p, offset); - } -} - -void sk_removeStroke(SK_Sketch *sketch, SK_Stroke *stk) -{ - if (sketch->active_stroke == stk) { - sketch->active_stroke = NULL; - } - - BLI_remlink(&sketch->strokes, stk); - sk_freeStroke(stk); -} - -void sk_reverseStroke(SK_Stroke *stk) -{ - SK_Point *old_points = stk->points; - int i = 0; - - sk_allocStrokeBuffer(stk); - - for (i = 0; i < stk->nb_points; i++) { - sk_copyPoint(stk->points + i, old_points + stk->nb_points - 1 - i); - } - - MEM_freeN(old_points); -} - - -/* Ramer-Douglas-Peucker algorithm for line simplification */ -void sk_filterStroke(SK_Stroke *stk, int start, int end) -{ - SK_Point *old_points = stk->points; - int nb_points = stk->nb_points; - char *marked = NULL; - char work; - int i; - - if (start == -1) { - start = 0; - end = stk->nb_points - 1; - } - - sk_allocStrokeBuffer(stk); - stk->nb_points = 0; - - /* adding points before range */ - for (i = 0; i < start; i++) { - sk_appendStrokePoint(stk, old_points + i); - } - - marked = MEM_callocN(nb_points, "marked array"); - marked[start] = 1; - marked[end] = 1; - - work = 1; - - /* while still reducing */ - while (work) { - int ls, le; - work = 0; - - ls = start; - le = start + 1; - - /* while not over interval */ - while (ls < end) { - int max_i = 0; - short v1[2]; - float max_dist = 16; /* more than 4 pixels */ - - /* find the next marked point */ - while (marked[le] == 0) { - le++; - } - - /* perpendicular vector to ls-le */ - v1[1] = old_points[le].p2d[0] - old_points[ls].p2d[0]; - v1[0] = old_points[ls].p2d[1] - old_points[le].p2d[1]; - - - for (i = ls + 1; i < le; i++) { - float mul; - float dist; - short v2[2]; - - v2[0] = old_points[i].p2d[0] - old_points[ls].p2d[0]; - v2[1] = old_points[i].p2d[1] - old_points[ls].p2d[1]; - - if (v2[0] == 0 && v2[1] == 0) { - continue; - } - - mul = (float)(v1[0] * v2[0] + v1[1] * v2[1]) / (float)(v2[0] * v2[0] + v2[1] * v2[1]); - - dist = mul * mul * (v2[0] * v2[0] + v2[1] * v2[1]); - - if (dist > max_dist) { - max_dist = dist; - max_i = i; - } - } - - if (max_i != 0) { - work = 1; - marked[max_i] = 1; - } - - ls = le; - le = ls + 1; - } - } - - - /* adding points after range */ - for (i = start; i <= end; i++) { - if (marked[i]) { - sk_appendStrokePoint(stk, old_points + i); - } - } - - MEM_freeN(marked); - - /* adding points after range */ - for (i = end + 1; i < nb_points; i++) { - sk_appendStrokePoint(stk, old_points + i); - } - - MEM_freeN(old_points); - - sk_shrinkStrokeBuffer(stk); -} - - -void sk_filterLastContinuousStroke(SK_Stroke *stk) -{ - int start, end; - - end = stk->nb_points - 1; - - for (start = end - 1; start > 0 && stk->points[start].type == PT_CONTINUOUS; start--) { - /* nothing to do here*/ - } - - if (end - start > 1) { - sk_filterStroke(stk, start, end); - } -} - -SK_Point *sk_lastStrokePoint(SK_Stroke *stk) -{ - SK_Point *pt = NULL; - - if (stk->nb_points > 0) { - pt = stk->points + (stk->nb_points - 1); - } - - return pt; -} - -void sk_endContinuousStroke(SK_Stroke *stk) -{ - stk->points[stk->nb_points - 1].type = PT_EXACT; -} - -void sk_updateNextPoint(SK_Sketch *sketch, SK_Stroke *stk) -{ - if (stk) { - memcpy(&(sketch->next_point), &(stk->points[stk->nb_points - 1]), sizeof(SK_Point)); - } -} - -int sk_stroke_filtermval(SK_DrawData *dd) -{ - int retval = 0; - if (ABS(dd->mval[0] - dd->previous_mval[0]) + ABS(dd->mval[1] - dd->previous_mval[1]) > U.gp_manhattendist) { - retval = 1; - } - - return retval; -} - -void sk_initDrawData(SK_DrawData *dd, const int mval[2]) -{ - dd->mval[0] = mval[0]; - dd->mval[1] = mval[1]; - dd->previous_mval[0] = -1; - dd->previous_mval[1] = -1; - dd->type = PT_EXACT; -} - - -void sk_deleteSelectedStrokes(SK_Sketch *sketch) -{ - SK_Stroke *stk, *next; - - for (stk = sketch->strokes.first; stk; stk = next) { - next = stk->next; - - if (stk->selected == 1) { - sk_removeStroke(sketch, stk); - } - } -} - -void sk_selectAllSketch(SK_Sketch *sketch, int mode) -{ - SK_Stroke *stk = NULL; - - if (mode == -1) { - for (stk = sketch->strokes.first; stk; stk = stk->next) { - stk->selected = 0; - } - } - else if (mode == 0) { - for (stk = sketch->strokes.first; stk; stk = stk->next) { - stk->selected = 1; - } - } - else if (mode == 1) { - int selected = 1; - - for (stk = sketch->strokes.first; stk; stk = stk->next) { - selected &= stk->selected; - } - - selected ^= 1; - - for (stk = sketch->strokes.first; stk; stk = stk->next) { - stk->selected = selected; - } - } -} diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index 0ea4007c95f..f99bd773ebc 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -82,6 +82,9 @@ #include "BKE_smoke.h" #include "BKE_texture.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + #include "RE_shader_ext.h" #include "GPU_glew.h" @@ -125,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), struct Depsgraph *UNUSED(depsgraph), 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 */ @@ -694,16 +697,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; @@ -2104,7 +2107,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(struct Depsgraph *depsgraph, Scene *scene, Object *ob, SmokeDomainSettings *sds, float dt) { Object **flowobjs = NULL; EmissionMap *emaps = NULL; @@ -2211,7 +2214,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(depsgraph, scene, collob, true, 5, BKE_scene_frame_get(scene), eModifierType_Smoke); BLI_mutex_unlock(&object_update_lock); /* apply flow */ @@ -2523,12 +2526,12 @@ static void update_effectors_task_cb( } } -static void update_effectors(Scene *scene, Object *ob, SmokeDomainSettings *sds, float UNUSED(dt)) +static void update_effectors(struct Depsgraph *depsgraph, 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(depsgraph, scene, ob, NULL, sds->effector_weights, true); if (effectors) { // precalculate wind forces @@ -2558,7 +2561,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(struct Depsgraph *depsgraph, Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh *domain_dm, float fps) { SmokeDomainSettings *sds = smd->domain; /* stability values copied from wturbulence.cpp */ @@ -2628,11 +2631,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(depsgraph, 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(depsgraph, 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); } } @@ -2725,7 +2728,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, struct Depsgraph *depsgraph, Scene *scene, Object *ob, DerivedMesh *dm) { if ((smd->type & MOD_SMOKE_TYPE_FLOW)) { @@ -2846,11 +2850,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(depsgraph, 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, DEG_get_evaluated_view_layer(depsgraph)); if (sds->wt && sds->total_cells > 1) { smoke_turbulence_step(sds->wt, sds->fluid); @@ -2867,13 +2871,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, struct Depsgraph *depsgraph, 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, depsgraph, scene, ob, dm); if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain) BLI_rw_mutex_unlock(smd->domain->fluid_mutex); @@ -2988,7 +2993,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]; @@ -2996,7 +3001,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 c3527af90ca..0af400796a4 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,9 @@ variables on the UI for now #include "BKE_mesh.h" #include "BKE_scene.h" +#include "DEG_depsgraph.h" +#include "DEG_depsgraph_query.h" + #include "PIL_time.h" /* callbacks for errors and interrupts and some goo */ @@ -512,35 +516,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 +553,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); - } - } - } } @@ -979,29 +966,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*/ @@ -1546,12 +1525,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(struct Depsgraph *depsgraph, 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(depsgraph, scene, ob, NULL, sb->effector_weights, true); _scan_for_ext_spring_forces(scene, ob, timenow, 0, sb->totspring, do_effector); pdEndEffectors(&do_effector); } @@ -1563,7 +1542,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(struct Depsgraph *depsgraph, Scene *scene, struct Object *ob, float timenow, int totsprings, int *UNUSED(ptr_to_break_func(void))) { ListBase *do_effector = NULL; ListBase threads; @@ -1571,7 +1550,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(depsgraph, 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); @@ -2229,7 +2208,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(struct Depsgraph *depsgraph, 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) @@ -2245,7 +2224,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(DEG_get_evaluated_view_layer(depsgraph), 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)); @@ -2254,10 +2233,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(depsgraph, 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(depsgraph, scene, ob, NULL, sb->effector_weights, true); if (do_deflector) { float defforce[3]; @@ -2274,11 +2253,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(struct Depsgraph *depsgraph, 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(depsgraph, scene, ob, forcetime, timenow); return; } else { @@ -2309,7 +2288,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(DEG_get_evaluated_view_layer(depsgraph), 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)); @@ -2317,9 +2296,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(depsgraph, 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(depsgraph, scene, ob, NULL, ob->soft->effector_weights, true); if (do_deflector) { float defforce[3]; @@ -3506,7 +3485,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(struct Depsgraph *depsgraph, Scene *scene, Object *ob, SoftBody *sb, float dtime) { /* the simulator */ float forcetime; @@ -3520,11 +3499,13 @@ 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); + ViewLayer *view_layer = DEG_get_evaluated_view_layer(depsgraph); + + ccd_update_deflector_hash(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(view_layer, sb->collision_group)) { + ccd_build_deflector_hash(view_layer, sb->collision_group, ob, sb->scratch->colliderhash); } sb->scratch->needstobuildcollider=0; } @@ -3554,12 +3535,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(depsgraph, 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(depsgraph, scene, ob, forcetime, timedone/dtime); softbody_apply_forces(ob, forcetime, 2, &err, mid_flags); softbody_apply_goalsnap(ob); @@ -3640,7 +3621,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(struct Depsgraph *depsgraph, Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], int numVerts) { SoftBody *sb= ob->soft; PointCache *cache; @@ -3648,7 +3629,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; @@ -3717,7 +3697,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); @@ -3757,7 +3737,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(depsgraph, 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..ed23078a9d8 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -77,12 +77,6 @@ # include "BLI_array.h" #endif -#include "GPU_draw.h" -#include "GPU_glew.h" -#include "GPU_buffers.h" -#include "GPU_shader.h" -#include "GPU_basic_shader.h" - #include "CCGSubSurf.h" #ifdef WITH_OPENSUBDIV @@ -1775,47 +1769,7 @@ static void ccgDM_foreachMappedLoop( } } -static void ccgDM_drawVerts(DerivedMesh *dm) -{ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; - CCGSubSurf *ss = ccgdm->ss; - int edgeSize = ccgSubSurf_getEdgeSize(ss); - int gridSize = ccgSubSurf_getGridSize(ss); - CCGVertIterator vi; - CCGEdgeIterator ei; - CCGFaceIterator fi; - - glBegin(GL_POINTS); - for (ccgSubSurf_initVertIterator(ss, &vi); !ccgVertIterator_isStopped(&vi); ccgVertIterator_next(&vi)) { - CCGVert *v = ccgVertIterator_getCurrent(&vi); - glVertex3fv(ccgSubSurf_getVertData(ss, v)); - } - - for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) { - CCGEdge *e = ccgEdgeIterator_getCurrent(&ei); - int x; - - for (x = 1; x < edgeSize - 1; x++) - glVertex3fv(ccgSubSurf_getEdgeData(ss, e, x)); - } - - for (ccgSubSurf_initFaceIterator(ss, &fi); !ccgFaceIterator_isStopped(&fi); ccgFaceIterator_next(&fi)) { - CCGFace *f = ccgFaceIterator_getCurrent(&fi); - int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f); - - glVertex3fv(ccgSubSurf_getFaceCenterData(f)); - for (S = 0; S < numVerts; S++) - for (x = 1; x < gridSize - 1; x++) - glVertex3fv(ccgSubSurf_getFaceGridEdgeData(ss, f, S, x)); - for (S = 0; S < numVerts; S++) - for (y = 1; y < gridSize - 1; y++) - for (x = 1; x < gridSize - 1; x++) - glVertex3fv(ccgSubSurf_getFaceGridData(ss, f, S, x, y)); - } - glEnd(); -} - -static void ccgdm_pbvh_update(CCGDerivedMesh *ccgdm) +static void UNUSED_FUNCTION(ccgdm_pbvh_update)(CCGDerivedMesh *ccgdm) { if (ccgdm->pbvh && ccgDM_use_grid_pbvh(ccgdm)) { CCGFace **faces; @@ -1830,2179 +1784,6 @@ static void ccgdm_pbvh_update(CCGDerivedMesh *ccgdm) } } -static void ccgDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdges) -{ - GPUDrawObject *gdo; - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; - -#ifdef WITH_OPENSUBDIV - if (ccgdm->useGpuBackend) { - /* TODO(sergey): We currently only support all edges drawing. */ - if (ccgSubSurf_prepareGLMesh(ccgdm->ss, true, -1)) { - ccgSubSurf_drawGLMesh(ccgdm->ss, false, -1, -1); - } - return; - } -#endif - - ccgdm_pbvh_update(ccgdm); - -/* old debug feature for edges, unsupported for now */ -#if 0 - int useAging = 0; - - if (!(G.f & G_BACKBUFSEL)) { - CCGSubSurf *ss = ccgdm->ss; - ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL); - - /* it needs some way to upload this to VBO now */ - if (useAging) { - int ageCol = 255 - ccgSubSurf_getEdgeAge(ss, e) * 4; - glColor3ub(0, ageCol > 0 ? ageCol : 0, 0); - } - } -#endif - - 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 - gdo->totinterior) * 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, gdo->tot_loose_edge_drawn * 2); - } - } - - if (gdo->edges && ccgdm->drawInteriorEdges) { - GPU_buffer_draw_elements(gdo->edges, GL_LINES, gdo->interior_offset * 2, gdo->totinterior * 2); - } - GPU_buffers_unbind(); -} - -static void ccgDM_drawLooseEdges(DerivedMesh *dm) -{ - int start; - int count; - -#ifdef WITH_OPENSUBDIV - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; - if (ccgdm->useGpuBackend) { - /* TODO(sergey): Needs implementation. */ - return; - } -#endif - - GPU_edge_setup(dm); - - start = (dm->drawObject->loose_edge_offset * 2); - count = (dm->drawObject->interior_offset - dm->drawObject->loose_edge_offset) * 2; - - if (count) { - GPU_buffer_draw_elements(dm->drawObject->edges, GL_LINES, start, count); - } - - GPU_buffers_unbind(); -} - -static void ccgDM_NormalFast(float *a, float *b, float *c, float *d, float no[3]) -{ - float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2]; - float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2]; - - no[0] = b_dY * a_cZ - b_dZ * a_cY; - no[1] = b_dZ * a_cX - b_dX * a_cZ; - no[2] = b_dX * a_cY - b_dY * a_cX; - - normalize_v3(no); -} - - -static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d) -{ - float a_cX = c[0] - a[0], a_cY = c[1] - a[1], a_cZ = c[2] - a[2]; - float b_dX = d[0] - b[0], b_dY = d[1] - b[1], b_dZ = d[2] - b[2]; - float no[3]; - - no[0] = b_dY * a_cZ - b_dZ * a_cY; - 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 */ - glNormal3fv(no); -} - -/* Only used by non-editmesh types */ -static void ccgDM_buffer_copy_normal( - DerivedMesh *dm, short *varray) -{ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; - CCGSubSurf *ss = ccgdm->ss; - CCGKey key; - const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL); - int gridSize = ccgSubSurf_getGridSize(ss); - int gridFaces = gridSize - 1; - DMFlagMat *faceFlags = ccgdm->faceFlags; - int i, totface = ccgSubSurf_getNumFaces(ss); - int shademodel; - int start = 0; - - /* we are in sculpt mode, disable loop normals (since they won't get updated) */ - if (ccgdm->pbvh) - lnors = NULL; - - CCG_key_top_level(&key, ss); - - for (i = 0; i < totface; i++) { - CCGFace *f = ccgdm->faceMap[i].face; - int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f); - int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f)); - const float (*ln)[3] = NULL; - - if (faceFlags) { - shademodel = (lnors || (faceFlags[index].flag & ME_SMOOTH)) ? GL_SMOOTH : GL_FLAT; - } - else { - shademodel = GL_SMOOTH; - } - - if (lnors) { - ln = lnors; - lnors += gridFaces * gridFaces * numVerts * 4; - } - - for (S = 0; S < numVerts; S++) { - CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S); - - if (ln) { - /* Can't use quad strips here... */ - for (y = 0; y < gridFaces; y ++) { - for (x = 0; x < gridFaces; x ++) { - normal_float_to_short_v3(&varray[start + 0], ln[0]); - normal_float_to_short_v3(&varray[start + 4], ln[3]); - normal_float_to_short_v3(&varray[start + 8], ln[2]); - normal_float_to_short_v3(&varray[start + 12], ln[1]); - - start += 16; - ln += 4; - } - } - } - else if (shademodel == GL_SMOOTH) { - for (y = 0; y < gridFaces; y ++) { - for (x = 0; x < gridFaces; x ++) { - float *a = CCG_grid_elem_no(&key, faceGridData, x, y ); - float *b = CCG_grid_elem_no(&key, faceGridData, x + 1, y); - float *c = CCG_grid_elem_no(&key, faceGridData, x + 1, y + 1); - float *d = CCG_grid_elem_no(&key, faceGridData, x, y + 1); - - normal_float_to_short_v3(&varray[start], a); - normal_float_to_short_v3(&varray[start + 4], b); - normal_float_to_short_v3(&varray[start + 8], c); - normal_float_to_short_v3(&varray[start + 12], d); - - start += 16; - } - } - } - else { - for (y = 0; y < gridFaces; y ++) { - for (x = 0; x < gridFaces; x ++) { - float f_no[3]; - short f_no_s[3]; - - float *a = CCG_grid_elem_co(&key, faceGridData, x, y ); - float *b = CCG_grid_elem_co(&key, faceGridData, x + 1, y ); - float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1); - float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1); - - ccgDM_NormalFast(a, b, c, d, f_no); - normal_float_to_short_v3(f_no_s, f_no); - - copy_v3_v3_short(&varray[start], f_no_s); - copy_v3_v3_short(&varray[start + 4], f_no_s); - copy_v3_v3_short(&varray[start + 8], f_no_s); - copy_v3_v3_short(&varray[start + 12], f_no_s); - - start += 16; - } - } - } - } - } -} - -typedef struct FaceCount { - unsigned int i_visible; - unsigned int i_hidden; - unsigned int i_tri_visible; - unsigned int i_tri_hidden; -} FaceCount; - - -/* Only used by non-editmesh types */ -static void ccgDM_buffer_copy_triangles( - DerivedMesh *dm, unsigned int *varray, - const int *mat_orig_to_new) -{ - GPUBufferMaterial *gpumat, *gpumaterials = dm->drawObject->materials; - const int gpu_totmat = dm->drawObject->totmaterial; - const short dm_totmat = dm->totmat; - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; - CCGSubSurf *ss = ccgdm->ss; - CCGKey key; - int gridSize = ccgSubSurf_getGridSize(ss); - int gridFaces = gridSize - 1; - DMFlagMat *faceFlags = ccgdm->faceFlags; - int i, totface = ccgSubSurf_getNumFaces(ss); - short mat_nr = -1; - int start; - int totloops = 0; - FaceCount *fc = MEM_mallocN(sizeof(*fc) * gpu_totmat, "gpumaterial.facecount"); - - CCG_key_top_level(&key, ss); - - for (i = 0; i < gpu_totmat; i++) { - fc[i].i_visible = 0; - fc[i].i_tri_visible = 0; - fc[i].i_hidden = gpumaterials[i].totpolys - 1; - fc[i].i_tri_hidden = gpumaterials[i].totelements - 1; - } - - for (i = 0; i < totface; i++) { - CCGFace *f = ccgdm->faceMap[i].face; - int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f); - int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f)); - bool is_hidden; - int mati; - - if (faceFlags) { - mat_nr = ME_MAT_NR_TEST(faceFlags[index].mat_nr, dm_totmat); - is_hidden = (faceFlags[index].flag & ME_HIDE) != 0; - } - else { - mat_nr = 0; - is_hidden = false; - } - mati = mat_orig_to_new[mat_nr]; - gpumat = dm->drawObject->materials + mati; - - if (is_hidden) { - for (S = 0; S < numVerts; S++) { - for (y = 0; y < gridFaces; y++) { - for (x = 0; x < gridFaces; x++) { - start = gpumat->start + fc[mati].i_tri_hidden; - - varray[start--] = totloops; - varray[start--] = totloops + 2; - varray[start--] = totloops + 3; - - varray[start--] = totloops; - varray[start--] = totloops + 1; - varray[start--] = totloops + 2; - - fc[mati].i_tri_hidden -= 6; - - totloops += 4; - } - } - } - gpumat->polys[fc[mati].i_hidden--] = i; - } - else { - for (S = 0; S < numVerts; S++) { - for (y = 0; y < gridFaces; y++) { - for (x = 0; x < gridFaces; x++) { - start = gpumat->start + fc[mati].i_tri_visible; - - varray[start++] = totloops + 3; - varray[start++] = totloops + 2; - varray[start++] = totloops; - - varray[start++] = totloops + 2; - varray[start++] = totloops + 1; - varray[start++] = totloops; - - fc[mati].i_tri_visible += 6; - - totloops += 4; - } - } - } - gpumat->polys[fc[mati].i_visible++] = i; - } - } - - /* set the visible polygons */ - for (i = 0; i < gpu_totmat; i++) { - gpumaterials[i].totvisiblepolys = fc[i].i_visible; - } - - MEM_freeN(fc); -} - - -/* Only used by non-editmesh types */ -static void ccgDM_buffer_copy_vertex( - DerivedMesh *dm, void *varray_p) -{ - float *varray = varray_p; - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; - CCGSubSurf *ss = ccgdm->ss; - CCGKey key; - int gridSize = ccgSubSurf_getGridSize(ss); - int gridFaces = gridSize - 1; - int i, totface = ccgSubSurf_getNumFaces(ss); - int totedge = ccgSubSurf_getNumEdges(ss); - int start = 0; - int edgeSize = ccgSubSurf_getEdgeSize(ss); - - CCG_key_top_level(&key, ss); - - for (i = 0; i < totface; i++) { - CCGFace *f = ccgdm->faceMap[i].face; - int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f); - - for (S = 0; S < numVerts; S++) { - CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S); - for (y = 0; y < gridFaces; y++) { - for (x = 0; x < gridFaces; x++) { - float *a = CCG_grid_elem_co(&key, faceGridData, x, y); - float *b = CCG_grid_elem_co(&key, faceGridData, x + 1, y); - float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1); - float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1); - - copy_v3_v3(&varray[start], a); - copy_v3_v3(&varray[start + 3], b); - copy_v3_v3(&varray[start + 6], c); - copy_v3_v3(&varray[start + 9], d); - - start += 12; - } - } - } - } - - /* upload loose points */ - for (i = 0; i < totedge; i++) { - CCGEdge *e = ccgdm->edgeMap[i].edge; - CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e); - - if (!ccgSubSurf_getEdgeNumFaces(e)) { - int j = 0; - for (j = 0; j < edgeSize; j++) { - copy_v3_v3(&varray[start], CCG_elem_offset_co(&key, edgeData, j)); - start += 3; - } - } - } -} - -/* Only used by non-editmesh types */ -static void ccgDM_buffer_copy_color( - DerivedMesh *dm, unsigned char *varray, - const void *user_data) -{ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; - CCGSubSurf *ss = ccgdm->ss; - CCGKey key; - const unsigned char *mloopcol = user_data; - int gridSize = ccgSubSurf_getGridSize(ss); - int gridFaces = gridSize - 1; - int i, totface = ccgSubSurf_getNumFaces(ss); - int start = 0; - int iface = 0; - - CCG_key_top_level(&key, ss); - - - for (i = 0; i < totface; i++) { - CCGFace *f = ccgdm->faceMap[i].face; - int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f); - - for (S = 0; S < numVerts; S++) { - for (y = 0; y < gridFaces; y++) { - for (x = 0; x < gridFaces; x++) { - copy_v4_v4_uchar(&varray[start + 0], &mloopcol[iface * 16 + 0]); - copy_v4_v4_uchar(&varray[start + 4], &mloopcol[iface * 16 + 12]); - copy_v4_v4_uchar(&varray[start + 8], &mloopcol[iface * 16 + 8]); - copy_v4_v4_uchar(&varray[start + 12], &mloopcol[iface * 16 + 4]); - - start += 16; - iface++; - } - } - } - } -} - -static void ccgDM_buffer_copy_uv( - DerivedMesh *dm, void *varray_p) -{ - float *varray = varray_p; - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; - CCGSubSurf *ss = ccgdm->ss; - CCGKey key; - MLoopUV *mloopuv = DM_get_loop_data_layer(dm, CD_MLOOPUV); - int gridSize = ccgSubSurf_getGridSize(ss); - int gridFaces = gridSize - 1; - int i, totface = ccgSubSurf_getNumFaces(ss); - int start = 0; - - CCG_key_top_level(&key, ss); - - for (i = 0; i < totface; i++) { - CCGFace *f = ccgdm->faceMap[i].face; - int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f); - - for (S = 0; S < numVerts; S++) { - for (y = 0; y < gridFaces; y++) { - for (x = 0; x < gridFaces; x++) { - copy_v2_v2(&varray[start + 0], mloopuv[0].uv); - copy_v2_v2(&varray[start + 2], mloopuv[3].uv); - copy_v2_v2(&varray[start + 4], mloopuv[2].uv); - copy_v2_v2(&varray[start + 6], mloopuv[1].uv); - - mloopuv += 4; - start += 8; - } - } - } - } -} - -static void ccgDM_buffer_copy_uv_texpaint( - DerivedMesh *dm, float *varray) -{ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; - CCGSubSurf *ss = ccgdm->ss; - CCGKey key; - int gridSize = ccgSubSurf_getGridSize(ss); - int gridFaces = gridSize - 1; - int i, totface = ccgSubSurf_getNumFaces(ss); - int start = 0; - DMFlagMat *faceFlags = ccgdm->faceFlags; - int dm_totmat = dm->totmat; - MLoopUV **mloopuv_base; - MLoopUV *stencil_base; - int stencil; - - CCG_key_top_level(&key, ss); - - /* should have been checked for before, reassert */ - BLI_assert(DM_get_loop_data_layer(dm, CD_MLOOPUV)); - mloopuv_base = MEM_mallocN(dm_totmat * sizeof(*mloopuv_base), "texslots"); - - for (i = 0; i < dm_totmat; i++) { - mloopuv_base[i] = DM_paint_uvlayer_active_get(dm, i); - } - - stencil = CustomData_get_stencil_layer(&dm->loopData, CD_MLOOPUV); - stencil_base = CustomData_get_layer_n(&dm->loopData, CD_MLOOPUV, stencil); - - start = 0; - - for (i = 0; i < totface; i++) { - CCGFace *f = ccgdm->faceMap[i].face; - int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f); - int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f)); - int matnr; - - if (faceFlags) { - matnr = faceFlags[index].mat_nr; - } - else { - matnr = 0; - } - - for (S = 0; S < numVerts; S++) { - for (y = 0; y < gridFaces; y++) { - for (x = 0; x < gridFaces; x++) { - /* divide by 4, gives us current loop-index */ - unsigned int i_ml = start / 4; - copy_v2_v2(&varray[start + 0], mloopuv_base[matnr][i_ml + 0].uv); - copy_v2_v2(&varray[start + 2], stencil_base[i_ml + 0].uv); - copy_v2_v2(&varray[start + 4], mloopuv_base[matnr][i_ml + 3].uv); - copy_v2_v2(&varray[start + 6], stencil_base[i_ml + 3].uv); - copy_v2_v2(&varray[start + 8], mloopuv_base[matnr][i_ml + 2].uv); - copy_v2_v2(&varray[start + 10], stencil_base[i_ml + 2].uv); - copy_v2_v2(&varray[start + 12], mloopuv_base[matnr][i_ml + 1].uv); - copy_v2_v2(&varray[start + 14], stencil_base[i_ml + 1].uv); - start += 16; - } - } - } - } - - MEM_freeN(mloopuv_base); -} - -static void ccgDM_buffer_copy_uvedge( - DerivedMesh *dm, float *varray) -{ - int i, totpoly; - int start; - const MLoopUV *mloopuv; -#ifndef USE_LOOP_LAYOUT_FAST - const MPoly *mpoly = dm->getPolyArray(dm); -#endif - - if ((mloopuv = DM_get_loop_data_layer(dm, CD_MLOOPUV)) == NULL) { - return; - } - - totpoly = dm->getNumPolys(dm); - start = 0; - -#ifndef USE_LOOP_LAYOUT_FAST - for (i = 0; i < totpoly; i++, mpoly++) { - for (j = 0; j < mpoly->totloop; j++) { - copy_v2_v2(&varray[start], mloopuv[mpoly->loopstart + j].uv); - copy_v2_v2(&varray[start + 2], mloopuv[mpoly->loopstart + (j + 1) % mpoly->totloop].uv); - start += 4; - } - } -#else - for (i = 0; i < totpoly; i++) { - copy_v2_v2(&varray[start + 0], mloopuv[(i * 4) + 0].uv); - copy_v2_v2(&varray[start + 2], mloopuv[(i * 4) + 1].uv); - - copy_v2_v2(&varray[start + 4], mloopuv[(i * 4) + 1].uv); - copy_v2_v2(&varray[start + 6], mloopuv[(i * 4) + 2].uv); - - copy_v2_v2(&varray[start + 8], mloopuv[(i * 4) + 2].uv); - copy_v2_v2(&varray[start + 10], mloopuv[(i * 4) + 3].uv); - - copy_v2_v2(&varray[start + 12], mloopuv[(i * 4) + 3].uv); - copy_v2_v2(&varray[start + 14], mloopuv[(i * 4) + 0].uv); - - start += 16; - } -#endif -} - -static void ccgDM_buffer_copy_edge( - DerivedMesh *dm, unsigned int *varray) -{ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; - CCGSubSurf *ss = ccgdm->ss; - /* getEdgeSuze returns num of verts, edges is one less */ - int i, j, edgeSize = ccgSubSurf_getEdgeSize(ss) - 1; - int totedge = ccgSubSurf_getNumEdges(ss); - int grid_face_side = ccgSubSurf_getGridSize(ss) - 1; - int totface = ccgSubSurf_getNumFaces(ss); - unsigned int index_start; - unsigned int tot_interior = 0; - unsigned int grid_tot_face = grid_face_side * grid_face_side; - - unsigned int iloose, inorm, iloosehidden, inormhidden; - unsigned int tot_loose_hidden = 0, tot_loose = 0; - unsigned int tot_hidden = 0, tot = 0; - unsigned int iloosevert; - /* int tot_interior = 0; */ - - /* first, handle hidden/loose existing edges, then interior edges */ - for (j = 0; j < totedge; j++) { - CCGEdge *e = ccgdm->edgeMap[j].edge; - - if (ccgdm->edgeFlags && !(ccgdm->edgeFlags[j] & ME_EDGEDRAW)) { - if (!ccgSubSurf_getEdgeNumFaces(e)) tot_loose_hidden++; - else tot_hidden++; - } - else { - if (!ccgSubSurf_getEdgeNumFaces(e)) tot_loose++; - else tot++; - } - } - - inorm = 0; - inormhidden = tot * edgeSize; - iloose = (tot + tot_hidden) * edgeSize; - iloosehidden = (tot + tot_hidden + tot_loose) * edgeSize; - iloosevert = dm->drawObject->tot_loop_verts; - - /* part one, handle all normal edges */ - for (j = 0; j < totedge; j++) { - CCGFace *f; - int fhandle = 0; - int totvert = 0; - unsigned int S = 0; - CCGEdge *e = ccgdm->edgeMap[j].edge; - bool isloose = !ccgSubSurf_getEdgeNumFaces(e); - - if (!isloose) { - CCGVert *v1, *v2; - CCGVert *ev1 = ccgSubSurf_getEdgeVert0(e); - CCGVert *ev2 = ccgSubSurf_getEdgeVert1(e); - - f = ccgSubSurf_getEdgeFace(e, 0); - fhandle = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f)); - totvert = ccgSubSurf_getFaceNumVerts(f); - - /* find the index of vertices in the face */ - for (i = 0; i < totvert; i++) { - v1 = ccgSubSurf_getFaceVert(f, i); - v2 = ccgSubSurf_getFaceVert(f, (i + 1) % totvert); - - if ((ev1 == v1 && ev2 == v2) || (ev1 == v2 && ev2 == v1)) { - S = i; - break; - } - } - } - - if (ccgdm->edgeFlags && !(ccgdm->edgeFlags[j] & ME_EDGEDRAW)) { - if (isloose) { - for (i = 0; i < edgeSize; i++) { - varray[iloosehidden * 2] = iloosevert; - varray[iloosehidden * 2 + 1] = iloosevert + 1; - iloosehidden++; - iloosevert++; - } - /* we are through with this loose edge and moving to the next, so increase by one */ - iloosevert++; - } - else { - index_start = ccgdm->faceMap[fhandle].startFace; - - for (i = 0; i < grid_face_side; i++) { - varray[inormhidden * 2] = (index_start + S * grid_tot_face + i * grid_face_side + grid_face_side - 1) * 4 + 1; - varray[inormhidden * 2 + 1] = (index_start + S * grid_tot_face + i * grid_face_side + grid_face_side - 1) * 4 + 2; - varray[inormhidden * 2 + 2] = (index_start + ((S + 1) % totvert) * grid_tot_face + grid_face_side * (grid_face_side - 1) + i) * 4 + 2; - varray[inormhidden * 2 + 3] = (index_start + ((S + 1) % totvert) * grid_tot_face + grid_face_side * (grid_face_side - 1) + i) * 4 + 3; - inormhidden += 2; - } - } - } - else { - if (isloose) { - for (i = 0; i < edgeSize; i++) { - varray[iloose * 2] = iloosevert; - varray[iloose * 2 + 1] = iloosevert + 1; - iloose++; - iloosevert++; - } - /* we are through with this loose edge and moving to the next, so increase by one */ - iloosevert++; - } - else { - index_start = ccgdm->faceMap[fhandle].startFace; - - for (i = 0; i < grid_face_side; i++) { - varray[inorm * 2] = (index_start + S * grid_tot_face + i * grid_face_side + grid_face_side - 1) * 4 + 1; - varray[inorm * 2 + 1] = (index_start + S * grid_tot_face + i * grid_face_side + grid_face_side - 1) * 4 + 2; - varray[inorm * 2 + 2] = (index_start + ((S + 1) % totvert) * grid_tot_face + grid_face_side * (grid_face_side - 1) + i) * 4 + 2; - varray[inorm * 2 + 3] = (index_start + ((S + 1) % totvert) * grid_tot_face + grid_face_side * (grid_face_side - 1) + i) * 4 + 3; - inorm += 2; - } - } - } - } - - /* part two, handle interior edges */ - inorm = totedge * grid_face_side * 2; - - index_start = 0; - for (i = 0; i < totface; i++) { - CCGFace *f = ccgdm->faceMap[i].face; - unsigned int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f); - - for (S = 0; S < numVerts; S++) { - for (x = 1; x < grid_face_side; x++) { - for (y = 0; y < grid_face_side; y++) { - unsigned int tmp = (index_start + x * grid_face_side + y) * 4; - varray[inorm * 2] = tmp; - varray[inorm * 2 + 1] = tmp + 1; - inorm++; - } - } - for (x = 0; x < grid_face_side; x++) { - for (y = 0; y < grid_face_side; y++) { - unsigned int tmp = (index_start + x * grid_face_side + y) * 4; - varray[inorm * 2] = tmp + 3; - varray[inorm * 2 + 1] = tmp; - inorm++; - } - } - - tot_interior += grid_face_side * (2 * grid_face_side - 1); - index_start += grid_tot_face; - } - } - - dm->drawObject->tot_loose_edge_drawn = tot_loose * edgeSize; - dm->drawObject->loose_edge_offset = (tot + tot_hidden) * edgeSize; - dm->drawObject->tot_edge_drawn = tot * edgeSize; - - dm->drawObject->interior_offset = totedge * edgeSize; - dm->drawObject->totinterior = tot_interior; -} - -static void ccgDM_copy_gpu_data( - DerivedMesh *dm, int type, void *varray_p, - const int *mat_orig_to_new, const void *user_data) -{ - /* 'varray_p' cast is redundant but include for self-documentation */ - switch (type) { - case GPU_BUFFER_VERTEX: - ccgDM_buffer_copy_vertex(dm, (float *)varray_p); - break; - case GPU_BUFFER_NORMAL: - ccgDM_buffer_copy_normal(dm, (short *)varray_p); - break; - case GPU_BUFFER_UV: - ccgDM_buffer_copy_uv(dm, (float *)varray_p); - break; - case GPU_BUFFER_UV_TEXPAINT: - ccgDM_buffer_copy_uv_texpaint(dm, (float *)varray_p); - break; - case GPU_BUFFER_COLOR: - ccgDM_buffer_copy_color(dm, (unsigned char *)varray_p, user_data); - break; - case GPU_BUFFER_UVEDGE: - ccgDM_buffer_copy_uvedge(dm, (float *)varray_p); - break; - case GPU_BUFFER_EDGE: - ccgDM_buffer_copy_edge(dm, (unsigned int *)varray_p); - break; - case GPU_BUFFER_TRIANGLES: - ccgDM_buffer_copy_triangles(dm, (unsigned int *)varray_p, mat_orig_to_new); - break; - default: - break; - } -} - -static GPUDrawObject *ccgDM_GPUObjectNew(DerivedMesh *dm) -{ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; - CCGSubSurf *ss = ccgdm->ss; - GPUDrawObject *gdo; - DMFlagMat *faceFlags = ccgdm->faceFlags; - int gridFaces = ccgSubSurf_getGridSize(ss) - 1; - const short dm_totmat = (faceFlags) ? dm->totmat : 1; - GPUBufferMaterial *matinfo; - int i; - unsigned int tot_internal_edges = 0; - int edgeVerts = ccgSubSurf_getEdgeSize(ss); - int edgeSize = edgeVerts - 1; - - int totedge = ccgSubSurf_getNumEdges(ss); - int totface = ccgSubSurf_getNumFaces(ss); - - /* object contains at least one material (default included) so zero means uninitialized dm */ - BLI_assert(dm_totmat != 0); - - matinfo = MEM_callocN(sizeof(*matinfo) * dm_totmat, "GPU_drawobject_new.mat_orig_to_new"); - - if (faceFlags) { - for (i = 0; i < totface; i++) { - CCGFace *f = ccgdm->faceMap[i].face; - int numVerts = ccgSubSurf_getFaceNumVerts(f); - int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f)); - const short new_matnr = ME_MAT_NR_TEST(faceFlags[index].mat_nr, dm_totmat); - matinfo[new_matnr].totelements += numVerts * gridFaces * gridFaces * 6; - matinfo[new_matnr].totloops += numVerts * gridFaces * gridFaces * 4; - matinfo[new_matnr].totpolys++; - tot_internal_edges += numVerts * gridFaces * (2 * gridFaces - 1); - } - } - else { - for (i = 0; i < totface; i++) { - CCGFace *f = ccgdm->faceMap[i].face; - int numVerts = ccgSubSurf_getFaceNumVerts(f); - matinfo[0].totelements += numVerts * gridFaces * gridFaces * 6; - matinfo[0].totloops += numVerts * gridFaces * gridFaces * 4; - matinfo[0].totpolys++; - tot_internal_edges += numVerts * gridFaces * (2 * gridFaces - 1); - } - } - - /* create the GPUDrawObject */ - gdo = MEM_callocN(sizeof(GPUDrawObject), "GPUDrawObject"); - gdo->totvert = 0; /* used to count indices, doesn't really matter for ccgsubsurf */ - gdo->totedge = (totedge * edgeSize + tot_internal_edges); - - GPU_buffer_material_finalize(gdo, matinfo, dm_totmat); - - /* store total number of points used for triangles */ - gdo->tot_triangle_point = ccgSubSurf_getNumFinalFaces(ss) * 6; - gdo->tot_loop_verts = ccgSubSurf_getNumFinalFaces(ss) * 4; - - /* finally, count loose points */ - for (i = 0; i < totedge; i++) { - CCGEdge *e = ccgdm->edgeMap[i].edge; - - if (!ccgSubSurf_getEdgeNumFaces(e)) - gdo->tot_loose_point += edgeVerts; - } - - return gdo; -} - -/* Only used by non-editmesh types */ -static void ccgDM_drawFacesSolid(DerivedMesh *dm, float (*partial_redraw_planes)[4], bool fast, DMSetMaterial setMaterial) -{ - int a; - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; - - ccgdm_pbvh_update(ccgdm); - - if (ccgdm->pbvh && ccgdm->multires.mmd) { - if (BKE_pbvh_has_faces(ccgdm->pbvh)) { - BKE_pbvh_draw(ccgdm->pbvh, partial_redraw_planes, NULL, - setMaterial, false, fast); - } - - return; - } - -#ifdef WITH_OPENSUBDIV - if (ccgdm->useGpuBackend) { - CCGSubSurf *ss = ccgdm->ss; - const DMFlagMat *faceFlags = ccgdm->faceFlags; - 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 i, current_patch = 0; - int mat_nr = -1; - bool draw_smooth = false; - int start_draw_patch = -1, num_draw_patches = 0; - if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, setMaterial != NULL, -1) == false)) { - return; - } - if (setMaterial == NULL) { - ccgSubSurf_drawGLMesh(ss, - true, - -1, - -1); - return; - } - 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; - int new_matnr; - bool new_draw_smooth; - if (faceFlags) { - new_draw_smooth = (faceFlags[i].flag & ME_SMOOTH); - new_matnr = (faceFlags[i].mat_nr + 1); - } - else { - new_draw_smooth = true; - new_matnr = 1; - } - if (new_draw_smooth != draw_smooth || new_matnr != mat_nr) { - if (num_draw_patches != 0) { - bool do_draw = setMaterial(mat_nr, NULL); - if (do_draw) { - 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 = num_patches; - mat_nr = new_matnr; - draw_smooth = new_draw_smooth; - } - else { - num_draw_patches += num_patches; - } - current_patch += num_patches; - } - if (num_draw_patches != 0) { - bool do_draw = setMaterial(mat_nr, NULL); - if (do_draw) { - glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT); - ccgSubSurf_drawGLMesh(ss, - true, - start_draw_patch, - num_draw_patches); - } - } - glShadeModel(GL_SMOOTH); - return; - } -#endif - - 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(); -} - -typedef struct { - DMVertexAttribs attribs; - int numdata; - - GPUAttrib datatypes[GPU_MAX_ATTRIB]; /* TODO, messing up when switching materials many times - [#21056]*/ -} GPUMaterialConv; - -/* Only used by non-editmesh types */ -static void ccgDM_drawMappedFacesGLSL(DerivedMesh *dm, - DMSetMaterial setMaterial, - DMSetDrawOptions setDrawOptions, - void *userData) -{ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; - CCGSubSurf *ss = ccgdm->ss; - CCGKey key; - GPUVertexAttribs gattribs; - int a, b; - const DMFlagMat *faceFlags = ccgdm->faceFlags; - unsigned char *varray; - size_t max_element_size = 0; - int tot_loops = 0; - int totpoly = ccgSubSurf_getNumFaces(ss); - int gridSize = ccgSubSurf_getGridSize(ss); - int gridFaces = gridSize - 1; - int edgeSize = ccgSubSurf_getEdgeSize(ss); - -#ifdef WITH_OPENSUBDIV - if (ccgdm->useGpuBackend) { - 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 i, current_patch = 0; - int mat_nr = -1; - bool draw_smooth = false; - int start_draw_patch = -1, num_draw_patches = 0; - GPU_draw_update_fvar_offset(dm); - if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, false, -1) == false)) { - return; - } - 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; - int new_matnr; - bool new_draw_smooth; - - if (faceFlags) { - new_draw_smooth = (faceFlags[i].flag & ME_SMOOTH); - new_matnr = (faceFlags[i].mat_nr + 1); - } - else { - new_draw_smooth = true; - new_matnr = 1; - } - if (new_draw_smooth != draw_smooth || new_matnr != mat_nr) { - if (num_draw_patches != 0) { - bool do_draw = setMaterial(mat_nr, &gattribs); - if (do_draw) { - 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 = num_patches; - mat_nr = new_matnr; - draw_smooth = new_draw_smooth; - } - else { - num_draw_patches += num_patches; - } - current_patch += num_patches; - } - if (num_draw_patches != 0) { - bool do_draw = setMaterial(mat_nr, &gattribs); - if (do_draw) { - glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT); - ccgSubSurf_drawGLMesh(ss, - true, - start_draw_patch, - num_draw_patches); - } - } - glShadeModel(GL_SMOOTH); - return; - } -#endif - - CCG_key_top_level(&key, ss); - ccgdm_pbvh_update(ccgdm); - - if (setDrawOptions != NULL) { - const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL); - DMVertexAttribs attribs = {{{NULL}}}; - int i; - int matnr = -1; - int do_draw = 0; - -#define PASSATTRIB(dx, dy, vert) { \ - if (attribs.totorco) \ - index = getFaceIndex(ss, f, S, x + dx, y + dy, edgeSize, gridSize); \ - else \ - index = 0; \ - DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert); \ - DM_draw_attrib_vertex_uniforms(&attribs); \ -} (void)0 - - totpoly = ccgSubSurf_getNumFaces(ss); - for (a = 0, i = 0; i < totpoly; i++) { - CCGFace *f = ccgdm->faceMap[i].face; - const float (*ln)[3] = NULL; - int S, x, y, drawSmooth; - int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f)); - int origIndex = ccgDM_getFaceMapIndex(ss, f); - - int numVerts = ccgSubSurf_getFaceNumVerts(f); - int new_matnr; - - if (faceFlags) { - drawSmooth = (lnors || (faceFlags[index].flag & ME_SMOOTH)); - new_matnr = faceFlags[index].mat_nr + 1; - } - else { - drawSmooth = 1; - new_matnr = 1; - } - - if (lnors) { - ln = lnors; - lnors += (gridFaces * gridFaces * numVerts) * 4; - } - - if (new_matnr != matnr) { - do_draw = setMaterial(matnr = new_matnr, &gattribs); - if (do_draw) - DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); - } - - if (!do_draw || (setDrawOptions && (origIndex != ORIGINDEX_NONE) && - (setDrawOptions(userData, origIndex) == DM_DRAW_OPTION_SKIP))) - { - a += gridFaces * gridFaces * numVerts; - continue; - } - - glShadeModel(drawSmooth ? GL_SMOOTH : GL_FLAT); - for (S = 0; S < numVerts; S++) { - CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S); - CCGElem *vda, *vdb; - - if (ln) { - glBegin(GL_QUADS); - for (y = 0; y < gridFaces; y++) { - for (x = 0; x < gridFaces; x++) { - float *aco = CCG_grid_elem_co(&key, faceGridData, x, y); - float *bco = CCG_grid_elem_co(&key, faceGridData, x + 1, y); - float *cco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1); - float *dco = CCG_grid_elem_co(&key, faceGridData, x, y + 1); - - PASSATTRIB(0, 1, 1); - glNormal3fv(ln[1]); - glVertex3fv(dco); - PASSATTRIB(1, 1, 2); - glNormal3fv(ln[2]); - glVertex3fv(cco); - PASSATTRIB(1, 0, 3); - glNormal3fv(ln[3]); - glVertex3fv(bco); - PASSATTRIB(0, 0, 0); - glNormal3fv(ln[0]); - glVertex3fv(aco); - - ln += 4; - a++; - } - } - glEnd(); - } - else if (drawSmooth) { - for (y = 0; y < gridFaces; y++) { - glBegin(GL_QUAD_STRIP); - for (x = 0; x < gridFaces; x++) { - vda = CCG_grid_elem(&key, faceGridData, x, y + 0); - vdb = CCG_grid_elem(&key, faceGridData, x, y + 1); - - PASSATTRIB(0, 0, 0); - glNormal3fv(CCG_elem_no(&key, vda)); - glVertex3fv(CCG_elem_co(&key, vda)); - - PASSATTRIB(0, 1, 1); - glNormal3fv(CCG_elem_no(&key, vdb)); - glVertex3fv(CCG_elem_co(&key, vdb)); - - if (x != gridFaces - 1) - a++; - } - - vda = CCG_grid_elem(&key, faceGridData, x, y + 0); - vdb = CCG_grid_elem(&key, faceGridData, x, y + 1); - - PASSATTRIB(0, 0, 3); - glNormal3fv(CCG_elem_no(&key, vda)); - glVertex3fv(CCG_elem_co(&key, vda)); - - PASSATTRIB(0, 1, 2); - glNormal3fv(CCG_elem_no(&key, vdb)); - glVertex3fv(CCG_elem_co(&key, vdb)); - - glEnd(); - - a++; - } - } - else { - glBegin(GL_QUADS); - for (y = 0; y < gridFaces; y++) { - for (x = 0; x < gridFaces; x++) { - float *aco = CCG_grid_elem_co(&key, faceGridData, x, y); - float *bco = CCG_grid_elem_co(&key, faceGridData, x + 1, y); - float *cco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1); - float *dco = CCG_grid_elem_co(&key, faceGridData, x, y + 1); - - ccgDM_glNormalFast(aco, bco, cco, dco); - - PASSATTRIB(0, 1, 1); - glVertex3fv(dco); - PASSATTRIB(1, 1, 2); - glVertex3fv(cco); - PASSATTRIB(1, 0, 3); - glVertex3fv(bco); - PASSATTRIB(0, 0, 0); - glVertex3fv(aco); - - a++; - } - } - glEnd(); - } - } - } - - glShadeModel(GL_SMOOTH); -#undef PASSATTRIB - } - else { - GPUMaterialConv *matconv; - size_t offset; - int *mat_orig_to_new; - int tot_active_mat; - GPUBuffer *buffer = NULL; - - GPU_vertex_setup(dm); - GPU_normal_setup(dm); - GPU_triangle_setup(dm); - - tot_active_mat = dm->drawObject->totmaterial; - - matconv = MEM_callocN(sizeof(*matconv) * tot_active_mat, - "cdDM_drawMappedFacesGLSL.matconv"); - mat_orig_to_new = MEM_mallocN(sizeof(*mat_orig_to_new) * dm->totmat, - "cdDM_drawMappedFacesGLSL.mat_orig_to_new"); - - /* part one, check what attributes are needed per material */ - for (a = 0; a < tot_active_mat; a++) { - int new_matnr; - int do_draw; - - new_matnr = dm->drawObject->materials[a].mat_nr; - - /* map from original material index to new - * GPUBufferMaterial index */ - mat_orig_to_new[new_matnr] = a; - do_draw = setMaterial(new_matnr + 1, &gattribs); - - if (do_draw) { - int numdata = 0; - DM_vertex_attributes_from_gpu(dm, &gattribs, &matconv[a].attribs); - - if (matconv[a].attribs.totorco && matconv[a].attribs.orco.array) { - matconv[a].datatypes[numdata].index = matconv[a].attribs.orco.gl_index; - matconv[a].datatypes[numdata].info_index = matconv[a].attribs.orco.gl_info_index; - matconv[a].datatypes[numdata].size = 3; - matconv[a].datatypes[numdata].type = GL_FLOAT; - numdata++; - } - for (b = 0; b < matconv[a].attribs.tottface; b++) { - if (matconv[a].attribs.tface[b].array) { - matconv[a].datatypes[numdata].index = matconv[a].attribs.tface[b].gl_index; - matconv[a].datatypes[numdata].info_index = matconv[a].attribs.tface[b].gl_info_index; - matconv[a].datatypes[numdata].size = 2; - matconv[a].datatypes[numdata].type = GL_FLOAT; - numdata++; - } - } - for (b = 0; b < matconv[a].attribs.totmcol; b++) { - if (matconv[a].attribs.mcol[b].array) { - matconv[a].datatypes[numdata].index = matconv[a].attribs.mcol[b].gl_index; - matconv[a].datatypes[numdata].info_index = matconv[a].attribs.mcol[b].gl_info_index; - matconv[a].datatypes[numdata].size = 4; - matconv[a].datatypes[numdata].type = GL_UNSIGNED_BYTE; - numdata++; - } - } - for (b = 0; b < matconv[a].attribs.tottang; b++) { - if (matconv[a].attribs.tottang && matconv[a].attribs.tang[b].array) { - matconv[a].datatypes[numdata].index = matconv[a].attribs.tang[b].gl_index; - matconv[a].datatypes[numdata].info_index = matconv[a].attribs.tang[b].gl_info_index; - matconv[a].datatypes[numdata].size = 4; - matconv[a].datatypes[numdata].type = GL_FLOAT; - numdata++; - } - } - if (numdata != 0) { - matconv[a].numdata = numdata; - max_element_size = max_ii(GPU_attrib_element_size(matconv[a].datatypes, numdata), max_element_size); - } - } - } - - /* part two, generate and fill the arrays with the data */ - if (max_element_size > 0) { - buffer = GPU_buffer_alloc(max_element_size * dm->drawObject->tot_loop_verts); - - varray = GPU_buffer_lock_stream(buffer, GPU_BINDING_ARRAY); - if (varray == NULL) { - GPU_buffers_unbind(); - GPU_buffer_free(buffer); - MEM_freeN(mat_orig_to_new); - MEM_freeN(matconv); - fprintf(stderr, "Out of memory, can't draw object\n"); - return; - } - - for (a = 0; a < totpoly; a++) { - CCGFace *f = ccgdm->faceMap[a].face; - int orig_index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f)); - int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f); - int i; - - if (faceFlags) { - i = mat_orig_to_new[faceFlags[orig_index].mat_nr]; - } - else { - i = mat_orig_to_new[0]; - } - - if (matconv[i].numdata != 0) { - for (S = 0; S < numVerts; S++) { - for (y = 0; y < gridFaces; y++) { - for (x = 0; x < gridFaces; x++) { - - offset = tot_loops * max_element_size; - - if (matconv[i].attribs.totorco && matconv[i].attribs.orco.array) { - int index; - - index = getFaceIndex(ss, f, S, x, y, edgeSize, gridSize); - copy_v3_v3((float *)&varray[offset], - (float *)matconv[i].attribs.orco.array[index]); - index = getFaceIndex(ss, f, S, x + 1, y, edgeSize, gridSize); - copy_v3_v3((float *)&varray[offset + max_element_size], - (float *)matconv[i].attribs.orco.array[index]); - index = getFaceIndex(ss, f, S, x + 1, y + 1, edgeSize, gridSize); - copy_v3_v3((float *)&varray[offset + 2 * max_element_size], - (float *)matconv[i].attribs.orco.array[index]); - index = getFaceIndex(ss, f, S, x, y + 1, edgeSize, gridSize); - copy_v3_v3((float *)&varray[offset + 3 * max_element_size], - (float *)matconv[i].attribs.orco.array[index]); - - offset += sizeof(float) * 3; - } - for (b = 0; b < matconv[i].attribs.tottface; b++) { - if (matconv[i].attribs.tface[b].array) { - const MLoopUV *mloopuv = matconv[i].attribs.tface[b].array + tot_loops; - - copy_v2_v2((float *)&varray[offset], mloopuv[0].uv); - copy_v2_v2((float *)&varray[offset + max_element_size], mloopuv[3].uv); - copy_v2_v2((float *)&varray[offset + 2 * max_element_size], mloopuv[2].uv); - copy_v2_v2((float *)&varray[offset + 3 * max_element_size], mloopuv[1].uv); - - offset += sizeof(float) * 2; - } - } - for (b = 0; b < matconv[i].attribs.totmcol; b++) { - if (matconv[i].attribs.mcol[b].array) { - const MLoopCol *mloopcol = matconv[i].attribs.mcol[b].array + tot_loops; - - copy_v4_v4_uchar(&varray[offset], &mloopcol[0].r); - copy_v4_v4_uchar(&varray[offset + max_element_size], &mloopcol[3].r); - copy_v4_v4_uchar(&varray[offset + 2 * max_element_size], &mloopcol[2].r); - copy_v4_v4_uchar(&varray[offset + 3 * max_element_size], &mloopcol[1].r); - - offset += sizeof(unsigned char) * 4; - } - } - for (b = 0; b < matconv[i].attribs.tottang; b++) { - if (matconv[i].attribs.tottang && matconv[i].attribs.tang[b].array) { - const float (*looptang)[4] = (const float (*)[4])matconv[i].attribs.tang[b].array + tot_loops; - - copy_v4_v4((float *)&varray[offset], looptang[0]); - copy_v4_v4((float *)&varray[offset + max_element_size], looptang[3]); - copy_v4_v4((float *)&varray[offset + 2 * max_element_size], looptang[2]); - copy_v4_v4((float *)&varray[offset + 3 * max_element_size], looptang[1]); - - offset += sizeof(float) * 4; - } - } - - tot_loops += 4; - } - } - } - } - else { - tot_loops += 4 * numVerts * gridFaces * gridFaces; - } - } - GPU_buffer_unlock(buffer, GPU_BINDING_ARRAY); - } - - for (a = 0; a < tot_active_mat; a++) { - int new_matnr; - int do_draw; - - new_matnr = dm->drawObject->materials[a].mat_nr; - - do_draw = setMaterial(new_matnr + 1, &gattribs); - - if (do_draw) { - if (matconv[a].numdata) { - GPU_interleaved_attrib_setup(buffer, matconv[a].datatypes, matconv[a].numdata, max_element_size); - } - GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, - dm->drawObject->materials[a].start, dm->drawObject->materials[a].totelements); - if (matconv[a].numdata) { - GPU_interleaved_attrib_unbind(); - } - } - } - - GPU_buffers_unbind(); - if (buffer) - GPU_buffer_free(buffer); - - MEM_freeN(mat_orig_to_new); - MEM_freeN(matconv); - } -} - -static void ccgDM_drawFacesGLSL(DerivedMesh *dm, DMSetMaterial setMaterial) -{ - dm->drawMappedFacesGLSL(dm, setMaterial, NULL, NULL); -} - -/* Only used by non-editmesh types */ -static void ccgDM_drawMappedFacesMat(DerivedMesh *dm, - void (*setMaterial)(void *userData, int matnr, void *attribs), - bool (*setFace)(void *userData, int index), void *userData) -{ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; - CCGSubSurf *ss = ccgdm->ss; - CCGKey key; - GPUVertexAttribs gattribs; - DMVertexAttribs attribs = {{{NULL}}}; - int gridSize = ccgSubSurf_getGridSize(ss); - int gridFaces = gridSize - 1; - int edgeSize = ccgSubSurf_getEdgeSize(ss); - DMFlagMat *faceFlags = ccgdm->faceFlags; - const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL); - int a, i, numVerts, matnr, totface; - -#ifdef WITH_OPENSUBDIV - if (ccgdm->useGpuBackend) { - 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; - bool draw_smooth = false; - int start_draw_patch = -1, num_draw_patches = 0; - GPU_draw_update_fvar_offset(dm); - if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, true, -1) == false)) { - return; - } - 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; - int new_matnr; - bool new_draw_smooth; - - if (faceFlags) { - new_draw_smooth = (faceFlags[i].flag & ME_SMOOTH); - new_matnr = (faceFlags[i].mat_nr + 1); - } - else { - new_draw_smooth = true; - new_matnr = 1; - } - if (new_draw_smooth != draw_smooth || new_matnr != mat_nr) { - if (num_draw_patches != 0) { - setMaterial(userData, mat_nr, &gattribs); - 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 = num_patches; - mat_nr = new_matnr; - draw_smooth = new_draw_smooth; - } - else { - num_draw_patches += num_patches; - } - current_patch += num_patches; - } - if (num_draw_patches != 0) { - setMaterial(userData, mat_nr, &gattribs); - glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT); - ccgSubSurf_drawGLMesh(ss, - true, - start_draw_patch, - num_draw_patches); - } - glShadeModel(GL_SMOOTH); - return; - } -#endif - - CCG_key_top_level(&key, ss); - ccgdm_pbvh_update(ccgdm); - - matnr = -1; - -#define PASSATTRIB(dx, dy, vert) { \ - if (attribs.totorco) \ - index = getFaceIndex(ss, f, S, x + dx, y + dy, edgeSize, gridSize); \ - else \ - index = 0; \ - DM_draw_attrib_vertex(&attribs, a, index, vert, ((a) * 4) + vert); \ - DM_draw_attrib_vertex_uniforms(&attribs); \ -} (void)0 - - totface = ccgSubSurf_getNumFaces(ss); - for (a = 0, i = 0; i < totface; i++) { - CCGFace *f = ccgdm->faceMap[i].face; - const float (*ln)[3] = NULL; - int S, x, y, drawSmooth; - int index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f)); - int origIndex = ccgDM_getFaceMapIndex(ss, f); - int new_matnr; - - numVerts = ccgSubSurf_getFaceNumVerts(f); - - /* get flags */ - if (faceFlags) { - drawSmooth = (lnors || (faceFlags[index].flag & ME_SMOOTH)); - new_matnr = faceFlags[index].mat_nr + 1; - } - else { - drawSmooth = 1; - new_matnr = 1; - } - - if (lnors) { - ln = lnors; - lnors += (gridFaces * gridFaces * numVerts) * 4; - } - - /* material */ - if (new_matnr != matnr) { - setMaterial(userData, matnr = new_matnr, &gattribs); - DM_vertex_attributes_from_gpu(dm, &gattribs, &attribs); - } - - /* face hiding */ - if ((setFace && (origIndex != ORIGINDEX_NONE) && !setFace(userData, origIndex))) { - a += gridFaces * gridFaces * numVerts; - continue; - } - - /* draw face*/ - glShadeModel(drawSmooth ? GL_SMOOTH : GL_FLAT); - for (S = 0; S < numVerts; S++) { - CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S); - CCGElem *vda, *vdb; - - if (ln) { - glBegin(GL_QUADS); - for (y = 0; y < gridFaces; y++) { - for (x = 0; x < gridFaces; x++) { - float *aco = CCG_grid_elem_co(&key, faceGridData, x, y + 0); - float *bco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 0); - float *cco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1); - float *dco = CCG_grid_elem_co(&key, faceGridData, x, y + 1); - - PASSATTRIB(0, 1, 1); - glNormal3fv(ln[1]); - glVertex3fv(dco); - PASSATTRIB(1, 1, 2); - glNormal3fv(ln[2]); - glVertex3fv(cco); - PASSATTRIB(1, 0, 3); - glNormal3fv(ln[3]); - glVertex3fv(bco); - PASSATTRIB(0, 0, 0); - glNormal3fv(ln[0]); - glVertex3fv(aco); - - ln += 4; - a++; - } - } - glEnd(); - } - else if (drawSmooth) { - for (y = 0; y < gridFaces; y++) { - glBegin(GL_QUAD_STRIP); - for (x = 0; x < gridFaces; x++) { - vda = CCG_grid_elem(&key, faceGridData, x, y); - vdb = CCG_grid_elem(&key, faceGridData, x, y + 1); - - PASSATTRIB(0, 0, 0); - glNormal3fv(CCG_elem_no(&key, vda)); - glVertex3fv(CCG_elem_co(&key, vda)); - - PASSATTRIB(0, 1, 1); - glNormal3fv(CCG_elem_no(&key, vdb)); - glVertex3fv(CCG_elem_co(&key, vdb)); - - if (x != gridFaces - 1) - a++; - } - - vda = CCG_grid_elem(&key, faceGridData, x, y + 0); - vdb = CCG_grid_elem(&key, faceGridData, x, y + 1); - - PASSATTRIB(0, 0, 3); - glNormal3fv(CCG_elem_no(&key, vda)); - glVertex3fv(CCG_elem_co(&key, vda)); - - PASSATTRIB(0, 1, 2); - glNormal3fv(CCG_elem_no(&key, vdb)); - glVertex3fv(CCG_elem_co(&key, vdb)); - - glEnd(); - - a++; - } - } - else { - glBegin(GL_QUADS); - for (y = 0; y < gridFaces; y++) { - for (x = 0; x < gridFaces; x++) { - float *aco = CCG_grid_elem_co(&key, faceGridData, x, y + 0); - float *bco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 0); - float *cco = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1); - float *dco = CCG_grid_elem_co(&key, faceGridData, x, y + 1); - - ccgDM_glNormalFast(aco, bco, cco, dco); - - PASSATTRIB(0, 1, 1); - glVertex3fv(dco); - PASSATTRIB(1, 1, 2); - glVertex3fv(cco); - PASSATTRIB(1, 0, 3); - glVertex3fv(bco); - PASSATTRIB(0, 0, 0); - glVertex3fv(aco); - - a++; - } - } - glEnd(); - } - } - } - - glShadeModel(GL_SMOOTH); -#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, - DMCompareDrawOptions compareDrawOptions, - void *userData, DMDrawFlag flag) -{ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; - CCGSubSurf *ss = ccgdm->ss; - CCGKey key; - MLoopCol *mloopcol = NULL; - const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL); - int i, gridSize = ccgSubSurf_getGridSize(ss); - DMFlagMat *faceFlags = ccgdm->faceFlags; - int useColors = flag & DM_DRAW_USE_COLORS; - int gridFaces = gridSize - 1, totface; - int prev_mat_nr = -1; - - if (ccgdm->pbvh) { - if (G.debug_value == 14) - BKE_pbvh_draw_BB(ccgdm->pbvh); - } - -#ifdef WITH_OPENSUBDIV - if (ccgdm->useGpuBackend) { - int new_matnr; - bool draw_smooth, do_draw = true; - if (setDrawOptions == NULL) { - /* TODO(sergey): This is for cases when vertex colors or weights - * are visualising. Currently we don't have CD layers for this data - * and here we only make it so there's no garbage displayed. - * - * In the future we'll either need to have CD for this data or pass - * this data as face-varying or vertex-varying data in OSD mesh. - */ - glColor3f(0.8f, 0.8f, 0.8f); - } - if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, true, -1) == false)) { - return; - } - if (faceFlags) { - draw_smooth = (faceFlags[0].flag & ME_SMOOTH); - new_matnr = (faceFlags[0].mat_nr + 1); - } - else { - draw_smooth = true; - new_matnr = 1; - } - if (setMaterial) { - setMaterial(new_matnr, NULL); - } - if (setDrawOptions) { - if (setDrawOptions(userData, 0) == DM_DRAW_OPTION_SKIP) { - do_draw = false; - } - } - if (do_draw) { - glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT); - ccgSubSurf_drawGLMesh(ss, true, -1, -1); - glShadeModel(GL_SMOOTH); - } - return; - } -#endif - - CCG_key_top_level(&key, ss); - - /* currently unused -- each original face is handled separately */ - (void)compareDrawOptions; - - if (useColors) { - mloopcol = dm->getLoopDataArray(dm, CD_PREVIEW_MLOOPCOL); - if (!mloopcol) - mloopcol = dm->getLoopDataArray(dm, CD_MLOOPCOL); - } - - totface = ccgSubSurf_getNumFaces(ss); - for (i = 0; i < totface; i++) { - CCGFace *f = ccgdm->faceMap[i].face; - int S, x, y, numVerts = ccgSubSurf_getFaceNumVerts(f); - int drawSmooth, index = ccgDM_getFaceMapIndex(ss, f); - int origIndex; - unsigned char *cp = NULL; - const float (*ln)[3] = NULL; - - origIndex = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f)); - - if (flag & DM_DRAW_ALWAYS_SMOOTH) drawSmooth = 1; - else if (faceFlags) drawSmooth = (lnors || (faceFlags[origIndex].flag & ME_SMOOTH)); - else drawSmooth = 1; - - if (mloopcol) { - cp = (unsigned char *)mloopcol; - mloopcol += gridFaces * gridFaces * numVerts * 4; - } - - if (lnors) { - ln = lnors; - lnors += (gridFaces * gridFaces * numVerts) * 4; - } - - { - DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL; - - if (setMaterial) { - int mat_nr = faceFlags ? faceFlags[origIndex].mat_nr + 1 : 1; - - if (mat_nr != prev_mat_nr) { - setMaterial(mat_nr, NULL); /* XXX, no faceFlags no material */ - prev_mat_nr = mat_nr; - } - } - - if (setDrawOptions && (index != ORIGINDEX_NONE)) - draw_option = setDrawOptions(userData, index); - - if (draw_option != DM_DRAW_OPTION_SKIP) { - if (draw_option == DM_DRAW_OPTION_STIPPLE) { - GPU_basic_shader_bind(GPU_SHADER_STIPPLE | GPU_SHADER_USE_COLOR); - GPU_basic_shader_stipple(GPU_SHADER_STIPPLE_QUARTTONE); - } - - for (S = 0; S < numVerts; S++) { - CCGElem *faceGridData = ccgSubSurf_getFaceGridDataArray(ss, f, S); - if (ln) { - glBegin(GL_QUADS); - for (y = 0; y < gridFaces; y++) { - for (x = 0; x < gridFaces; x++) { - float *a = CCG_grid_elem_co(&key, faceGridData, x, y + 0); - float *b = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 0); - float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1); - float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1); - - if (cp) glColor4ubv(&cp[4]); - glNormal3fv(ln[1]); - glVertex3fv(d); - if (cp) glColor4ubv(&cp[8]); - glNormal3fv(ln[2]); - glVertex3fv(c); - if (cp) glColor4ubv(&cp[12]); - glNormal3fv(ln[3]); - glVertex3fv(b); - if (cp) glColor4ubv(&cp[0]); - glNormal3fv(ln[0]); - glVertex3fv(a); - - if (cp) cp += 16; - ln += 4; - } - } - glEnd(); - } - else if (drawSmooth) { - for (y = 0; y < gridFaces; y++) { - CCGElem *a, *b; - glBegin(GL_QUAD_STRIP); - for (x = 0; x < gridFaces; x++) { - a = CCG_grid_elem(&key, faceGridData, x, y + 0); - b = CCG_grid_elem(&key, faceGridData, x, y + 1); - - if (cp) glColor4ubv(&cp[0]); - glNormal3fv(CCG_elem_no(&key, a)); - glVertex3fv(CCG_elem_co(&key, a)); - if (cp) glColor4ubv(&cp[4]); - glNormal3fv(CCG_elem_no(&key, b)); - glVertex3fv(CCG_elem_co(&key, b)); - - if (x != gridFaces - 1) { - if (cp) cp += 16; - } - } - - a = CCG_grid_elem(&key, faceGridData, x, y + 0); - b = CCG_grid_elem(&key, faceGridData, x, y + 1); - - if (cp) glColor4ubv(&cp[12]); - glNormal3fv(CCG_elem_no(&key, a)); - glVertex3fv(CCG_elem_co(&key, a)); - if (cp) glColor4ubv(&cp[8]); - glNormal3fv(CCG_elem_no(&key, b)); - glVertex3fv(CCG_elem_co(&key, b)); - - if (cp) cp += 16; - - glEnd(); - } - } - else { - glBegin(GL_QUADS); - for (y = 0; y < gridFaces; y++) { - for (x = 0; x < gridFaces; x++) { - float *a = CCG_grid_elem_co(&key, faceGridData, x, y + 0); - float *b = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 0); - float *c = CCG_grid_elem_co(&key, faceGridData, x + 1, y + 1); - float *d = CCG_grid_elem_co(&key, faceGridData, x, y + 1); - - ccgDM_glNormalFast(a, b, c, d); - - if (cp) glColor4ubv(&cp[4]); - glVertex3fv(d); - if (cp) glColor4ubv(&cp[8]); - glVertex3fv(c); - if (cp) glColor4ubv(&cp[12]); - glVertex3fv(b); - if (cp) glColor4ubv(&cp[0]); - glVertex3fv(a); - - if (cp) cp += 16; - } - } - glEnd(); - } - } - if (draw_option == DM_DRAW_OPTION_STIPPLE) - GPU_basic_shader_bind(GPU_SHADER_USE_COLOR); - } - } - } -} - -static void ccgDM_drawMappedEdges(DerivedMesh *dm, - DMSetDrawOptions setDrawOptions, - void *userData) -{ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; - CCGSubSurf *ss = ccgdm->ss; - CCGEdgeIterator ei; - CCGKey key; - int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss); - -#ifdef WITH_OPENSUBDIV - if (ccgdm->useGpuBackend) { - /* TODO(sergey): Only draw edges from base mesh. */ - if (ccgSubSurf_prepareGLMesh(ccgdm->ss, true, -1)) { - if (!setDrawOptions || (setDrawOptions(userData, 0) != DM_DRAW_OPTION_SKIP)) { - ccgSubSurf_drawGLMesh(ccgdm->ss, false, -1, -1); - } - } - return; - } -#endif - - CCG_key_top_level(&key, ss); - ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL); - - for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) { - CCGEdge *e = ccgEdgeIterator_getCurrent(&ei); - CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e); - int index = ccgDM_getEdgeMapIndex(ss, e); - - glBegin(GL_LINE_STRIP); - if (index != -1 && (!setDrawOptions || (setDrawOptions(userData, index) != DM_DRAW_OPTION_SKIP))) { - if (useAging && !(G.f & G_BACKBUFSEL)) { - int ageCol = 255 - ccgSubSurf_getEdgeAge(ss, e) * 4; - glColor3ub(0, ageCol > 0 ? ageCol : 0, 0); - } - - for (i = 0; i < edgeSize - 1; i++) { - glVertex3fv(CCG_elem_offset_co(&key, edgeData, i)); - glVertex3fv(CCG_elem_offset_co(&key, edgeData, i + 1)); - } - } - glEnd(); - } -} - -static void ccgDM_drawMappedEdgesInterp(DerivedMesh *dm, - DMSetDrawOptions setDrawOptions, - DMSetDrawInterpOptions setDrawInterpOptions, - void *userData) -{ - CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm; - CCGSubSurf *ss = ccgdm->ss; - CCGKey key; - CCGEdgeIterator ei; - int i, useAging, edgeSize = ccgSubSurf_getEdgeSize(ss); - -#ifdef WITH_OPENSUBDIV - if (ccgdm->useGpuBackend) { - BLI_assert(!"Not currently supported"); - return; - } -#endif - - CCG_key_top_level(&key, ss); - ccgSubSurf_getUseAgeCounts(ss, &useAging, NULL, NULL, NULL); - - for (ccgSubSurf_initEdgeIterator(ss, &ei); !ccgEdgeIterator_isStopped(&ei); ccgEdgeIterator_next(&ei)) { - CCGEdge *e = ccgEdgeIterator_getCurrent(&ei); - CCGElem *edgeData = ccgSubSurf_getEdgeDataArray(ss, e); - int index = ccgDM_getEdgeMapIndex(ss, e); - - glBegin(GL_LINE_STRIP); - if (index != -1 && (!setDrawOptions || (setDrawOptions(userData, index) != DM_DRAW_OPTION_SKIP))) { - for (i = 0; i < edgeSize; i++) { - setDrawInterpOptions(userData, index, (float) i / (edgeSize - 1)); - - if (useAging && !(G.f & G_BACKBUFSEL)) { - int ageCol = 255 - ccgSubSurf_getEdgeAge(ss, e) * 4; - glColor3ub(0, ageCol > 0 ? ageCol : 0, 0); - } - - glVertex3fv(CCG_elem_offset_co(&key, edgeData, i)); - } - } - glEnd(); - } -} - static void ccgDM_foreachMappedFaceCenter( DerivedMesh *dm, void (*func)(void *userData, int index, const float co[3], const float no[3]), @@ -4687,23 +2468,6 @@ static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm) ccgdm->dm.foreachMappedLoop = ccgDM_foreachMappedLoop; ccgdm->dm.foreachMappedFaceCenter = ccgDM_foreachMappedFaceCenter; - ccgdm->dm.drawVerts = ccgDM_drawVerts; - 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; - ccgdm->dm.gpuObjectNew = ccgDM_GPUObjectNew; - ccgdm->dm.copy_gpu_data = ccgDM_copy_gpu_data; - ccgdm->dm.release = ccgDM_release; } @@ -5155,8 +2919,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 b650b6e9fb8..3892b2f0546 100644 --- a/source/blender/blenkernel/intern/text.c +++ b/source/blender/blenkernel/intern/text.c @@ -47,8 +47,6 @@ #include "BLI_fileops.h" #include "DNA_constraint_types.h" -#include "DNA_controller_types.h" -#include "DNA_actuator_types.h" #include "DNA_scene_types.h" #include "DNA_screen_types.h" #include "DNA_space_types.h" @@ -58,7 +56,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/texture.c b/source/blender/blenkernel/intern/texture.c index 250408642bb..2bf2fa7807b 100644 --- a/source/blender/blenkernel/intern/texture.c +++ b/source/blender/blenkernel/intern/texture.c @@ -44,9 +44,7 @@ #include "DNA_key_types.h" #include "DNA_object_types.h" -#include "DNA_lamp_types.h" #include "DNA_material_types.h" -#include "DNA_world_types.h" #include "DNA_brush_types.h" #include "DNA_node_types.h" #include "DNA_color_types.h" @@ -213,22 +211,6 @@ void BKE_texture_free(Tex *tex) } MEM_SAFE_FREE(tex->coba); - if (tex->env) { - BKE_texture_envmap_free(tex->env); - tex->env = NULL; - } - if (tex->pd) { - BKE_texture_pointdensity_free(tex->pd); - tex->pd = NULL; - } - if (tex->vd) { - BKE_texture_voxeldata_free(tex->vd); - tex->vd = NULL; - } - if (tex->ot) { - BKE_texture_ocean_free(tex->ot); - tex->ot = NULL; - } BKE_icon_id_delete((ID *)tex); BKE_previewimg_free(&tex->preview); @@ -285,30 +267,6 @@ void BKE_texture_default(Tex *tex) tex->vn_distm = 0; tex->vn_coltype = 0; - if (tex->env) { - tex->env->stype = ENV_ANIM; - tex->env->clipsta = 0.1; - tex->env->clipend = 100; - tex->env->cuberes = 512; - tex->env->depth = 0; - } - - if (tex->pd) { - tex->pd->radius = 0.3f; - tex->pd->falloff_type = TEX_PD_FALLOFF_STD; - } - - if (tex->vd) { - tex->vd->resol[0] = tex->vd->resol[1] = tex->vd->resol[2] = 0; - tex->vd->interp_type = TEX_VD_LINEAR; - tex->vd->file_format = TEX_VD_SMOKE; - } - - if (tex->ot) { - tex->ot->output = TEX_OCN_DISPLACEMENT; - tex->ot->object = NULL; - } - tex->iuser.fie_ima = 2; tex->iuser.ok = 1; tex->iuser.frames = 100; @@ -319,26 +277,6 @@ void BKE_texture_default(Tex *tex) void BKE_texture_type_set(Tex *tex, int type) { - switch (type) { - - case TEX_VOXELDATA: - if (tex->vd == NULL) - tex->vd = BKE_texture_voxeldata_add(); - break; - case TEX_POINTDENSITY: - if (tex->pd == NULL) - tex->pd = BKE_texture_pointdensity_add(); - break; - case TEX_ENVMAP: - if (tex->env == NULL) - tex->env = BKE_texture_envmap_add(); - break; - case TEX_OCEAN: - if (tex->ot == NULL) - tex->ot = BKE_texture_ocean_add(); - break; - } - tex->type = type; } @@ -476,10 +414,6 @@ MTex *BKE_texture_mtex_add_id(ID *id, int slot) MEM_freeN(mtex_ar[slot]); mtex_ar[slot] = NULL; } - else if (GS(id->name) == ID_MA) { - /* Reset this slot's ON/OFF toggle, for materials, when slot was empty. */ - ((Material *)id)->septex &= ~(1 << slot); - } mtex_ar[slot] = BKE_texture_mtex_add(); @@ -498,9 +432,6 @@ MTex *BKE_texture_mtex_add_id(ID *id, int slot) */ void BKE_texture_copy_data(Main *bmain, Tex *tex_dst, const Tex *tex_src, const int flag) { - /* We never handle usercount here for own data. */ - const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT; - if (!BKE_texture_is_image_user(tex_src)) { tex_dst->ima = NULL; } @@ -508,19 +439,6 @@ void BKE_texture_copy_data(Main *bmain, Tex *tex_dst, const Tex *tex_src, const if (tex_dst->coba) { tex_dst->coba = MEM_dupallocN(tex_dst->coba); } - if (tex_dst->env) { - tex_dst->env = BKE_texture_envmap_copy(tex_dst->env, flag_subdata); - } - if (tex_dst->pd) { - tex_dst->pd = BKE_texture_pointdensity_copy(tex_dst->pd, flag_subdata); - } - if (tex_dst->vd) { - tex_dst->vd = MEM_dupallocN(tex_dst->vd); - } - if (tex_dst->ot) { - tex_dst->ot = BKE_texture_ocean_copy(tex_dst->ot, flag_subdata); - } - if (tex_src->nodetree) { if (tex_src->nodetree->execdata) { ntreeTexEndExecTree(tex_src->nodetree->execdata); @@ -562,19 +480,6 @@ Tex *BKE_texture_localize(Tex *tex) /* image texture: BKE_texture_free also doesn't decrease */ if (texn->coba) texn->coba = MEM_dupallocN(texn->coba); - if (texn->env) { - texn->env = BKE_texture_envmap_copy(texn->env, LIB_ID_CREATE_NO_USER_REFCOUNT); - id_us_min(&texn->env->ima->id); - } - if (texn->pd) texn->pd = BKE_texture_pointdensity_copy(texn->pd, LIB_ID_CREATE_NO_USER_REFCOUNT); - if (texn->vd) { - texn->vd = MEM_dupallocN(texn->vd); - if (texn->vd->dataset) - texn->vd->dataset = MEM_dupallocN(texn->vd->dataset); - } - if (texn->ot) { - texn->ot = BKE_texture_ocean_copy(tex->ot, LIB_ID_CREATE_NO_USER_REFCOUNT); - } texn->preview = NULL; @@ -593,64 +498,6 @@ void BKE_texture_make_local(Main *bmain, Tex *tex, const bool lib_local) BKE_id_make_local_generic(bmain, &tex->id, true, lib_local); } -Tex *give_current_object_texture(Object *ob) -{ - Material *ma, *node_ma; - Tex *tex = NULL; - - if (ob == NULL) return NULL; - if (ob->totcol == 0 && !(ob->type == OB_LAMP)) return NULL; - - if (ob->type == OB_LAMP) { - tex = give_current_lamp_texture(ob->data); - } - else { - ma = give_current_material(ob, ob->actcol); - - if ((node_ma = give_node_material(ma))) - ma = node_ma; - - tex = give_current_material_texture(ma); - } - - return tex; -} - -Tex *give_current_lamp_texture(Lamp *la) -{ - MTex *mtex = NULL; - Tex *tex = NULL; - - if (la) { - mtex = la->mtex[(int)(la->texact)]; - if (mtex) tex = mtex->tex; - } - - return tex; -} - -void set_current_lamp_texture(Lamp *la, Tex *newtex) -{ - int act = la->texact; - - if (la->mtex[act] && la->mtex[act]->tex) - id_us_min(&la->mtex[act]->tex->id); - - if (newtex) { - if (!la->mtex[act]) { - la->mtex[act] = BKE_texture_mtex_add(); - la->mtex[act]->texco = TEXCO_GLOB; - } - - la->mtex[act]->tex = newtex; - id_us_plus(&newtex->id); - } - else if (la->mtex[act]) { - MEM_freeN(la->mtex[act]); - la->mtex[act] = NULL; - } -} - Tex *give_current_linestyle_texture(FreestyleLineStyle *linestyle) { MTex *mtex = NULL; @@ -686,55 +533,9 @@ void set_current_linestyle_texture(FreestyleLineStyle *linestyle, Tex *newtex) } } -bNode *give_current_material_texture_node(Material *ma) -{ - if (ma && ma->use_nodes && ma->nodetree) - return nodeGetActiveID(ma->nodetree, ID_TE); - - return NULL; -} - -Tex *give_current_material_texture(Material *ma) -{ - MTex *mtex = NULL; - Tex *tex = NULL; - bNode *node; - - if (ma && ma->use_nodes && ma->nodetree) { - /* first check texture, then material, this works together - * with a hack that clears the active ID flag for textures on - * making a material node active */ - node = nodeGetActiveID(ma->nodetree, ID_TE); - - if (node) { - tex = (Tex *)node->id; - ma = NULL; - } - } - - if (ma) { - mtex = ma->mtex[(int)(ma->texact)]; - if (mtex) tex = mtex->tex; - } - - return tex; -} - bool give_active_mtex(ID *id, MTex ***mtex_ar, short *act) { switch (GS(id->name)) { - case ID_MA: - *mtex_ar = ((Material *)id)->mtex; - if (act) *act = (((Material *)id)->texact); - break; - case ID_WO: - *mtex_ar = ((World *)id)->mtex; - if (act) *act = (((World *)id)->texact); - break; - case ID_LA: - *mtex_ar = ((Lamp *)id)->mtex; - if (act) *act = (((Lamp *)id)->texact); - break; case ID_LS: *mtex_ar = ((FreestyleLineStyle *)id)->mtex; if (act) *act = (((FreestyleLineStyle *)id)->texact); @@ -758,15 +559,6 @@ void set_active_mtex(ID *id, short act) else if (act >= MAX_MTEX) act = MAX_MTEX - 1; switch (GS(id->name)) { - case ID_MA: - ((Material *)id)->texact = act; - break; - case ID_WO: - ((World *)id)->texact = act; - break; - case ID_LA: - ((Lamp *)id)->texact = act; - break; case ID_LS: ((FreestyleLineStyle *)id)->texact = act; break; @@ -778,100 +570,6 @@ void set_active_mtex(ID *id, short act) } } -void set_current_material_texture(Material *ma, Tex *newtex) -{ - Tex *tex = NULL; - bNode *node; - - if ((ma->use_nodes && ma->nodetree) && - (node = nodeGetActiveID(ma->nodetree, ID_TE))) - { - tex = (Tex *)node->id; - id_us_min(&tex->id); - if (newtex) { - node->id = &newtex->id; - id_us_plus(&newtex->id); - } - else { - node->id = NULL; - } - } - else { - int act = (int)ma->texact; - - tex = (ma->mtex[act]) ? ma->mtex[act]->tex : NULL; - id_us_min(&tex->id); - - if (newtex) { - if (!ma->mtex[act]) { - ma->mtex[act] = BKE_texture_mtex_add(); - /* Reset this slot's ON/OFF toggle, for materials, when slot was empty. */ - ma->septex &= ~(1 << act); - /* For volumes the default UV texture coordinates are not available. */ - if (ma->material_type == MA_TYPE_VOLUME) { - ma->mtex[act]->texco = TEXCO_ORCO; - } - } - - ma->mtex[act]->tex = newtex; - id_us_plus(&newtex->id); - } - else if (ma->mtex[act]) { - MEM_freeN(ma->mtex[act]); - ma->mtex[act] = NULL; - } - } -} - -bool has_current_material_texture(Material *ma) -{ - bNode *node; - - if (ma && ma->use_nodes && ma->nodetree) { - node = nodeGetActiveID(ma->nodetree, ID_TE); - - if (node) - return true; - } - - return (ma != NULL); -} - -Tex *give_current_world_texture(World *world) -{ - MTex *mtex = NULL; - Tex *tex = NULL; - - if (!world) return NULL; - - mtex = world->mtex[(int)(world->texact)]; - if (mtex) tex = mtex->tex; - - return tex; -} - -void set_current_world_texture(World *wo, Tex *newtex) -{ - int act = wo->texact; - - if (wo->mtex[act] && wo->mtex[act]->tex) - id_us_min(&wo->mtex[act]->tex->id); - - if (newtex) { - if (!wo->mtex[act]) { - wo->mtex[act] = BKE_texture_mtex_add(); - wo->mtex[act]->texco = TEXCO_VIEW; - } - - wo->mtex[act]->tex = newtex; - id_us_plus(&newtex->id); - } - else if (wo->mtex[act]) { - MEM_freeN(wo->mtex[act]); - wo->mtex[act] = NULL; - } -} - Tex *give_current_brush_texture(Brush *br) { return br->mtex.tex; @@ -926,65 +624,6 @@ void set_current_particle_texture(ParticleSettings *part, Tex *newtex) /* ------------------------------------------------------------------------- */ -EnvMap *BKE_texture_envmap_add(void) -{ - EnvMap *env; - - env = MEM_callocN(sizeof(EnvMap), "envmap"); - env->type = ENV_CUBE; - env->stype = ENV_ANIM; - env->clipsta = 0.1; - env->clipend = 100.0; - env->cuberes = 512; - env->viewscale = 0.5; - - return env; -} - -/* ------------------------------------------------------------------------- */ - -EnvMap *BKE_texture_envmap_copy(const EnvMap *env, const int flag) -{ - EnvMap *envn; - int a; - - envn = MEM_dupallocN(env); - envn->ok = 0; - for (a = 0; a < 6; a++) { - envn->cube[a] = NULL; - } - if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) { - id_us_plus((ID *)envn->ima); - } - - return envn; -} - -/* ------------------------------------------------------------------------- */ - -void BKE_texture_envmap_free_data(EnvMap *env) -{ - unsigned int part; - - for (part = 0; part < 6; part++) { - if (env->cube[part]) - IMB_freeImBuf(env->cube[part]); - env->cube[part] = NULL; - } - env->ok = 0; -} - -/* ------------------------------------------------------------------------- */ - -void BKE_texture_envmap_free(EnvMap *env) -{ - - BKE_texture_envmap_free_data(env); - MEM_freeN(env); - -} - -/* ------------------------------------------------------------------------- */ void BKE_texture_pointdensity_init_data(PointDensity *pd) { @@ -1057,77 +696,8 @@ void BKE_texture_pointdensity_free(PointDensity *pd) BKE_texture_pointdensity_free_data(pd); MEM_freeN(pd); } - /* ------------------------------------------------------------------------- */ -void BKE_texture_voxeldata_free_data(VoxelData *vd) -{ - if (vd->dataset) { - MEM_freeN(vd->dataset); - vd->dataset = NULL; - } - -} - -void BKE_texture_voxeldata_free(VoxelData *vd) -{ - BKE_texture_voxeldata_free_data(vd); - MEM_freeN(vd); -} - -VoxelData *BKE_texture_voxeldata_add(void) -{ - VoxelData *vd; - - vd = MEM_callocN(sizeof(VoxelData), "voxeldata"); - vd->dataset = NULL; - vd->resol[0] = vd->resol[1] = vd->resol[2] = 1; - vd->interp_type = TEX_VD_LINEAR; - vd->file_format = TEX_VD_SMOKE; - vd->int_multiplier = 1.0; - vd->extend = TEX_CLIP; - vd->object = NULL; - vd->cachedframe = -1; - vd->ok = 0; - - return vd; -} - -VoxelData *BKE_texture_voxeldata_copy(VoxelData *vd) -{ - VoxelData *vdn; - - vdn = MEM_dupallocN(vd); - vdn->dataset = NULL; - - return vdn; -} - -/* ------------------------------------------------------------------------- */ - -OceanTex *BKE_texture_ocean_add(void) -{ - OceanTex *ot; - - ot = MEM_callocN(sizeof(struct OceanTex), "ocean texture"); - ot->output = TEX_OCN_DISPLACEMENT; - ot->object = NULL; - - return ot; -} - -OceanTex *BKE_texture_ocean_copy(const OceanTex *ot, const int UNUSED(flag)) -{ - OceanTex *otn = MEM_dupallocN(ot); - - return otn; -} - -void BKE_texture_ocean_free(struct OceanTex *ot) -{ - MEM_freeN(ot); -} - /** * \returns true if this texture can use its #Texture.ima (even if its NULL) */ @@ -1138,15 +708,6 @@ bool BKE_texture_is_image_user(const struct Tex *tex) { return true; } - case TEX_ENVMAP: - { - if (tex->env) { - if (tex->env->stype == ENV_LOAD) { - return true; - } - } - break; - } } return false; diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c index f9d34534a45..3314e8d01b6 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_context_active_PLACEHOLDER(scene)); } if (ob) diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c index 5a0081bff16..62710240109 100644 --- a/source/blender/blenkernel/intern/undo_system.c +++ b/source/blender/blenkernel/intern/undo_system.c @@ -39,6 +39,7 @@ #include "BKE_context.h" #include "BKE_global.h" +#include "BKE_library_override.h" #include "BKE_main.h" #include "BKE_undo_system.h" @@ -386,12 +387,19 @@ UndoStep *BKE_undosys_step_push_init(UndoStack *ustack, bContext *C, const char return BKE_undosys_step_push_init_with_type(ustack, C, name, ut); } +/** + * \param C: Can be NULL from some callers if their encoding function doesn't need it + */ bool BKE_undosys_step_push_with_type(UndoStack *ustack, bContext *C, const char *name, const UndoType *ut) { UNDO_NESTED_ASSERT(false); undosys_stack_validate(ustack, false); bool is_not_empty = ustack->step_active != NULL; + /* Might not be final place for this to be called - probably only want to call it from some + * undo handlers, not all of them? */ + BKE_main_override_static_operations_create(G.main, false); + /* Remove all undos after (also when 'ustack->step_active == NULL'). */ while (ustack->steps.last != ustack->step_active) { UndoStep *us_iter = ustack->steps.last; diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c new file mode 100644 index 00000000000..38378f66584 --- /dev/null +++ b/source/blender/blenkernel/intern/workspace.c @@ -0,0 +1,470 @@ +/* + * ***** 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_object.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->owner_ids); + BLI_freelistN(&workspace->layouts); +} + +/** + * 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); + } +} + +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) { + LISTBASE_CIRCULAR_BACKWARD_BEGIN(&workspace->layouts, iter_layout, start) + { + if (!callback(iter_layout, arg)) { + return iter_layout; + } + } + LISTBASE_CIRCULAR_BACKWARD_END(&workspace->layouts, iter_layout, start); + } + else { + LISTBASE_CIRCULAR_FORWARD_BEGIN(&workspace->layouts, iter_layout, start) + { + if (!callback(iter_layout, arg)) { + return iter_layout; + } + } + 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; +} + +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); +} + +/* Update / evaluate */ + +void BKE_workspace_update_tagged(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(depsgraph, bmain); +} + + +bool BKE_workspace_owner_id_check( + const WorkSpace *workspace, const char *owner_id) +{ + if ((*owner_id == '\0') || + ((workspace->flags & WORKSPACE_USE_FILTER_BY_ORIGIN) == 0)) + { + return true; + } + else { + /* we could use hash lookup, for now this list is highly under < ~16 items. */ + return BLI_findstring(&workspace->owner_ids, owner_id, offsetof(wmOwnerID, name)) != NULL; + } +} + diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c index 5736c9331bf..15bf01d2049 100644 --- a/source/blender/blenkernel/intern/world.c +++ b/source/blender/blenkernel/intern/world.c @@ -33,6 +33,7 @@ #include <string.h> #include <stdlib.h> #include <math.h> + #include "MEM_guardedalloc.h" #include "DNA_world_types.h" @@ -43,6 +44,7 @@ #include "BLI_listbase.h" #include "BKE_animsys.h" +#include "BKE_global.h" #include "BKE_icons.h" #include "BKE_library.h" #include "BKE_library_query.h" @@ -56,14 +58,8 @@ /** Free (or release) any data used by this world (does not free the world itself). */ void BKE_world_free(World *wrld) { - int a; - BKE_animdata_free((ID *)wrld, false); - for (a = 0; a < MAX_MTEX; a++) { - MEM_SAFE_FREE(wrld->mtex[a]); - } - /* is no lib link block, but world extension */ if (wrld->nodetree) { ntreeFreeTree(wrld->nodetree); @@ -84,23 +80,9 @@ void BKE_world_init(World *wrld) wrld->horr = 0.05f; wrld->horg = 0.05f; wrld->horb = 0.05f; - wrld->zenr = 0.01f; - wrld->zeng = 0.01f; - wrld->zenb = 0.01f; - wrld->skytype = 0; - - wrld->exp = 0.0f; - wrld->exposure = wrld->range = 1.0f; wrld->aodist = 10.0f; - wrld->aosamp = 5; wrld->aoenergy = 1.0f; - wrld->ao_env_energy = 1.0f; - wrld->ao_indirect_energy = 1.0f; - wrld->ao_indirect_bounces = 1; - wrld->aobias = 0.05f; - wrld->ao_samp_method = WO_AOSAMP_HAMMERSLEY; - wrld->ao_approx_error = 0.25f; wrld->preview = NULL; wrld->miststa = 5.0f; @@ -128,12 +110,6 @@ World *BKE_world_add(Main *bmain, const char *name) */ void BKE_world_copy_data(Main *bmain, World *wrld_dst, const World *wrld_src, const int flag) { - for (int a = 0; a < MAX_MTEX; a++) { - if (wrld_src->mtex[a]) { - wrld_dst->mtex[a] = MEM_dupallocN(wrld_src->mtex[a]); - } - } - if (wrld_src->nodetree) { /* Note: nodetree is *not* in bmain, however this specific case is handled at lower level * (see BKE_libblock_copy_ex()). */ @@ -167,17 +143,9 @@ World *BKE_world_localize(World *wrld) * ... Once f*** nodes are fully converted to that too :( */ World *wrldn; - int a; wrldn = BKE_libblock_copy_nolib(&wrld->id, false); - for (a = 0; a < MAX_MTEX; a++) { - if (wrld->mtex[a]) { - wrldn->mtex[a] = MEM_mallocN(sizeof(MTex), __func__); - memcpy(wrldn->mtex[a], wrld->mtex[a], sizeof(MTex)); - } - } - if (wrld->nodetree) wrldn->nodetree = ntreeLocalize(wrld->nodetree); @@ -192,3 +160,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(struct Depsgraph *UNUSED(depsgraph), World *world) +{ + if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) { + 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 d7fcd896e11..39174620961 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" @@ -326,10 +326,6 @@ static int write_video_frame(FFMpegContext *context, RenderData *rd, int cfra, A frame->pts = cfra; - if (rd->mode & R_FIELDS) { - frame->top_field_first = ((rd->mode & R_ODDFIELD) != 0); - } - ret = avcodec_encode_video2(c, &packet, frame, &got_output); if (ret >= 0 && got_output) { @@ -685,13 +681,6 @@ static AVStream *alloc_video_stream(FFMpegContext *context, RenderData *rd, int c->flags |= CODEC_FLAG_GLOBAL_HEADER; } - /* Determine whether we are encoding interlaced material or not */ - if (rd->mode & R_FIELDS) { - PRINT("Encoding interlaced video\n"); - c->flags |= CODEC_FLAG_INTERLACED_DCT; - c->flags |= CODEC_FLAG_INTERLACED_ME; - } - /* xasp & yasp got float lately... */ st->sample_aspect_ratio = c->sample_aspect_ratio = av_d2q(((double) rd->xasp / (double) rd->yasp), 255); |