Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h74
-rw-r--r--source/blender/blenkernel/BKE_anim.h9
-rw-r--r--source/blender/blenkernel/BKE_animsys.h8
-rw-r--r--source/blender/blenkernel/BKE_appdir.h1
-rw-r--r--source/blender/blenkernel/BKE_armature.h32
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h4
-rw-r--r--source/blender/blenkernel/BKE_blendfile.h4
-rw-r--r--source/blender/blenkernel/BKE_cachefile.h2
-rw-r--r--source/blender/blenkernel/BKE_camera.h8
-rw-r--r--source/blender/blenkernel/BKE_cloth.h3
-rw-r--r--source/blender/blenkernel/BKE_collection.h107
-rw-r--r--source/blender/blenkernel/BKE_collision.h2
-rw-r--r--source/blender/blenkernel/BKE_constraint.h10
-rw-r--r--source/blender/blenkernel/BKE_context.h24
-rw-r--r--source/blender/blenkernel/BKE_crazyspace.h9
-rw-r--r--source/blender/blenkernel/BKE_curve.h23
-rw-r--r--source/blender/blenkernel/BKE_customdata.h11
-rw-r--r--source/blender/blenkernel/BKE_data_transfer.h8
-rw-r--r--source/blender/blenkernel/BKE_depsgraph.h181
-rw-r--r--source/blender/blenkernel/BKE_displist.h29
-rw-r--r--source/blender/blenkernel/BKE_dynamicpaint.h7
-rw-r--r--source/blender/blenkernel/BKE_editmesh.h5
-rw-r--r--source/blender/blenkernel/BKE_editmesh_tangent.h40
-rw-r--r--source/blender/blenkernel/BKE_effect.h8
-rw-r--r--source/blender/blenkernel/BKE_fluidsim.h3
-rw-r--r--source/blender/blenkernel/BKE_freestyle.h2
-rw-r--r--source/blender/blenkernel/BKE_global.h3
-rw-r--r--source/blender/blenkernel/BKE_group.h34
-rw-r--r--source/blender/blenkernel/BKE_idprop.h1
-rw-r--r--source/blender/blenkernel/BKE_lamp.h2
-rw-r--r--source/blender/blenkernel/BKE_lattice.h22
-rw-r--r--source/blender/blenkernel/BKE_layer.h292
-rw-r--r--source/blender/blenkernel/BKE_library.h3
-rw-r--r--source/blender/blenkernel/BKE_library_override.h87
-rw-r--r--source/blender/blenkernel/BKE_library_query.h3
-rw-r--r--source/blender/blenkernel/BKE_library_remap.h2
-rw-r--r--source/blender/blenkernel/BKE_lightprobe.h46
-rw-r--r--source/blender/blenkernel/BKE_main.h2
-rw-r--r--source/blender/blenkernel/BKE_mask.h1
-rw-r--r--source/blender/blenkernel/BKE_material.h14
-rw-r--r--source/blender/blenkernel/BKE_mball.h13
-rw-r--r--source/blender/blenkernel/BKE_mball_tessellate.h2
-rw-r--r--source/blender/blenkernel/BKE_mesh.h34
-rw-r--r--source/blender/blenkernel/BKE_mesh_tangent.h61
-rw-r--r--source/blender/blenkernel/BKE_modifier.h55
-rw-r--r--source/blender/blenkernel/BKE_multires.h13
-rw-r--r--source/blender/blenkernel/BKE_node.h31
-rw-r--r--source/blender/blenkernel/BKE_object.h98
-rw-r--r--source/blender/blenkernel/BKE_object_facemap.h53
-rw-r--r--source/blender/blenkernel/BKE_outliner_treehash.h3
-rw-r--r--source/blender/blenkernel/BKE_paint.h13
-rw-r--r--source/blender/blenkernel/BKE_particle.h27
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h5
-rw-r--r--source/blender/blenkernel/BKE_pointcache.h5
-rw-r--r--source/blender/blenkernel/BKE_rigidbody.h13
-rw-r--r--source/blender/blenkernel/BKE_scene.h100
-rw-r--r--source/blender/blenkernel/BKE_screen.h37
-rw-r--r--source/blender/blenkernel/BKE_sequencer.h3
-rw-r--r--source/blender/blenkernel/BKE_smoke.h4
-rw-r--r--source/blender/blenkernel/BKE_softbody.h4
-rw-r--r--source/blender/blenkernel/BKE_sound.h8
-rw-r--r--source/blender/blenkernel/BKE_tracking.h1
-rw-r--r--source/blender/blenkernel/BKE_workspace.h155
-rw-r--r--source/blender/blenkernel/BKE_world.h6
-rw-r--r--source/blender/blenkernel/CMakeLists.txt30
-rw-r--r--source/blender/blenkernel/depsgraph_private.h169
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf.c2
-rw-r--r--source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c4
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c680
-rw-r--r--source/blender/blenkernel/intern/action.c10
-rw-r--r--source/blender/blenkernel/intern/anim.c102
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c49
-rw-r--r--source/blender/blenkernel/intern/armature.c40
-rw-r--r--source/blender/blenkernel/intern/armature_update.c67
-rw-r--r--source/blender/blenkernel/intern/blender.c10
-rw-r--r--source/blender/blenkernel/intern/blender_copybuffer.c17
-rw-r--r--source/blender/blenkernel/intern/blender_undo.c5
-rw-r--r--source/blender/blenkernel/intern/blendfile.c113
-rw-r--r--source/blender/blenkernel/intern/boids.c1
-rw-r--r--source/blender/blenkernel/intern/cachefile.c8
-rw-r--r--source/blender/blenkernel/intern/camera.c73
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c318
-rw-r--r--source/blender/blenkernel/intern/cloth.c13
-rw-r--r--source/blender/blenkernel/intern/collection.c848
-rw-r--r--source/blender/blenkernel/intern/collision.c46
-rw-r--r--source/blender/blenkernel/intern/constraint.c75
-rw-r--r--source/blender/blenkernel/intern/context.c142
-rw-r--r--source/blender/blenkernel/intern/crazyspace.c26
-rw-r--r--source/blender/blenkernel/intern/curve.c38
-rw-r--r--source/blender/blenkernel/intern/customdata.c112
-rw-r--r--source/blender/blenkernel/intern/data_transfer.c25
-rw-r--r--source/blender/blenkernel/intern/deform.c3
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c3739
-rw-r--r--source/blender/blenkernel/intern/displist.c106
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c115
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c693
-rw-r--r--source/blender/blenkernel/intern/editmesh.c20
-rw-r--r--source/blender/blenkernel/intern/editmesh_tangent.c431
-rw-r--r--source/blender/blenkernel/intern/effect.c89
-rw-r--r--source/blender/blenkernel/intern/fluidsim.c4
-rw-r--r--source/blender/blenkernel/intern/freestyle.c10
-rw-r--r--source/blender/blenkernel/intern/group.c195
-rw-r--r--source/blender/blenkernel/intern/icons.c2
-rw-r--r--source/blender/blenkernel/intern/idcode.c9
-rw-r--r--source/blender/blenkernel/intern/idprop.c35
-rw-r--r--source/blender/blenkernel/intern/image.c21
-rw-r--r--source/blender/blenkernel/intern/lamp.c47
-rw-r--r--source/blender/blenkernel/intern/lattice.c52
-rw-r--r--source/blender/blenkernel/intern/layer.c2195
-rw-r--r--source/blender/blenkernel/intern/library.c113
-rw-r--r--source/blender/blenkernel/intern/library_override.c752
-rw-r--r--source/blender/blenkernel/intern/library_query.c158
-rw-r--r--source/blender/blenkernel/intern/library_remap.c95
-rw-r--r--source/blender/blenkernel/intern/lightprobe.c100
-rw-r--r--source/blender/blenkernel/intern/linestyle.c13
-rw-r--r--source/blender/blenkernel/intern/mask.c17
-rw-r--r--source/blender/blenkernel/intern/mask_evaluate.c3
-rw-r--r--source/blender/blenkernel/intern/material.c590
-rw-r--r--source/blender/blenkernel/intern/mball.c84
-rw-r--r--source/blender/blenkernel/intern/mball_tessellate.c9
-rw-r--r--source/blender/blenkernel/intern/mesh.c189
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c204
-rw-r--r--source/blender/blenkernel/intern/mesh_tangent.c690
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c84
-rw-r--r--source/blender/blenkernel/intern/modifier.c22
-rw-r--r--source/blender/blenkernel/intern/multires.c38
-rw-r--r--source/blender/blenkernel/intern/nla.c2
-rw-r--r--source/blender/blenkernel/intern/node.c63
-rw-r--r--source/blender/blenkernel/intern/object.c278
-rw-r--r--source/blender/blenkernel/intern/object_deform.c3
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c172
-rw-r--r--source/blender/blenkernel/intern/object_facemap.c257
-rw-r--r--source/blender/blenkernel/intern/object_update.c212
-rw-r--r--source/blender/blenkernel/intern/outliner_treehash.c39
-rw-r--r--source/blender/blenkernel/intern/paint.c49
-rw-r--r--source/blender/blenkernel/intern/particle.c93
-rw-r--r--source/blender/blenkernel/intern/particle_child.c2
-rw-r--r--source/blender/blenkernel/intern/particle_distribute.c11
-rw-r--r--source/blender/blenkernel/intern/particle_system.c67
-rw-r--r--source/blender/blenkernel/intern/pbvh.c109
-rw-r--r--source/blender/blenkernel/intern/pointcache.c13
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c183
-rw-r--r--source/blender/blenkernel/intern/scene.c1385
-rw-r--r--source/blender/blenkernel/intern/screen.c113
-rw-r--r--source/blender/blenkernel/intern/sequencer.c29
-rw-r--r--source/blender/blenkernel/intern/smoke.c40
-rw-r--r--source/blender/blenkernel/intern/softbody.c129
-rw-r--r--source/blender/blenkernel/intern/sound.c168
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c264
-rw-r--r--source/blender/blenkernel/intern/text.c1
-rw-r--r--source/blender/blenkernel/intern/tracking.c3
-rw-r--r--source/blender/blenkernel/intern/workspace.c523
-rw-r--r--source/blender/blenkernel/intern/world.c11
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c4
154 files changed, 10542 insertions, 9501 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 700bfe568f1..9bb44a726de 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -98,6 +98,7 @@ struct ColorBand;
struct GPUVertexAttribs;
struct GPUDrawObject;
struct PBVH;
+struct EvaluationContext;
/* number of sub-elements each mesh element has (for interpolation) */
#define SUB_ELEMS_VERT 0
@@ -142,8 +143,6 @@ typedef int (*DMSetMaterial)(int mat_nr, void *attribs);
typedef int (*DMCompareDrawOptions)(void *userData, int cur_index, int next_index);
typedef void (*DMSetDrawInterpOptions)(void *userData, int index, float t);
typedef DMDrawOption (*DMSetDrawOptions)(void *userData, int index);
-typedef DMDrawOption (*DMSetDrawOptionsMappedTex)(void *userData, int origindex, int mat_nr);
-typedef DMDrawOption (*DMSetDrawOptionsTex)(struct MTexPoly *mtexpoly, const bool has_vcol, int matnr);
typedef enum DMDrawFlag {
DM_DRAW_USE_COLORS = (1 << 0),
@@ -389,9 +388,6 @@ struct DerivedMesh {
/** Draw all vertices as bgl points (no options) */
void (*drawVerts)(DerivedMesh *dm);
- /** Draw edges in the UV mesh (if exists) */
- void (*drawUVEdges)(DerivedMesh *dm);
-
/** Draw all edges as lines (no options)
*
* Also called for *final* editmode DerivedMeshes
@@ -411,14 +407,6 @@ struct DerivedMesh {
void (*drawFacesSolid)(DerivedMesh *dm, float (*partial_redraw_planes)[4],
bool fast, DMSetMaterial setMaterial);
- /** Draw all faces using MTFace
- * - Drawing options too complicated to enumerate, look at code.
- */
- void (*drawFacesTex)(DerivedMesh *dm,
- DMSetDrawOptionsTex setDrawOptions,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag flag);
-
/** Draw all faces with GLSL materials
* o setMaterial is called for every different material nr
* o Only if setMaterial returns true
@@ -445,14 +433,6 @@ struct DerivedMesh {
void *userData,
DMDrawFlag flag);
- /** Draw mapped faces using MTFace
- * - Drawing options too complicated to enumerate, look at code.
- */
- void (*drawMappedFacesTex)(DerivedMesh *dm,
- DMSetDrawOptionsMappedTex setDrawOptions,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag flag);
-
/** Draw mapped faces with GLSL materials
* - setMaterial is called for every different material nr
* - setDrawOptions is called for every face
@@ -680,56 +660,56 @@ void mesh_get_mapped_verts_coords(DerivedMesh *dm, float (*r_cos)[3], const int
/* */
DerivedMesh *mesh_get_derived_final(
- struct Scene *scene, struct Object *ob,
- CustomDataMask dataMask);
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct Object *ob, CustomDataMask dataMask);
DerivedMesh *mesh_get_derived_deform(
- struct Scene *scene, struct Object *ob,
- CustomDataMask dataMask);
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct Object *ob, CustomDataMask dataMask);
DerivedMesh *mesh_create_derived_for_modifier(
- struct Scene *scene, struct Object *ob,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob,
struct ModifierData *md, int build_shapekey_layers);
DerivedMesh *mesh_create_derived_render(
- struct Scene *scene, struct Object *ob,
- CustomDataMask dataMask);
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct Object *ob, CustomDataMask dataMask);
DerivedMesh *getEditDerivedBMesh(
struct BMEditMesh *em, struct Object *ob, CustomDataMask data_mask,
float (*vertexCos)[3]);
DerivedMesh *mesh_create_derived_index_render(
- struct Scene *scene, struct Object *ob,
- CustomDataMask dataMask, int index);
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct Object *ob, CustomDataMask dataMask, int index);
/* same as above but wont use render settings */
DerivedMesh *mesh_create_derived(struct Mesh *me, float (*vertCos)[3]);
DerivedMesh *mesh_create_derived_view(
- struct Scene *scene, struct Object *ob,
- CustomDataMask dataMask);
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct Object *ob, CustomDataMask dataMask);
DerivedMesh *mesh_create_derived_no_deform(
- struct Scene *scene, struct Object *ob,
- float (*vertCos)[3],
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct Object *ob, float (*vertCos)[3],
CustomDataMask dataMask);
DerivedMesh *mesh_create_derived_no_deform_render(
- struct Scene *scene, struct Object *ob,
- float (*vertCos)[3],
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct Object *ob, float (*vertCos)[3],
CustomDataMask dataMask);
/* for gameengine */
DerivedMesh *mesh_create_derived_no_virtual(
- struct Scene *scene, struct Object *ob, float (*vertCos)[3],
- CustomDataMask dataMask);
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob,
+ float (*vertCos)[3], CustomDataMask dataMask);
DerivedMesh *mesh_create_derived_physics(
- struct Scene *scene, struct Object *ob, float (*vertCos)[3],
- CustomDataMask dataMask);
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob,
+ float (*vertCos)[3], CustomDataMask dataMask);
DerivedMesh *editbmesh_get_derived_base(
struct Object *ob, struct BMEditMesh *em, CustomDataMask data_mask);
DerivedMesh *editbmesh_get_derived_cage(
- struct Scene *scene, struct Object *,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *,
struct BMEditMesh *em, CustomDataMask dataMask);
DerivedMesh *editbmesh_get_derived_cage_and_final(
- struct Scene *scene, struct Object *,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *,
struct BMEditMesh *em, CustomDataMask dataMask,
DerivedMesh **r_final);
@@ -738,7 +718,7 @@ DerivedMesh *object_get_derived_final(struct Object *ob, const bool for_render);
float (*editbmesh_get_vertex_cos(struct BMEditMesh *em, int *r_numVerts))[3];
bool editbmesh_modifier_is_enabled(struct Scene *scene, struct ModifierData *md, DerivedMesh *dm);
void makeDerivedMesh(
- struct Scene *scene, struct Object *ob, struct BMEditMesh *em,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct BMEditMesh *em,
CustomDataMask dataMask, const bool build_shapekey_layers);
void weight_to_rgb(float r_rgb[3], const float weight);
@@ -789,19 +769,15 @@ void DM_draw_attrib_vertex_uniforms(const DMVertexAttribs *attribs);
void DM_calc_tangents_names_from_gpu(
const struct GPUVertexAttribs *gattribs,
char (*tangent_names)[MAX_NAME], int *tangent_names_count);
+
void DM_add_named_tangent_layer_for_uv(
CustomData *uv_data, CustomData *tan_data, int numLoopData,
const char *layer_name);
-#define DM_TANGENT_MASK_ORCO (1 << 9)
-void DM_calc_loop_tangents_step_0(
- const CustomData *loopData, bool calc_active_tangent,
- const char (*tangent_names)[MAX_NAME], int tangent_names_count,
- bool *rcalc_act, bool *rcalc_ren, int *ract_uv_n, int *rren_uv_n,
- char *ract_uv_name, char *rren_uv_name, short *rtangent_mask);
void DM_calc_loop_tangents(
DerivedMesh *dm, bool calc_active_tangent, const char (*tangent_names)[MAX_NAME],
int tangent_names_count);
+
void DM_calc_auto_bump_scale(DerivedMesh *dm);
/** Set object's bounding box based on DerivedMesh min/max data */
diff --git a/source/blender/blenkernel/BKE_anim.h b/source/blender/blenkernel/BKE_anim.h
index 584f0da323a..30a7bdb0a27 100644
--- a/source/blender/blenkernel/BKE_anim.h
+++ b/source/blender/blenkernel/BKE_anim.h
@@ -41,6 +41,7 @@ struct bAnimVizSettings;
struct bMotionPath;
struct bPoseChannel;
struct ReportList;
+struct Main;
/* ---------------------------------------------------- */
/* Animation Visualization */
@@ -53,7 +54,7 @@ void animviz_free_motionpath(struct bMotionPath *mpath);
struct bMotionPath *animviz_verify_motionpaths(struct ReportList *reports, struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan);
void animviz_get_object_motionpaths(struct Object *ob, ListBase *targets);
-void animviz_calc_motionpaths(struct Scene *scene, ListBase *targets);
+void animviz_calc_motionpaths(struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *scene, ListBase *targets);
/* ---------------------------------------------------- */
/* Curve Paths */
@@ -65,8 +66,8 @@ int where_on_path(struct Object *ob, float ctime, float vec[4], float dir[3], fl
/* ---------------------------------------------------- */
/* Dupli-Geometry */
-struct ListBase *object_duplilist_ex(struct EvaluationContext *eval_ctx, struct Scene *sce, struct Object *ob, bool update);
-struct ListBase *object_duplilist(struct EvaluationContext *eval_ctx, struct Scene *sce, struct Object *ob);
+struct ListBase *object_duplilist_ex(const struct EvaluationContext *eval_ctx, struct Scene *sce, struct Object *ob, bool update);
+struct ListBase *object_duplilist(const struct EvaluationContext *eval_ctx, struct Scene *sce, struct Object *ob);
void free_object_duplilist(struct ListBase *lb);
int count_duplilist(struct Object *ob);
@@ -80,7 +81,7 @@ typedef struct DupliApplyData {
DupliExtraData *extra;
} DupliApplyData;
-DupliApplyData *duplilist_apply(struct Object *ob, struct Scene *scene, struct ListBase *duplilist);
+DupliApplyData *duplilist_apply(const struct EvaluationContext *eval_ctx, struct Object *ob, struct Scene *scene, struct ListBase *duplilist);
void duplilist_restore(struct ListBase *duplilist, DupliApplyData *apply_data);
void duplilist_free_apply_data(DupliApplyData *apply_data);
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index a70690d4029..d95b4a838b8 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -47,6 +47,7 @@ struct ReportList;
struct bAction;
struct bActionGroup;
struct AnimMapper;
+struct FCurve;
/* ************************************* */
/* AnimData API */
@@ -148,7 +149,7 @@ char *BKE_animdata_driver_path_hack(struct bContext *C, struct PointerRNA *ptr,
char *base_path);
/* ************************************* */
-/* Batch AnimData API */
+/* Gwn_Batch AnimData API */
/* Define for callback looper used in BKE_animdata_main_cb */
typedef void (*ID_AnimData_Edit_Callback)(struct ID *id, struct AnimData *adt, void *user_data);
@@ -179,7 +180,6 @@ void BKE_animsys_evaluate_animdata(struct Scene *scene, struct ID *id, struct An
void BKE_animsys_evaluate_all_animation(struct Main *main, struct Scene *scene, float ctime);
/* TODO(sergey): This is mainly a temp public function. */
-struct FCurve;
bool BKE_animsys_execute_fcurve(struct PointerRNA *ptr, struct AnimMapper *remap, struct FCurve *fcu, float curval);
/* ------------ Specialized API --------------- */
@@ -202,8 +202,8 @@ void animsys_evaluate_action_group(struct PointerRNA *ptr, struct bAction *act,
struct EvaluationContext;
-void BKE_animsys_eval_animdata(struct EvaluationContext *eval_ctx, struct ID *id);
-void BKE_animsys_eval_driver(struct EvaluationContext *eval_ctx, struct ID *id, struct FCurve *fcurve);
+void BKE_animsys_eval_animdata(const struct EvaluationContext *eval_ctx, struct ID *id);
+void BKE_animsys_eval_driver(const struct EvaluationContext *eval_ctx, struct ID *id, struct FCurve *fcurve);
/* ************************************* */
diff --git a/source/blender/blenkernel/BKE_appdir.h b/source/blender/blenkernel/BKE_appdir.h
index ac8f861fa56..ffbdc6972f4 100644
--- a/source/blender/blenkernel/BKE_appdir.h
+++ b/source/blender/blenkernel/BKE_appdir.h
@@ -82,6 +82,7 @@ enum {
#define BLENDER_STARTUP_FILE "startup.blend"
#define BLENDER_USERPREF_FILE "userpref.blend"
+#define BLENDER_WORKSPACES_FILE "workspaces.blend"
#define BLENDER_QUIT_FILE "quit.blend"
#define BLENDER_BOOKMARK_FILE "bookmarks.txt"
#define BLENDER_HISTORY_FILE "recent-files.txt"
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index 60fb79d75d5..192690c074c 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -33,7 +33,9 @@
* \author nzc
*/
+struct bPose;
struct Bone;
+struct EvaluationContext;
struct GHash;
struct Main;
struct bArmature;
@@ -98,9 +100,8 @@ void BKE_armature_where_is(struct bArmature *arm);
void BKE_armature_where_is_bone(struct Bone *bone, struct Bone *prevbone, const bool use_recursion);
void BKE_pose_clear_pointers(struct bPose *pose);
void BKE_pose_rebuild(struct Object *ob, struct bArmature *arm);
-void BKE_pose_rebuild_ex(struct Object *ob, struct bArmature *arm, const bool sort_bones);
-void BKE_pose_where_is(struct Scene *scene, struct Object *ob);
-void BKE_pose_where_is_bone(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime, bool do_extra);
+void BKE_pose_where_is(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
+void BKE_pose_where_is_bone(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan, float ctime, bool do_extra);
void BKE_pose_where_is_bone_tail(struct bPoseChannel *pchan);
/* get_objectspace_bone_matrix has to be removed still */
@@ -117,7 +118,7 @@ void BKE_armature_loc_pose_to_bone(struct bPoseChannel *pchan, const float inloc
void BKE_armature_mat_bone_to_pose(struct bPoseChannel *pchan, float inmat[4][4], float outmat[4][4]);
void BKE_armature_mat_pose_to_delta(float delta_mat[4][4], float pose_mat[4][4], float arm_mat[4][4]);
-void BKE_armature_mat_pose_to_bone_ex(struct Object *ob, struct bPoseChannel *pchan, float inmat[4][4], float outmat[4][4]);
+void BKE_armature_mat_pose_to_bone_ex(const struct EvaluationContext *eval_ctx, struct Object *ob, struct bPoseChannel *pchan, float inmat[4][4], float outmat[4][4]);
void BKE_pchan_mat3_to_rot(struct bPoseChannel *pchan, float mat[3][3], bool use_compat);
void BKE_pchan_apply_mat4(struct bPoseChannel *pchan, float mat[4][4], bool use_comat);
@@ -155,7 +156,6 @@ void b_bone_spline_setup(struct bPoseChannel *pchan, int rest, Mat4 result_array
struct bKinematicConstraint;
struct bPose;
struct bSplineIKConstraint;
-struct EvaluationContext;
struct bPoseChannel *BKE_armature_ik_solver_find_root(
struct bPoseChannel *pchan,
@@ -165,47 +165,49 @@ struct bPoseChannel *BKE_armature_splineik_solver_find_root(
struct bSplineIKConstraint *data);
void BKE_pose_splineik_init_tree(struct Scene *scene, struct Object *ob, float ctime);
-void BKE_splineik_execute_tree(struct Scene *scene, struct Object *ob, struct bPoseChannel *pchan_root, float ctime);
+void BKE_splineik_execute_tree(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct Object *ob, struct bPoseChannel *pchan_root, float ctime);
-void BKE_pose_eval_init(struct EvaluationContext *eval_ctx,
+void BKE_pose_eval_init(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob,
struct bPose *pose);
-void BKE_pose_eval_init_ik(struct EvaluationContext *eval_ctx,
+void BKE_pose_eval_init_ik(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob,
struct bPose *pose);
-void BKE_pose_eval_bone(struct EvaluationContext *eval_ctx,
+void BKE_pose_eval_bone(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob,
struct bPoseChannel *pchan);
-void BKE_pose_constraints_evaluate(struct EvaluationContext *eval_ctx,
+void BKE_pose_constraints_evaluate(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob,
struct bPoseChannel *pchan);
-void BKE_pose_bone_done(struct EvaluationContext *eval_ctx,
+void BKE_pose_bone_done(const struct EvaluationContext *eval_ctx,
struct bPoseChannel *pchan);
-void BKE_pose_iktree_evaluate(struct EvaluationContext *eval_ctx,
+void BKE_pose_iktree_evaluate(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob,
struct bPoseChannel *rootchan);
-void BKE_pose_splineik_evaluate(struct EvaluationContext *eval_ctx,
+void BKE_pose_splineik_evaluate(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob,
struct bPoseChannel *rootchan);
-void BKE_pose_eval_flush(struct EvaluationContext *eval_ctx,
+void BKE_pose_eval_flush(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob,
struct bPose *pose);
-void BKE_pose_eval_proxy_copy(struct EvaluationContext *eval_ctx,
+void BKE_pose_eval_proxy_copy(const struct EvaluationContext *eval_ctx,
struct Object *ob);
#ifdef __cplusplus
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index f95b1963a91..27223afe4ff 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 1
+#define BLENDER_VERSION 280
+#define BLENDER_SUBVERSION 3
/* 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..f69ac7e01cd 100644
--- a/source/blender/blenkernel/BKE_camera.h
+++ b/source/blender/blenkernel/BKE_camera.h
@@ -44,6 +44,7 @@ struct Object;
struct RegionView3D;
struct RenderData;
struct Scene;
+struct ViewLayer;
struct rctf;
struct View3D;
struct GPUFXSettings;
@@ -128,7 +129,7 @@ void BKE_camera_view_frame(
float r_vec[4][3]);
bool BKE_camera_view_frame_fit_to_scene(
- struct Scene *scene, struct View3D *v3d, struct Object *camera_ob,
+ struct Scene *scene, struct ViewLayer *view_layer, struct Object *camera_ob,
float r_co[3], float *r_scale);
bool BKE_camera_view_frame_fit_to_coords(
const struct Scene *scene,
@@ -147,6 +148,11 @@ float BKE_camera_multiview_shift_x(struct RenderData *rd, struct Object
void BKE_camera_multiview_params(struct RenderData *rd, struct CameraParams *params, struct Object *camera, const char *viewname);
bool BKE_camera_multiview_spherical_stereo(struct RenderData *rd, struct Object *camera);
+/* Camera background image API */
+struct CameraBGImage *BKE_camera_background_image_new(struct Camera *cam);
+void BKE_camera_background_image_remove(struct Camera *cam, struct CameraBGImage *bgpic);
+void BKE_camera_background_image_clear(struct Camera *cam);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_cloth.h b/source/blender/blenkernel/BKE_cloth.h
index 6c517bd02df..7f7cbd678e2 100644
--- a/source/blender/blenkernel/BKE_cloth.h
+++ b/source/blender/blenkernel/BKE_cloth.h
@@ -41,6 +41,7 @@ struct MFace;
struct DerivedMesh;
struct ClothModifierData;
struct CollisionModifierData;
+struct EvaluationContext;
#define DO_INLINE MALWAYS_INLINE
@@ -226,7 +227,7 @@ void cloth_free_contacts(ColliderContacts *collider_contacts, int totcolliders);
void cloth_free_modifier_extern (struct ClothModifierData *clmd );
void cloth_free_modifier (struct ClothModifierData *clmd );
void cloth_init (struct ClothModifierData *clmd );
-void clothModifier_do (struct ClothModifierData *clmd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3]);
+void clothModifier_do(struct ClothModifierData *clmd, const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm, float (*vertexCos)[3]);
int cloth_uses_vgroup(struct ClothModifierData *clmd);
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
new file mode 100644
index 00000000000..48b4ff881ae
--- /dev/null
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -0,0 +1,107 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BKE_COLLECTION_H__
+#define __BKE_COLLECTION_H__
+
+/** \file blender/blenkernel/BKE_collection.h
+ * \ingroup bke
+ */
+
+#include "BLI_ghash.h"
+#include "BLI_iterator.h"
+#include "DNA_listBase.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct Base;
+struct BLI_Iterator;
+struct Group;
+struct ID;
+struct LayerCollection;
+struct Main;
+struct Object;
+struct Scene;
+struct SceneCollection;
+
+struct SceneCollection *BKE_collection_add(
+ struct ID *owner_id, struct SceneCollection *sc_parent, const int type, const char *name);
+bool BKE_collection_remove(struct ID *owner_id, struct SceneCollection *sc);
+void BKE_collection_copy_data(struct SceneCollection *sc_dst, struct SceneCollection *sc_src, const int flag);
+struct SceneCollection *BKE_collection_master(const struct ID *owner_id);
+void BKE_collection_rename(const struct Scene *scene, struct SceneCollection *sc, const char *name);
+void BKE_collection_master_free(struct ID *owner_id, const bool do_id_user);
+bool BKE_collection_object_add(const struct ID *owner_id, struct SceneCollection *sc, struct Object *object);
+void BKE_collection_object_add_from(struct Scene *scene, struct Object *ob_src, struct Object *ob_dst);
+bool BKE_collection_object_remove(struct Main *bmain, struct ID *owner_id, struct SceneCollection *sc, struct Object *object, const bool free_us);
+bool BKE_collections_object_remove(struct Main *bmain, struct ID *owner_id, struct Object *object, const bool free_us);
+void BKE_collection_object_move(struct ID *owner_id, struct SceneCollection *sc_dst, struct SceneCollection *sc_src, struct Object *ob);
+
+struct Group *BKE_collection_group_create(struct Main *bmain, struct Scene *scene, struct LayerCollection *lc);
+
+void BKE_collection_reinsert_after(const struct Scene *scene, struct SceneCollection *sc_reinsert, struct SceneCollection *sc_after);
+void BKE_collection_reinsert_into(struct SceneCollection *sc_reinsert, struct SceneCollection *sc_into);
+
+bool BKE_collection_move_above(const struct ID *owner_id, struct SceneCollection *sc_dst, struct SceneCollection *sc_src);
+bool BKE_collection_move_below(const struct ID *owner_id, struct SceneCollection *sc_dst, struct SceneCollection *sc_src);
+bool BKE_collection_move_into(const struct ID *owner_id, struct SceneCollection *sc_dst, struct SceneCollection *sc_src);
+
+typedef void (*BKE_scene_objects_Cb)(struct Object *ob, void *data);
+typedef void (*BKE_scene_collections_Cb)(struct SceneCollection *ob, void *data);
+
+void BKE_scene_collections_callback(struct Scene *scene, BKE_scene_collections_Cb callback, void *data);
+void BKE_scene_objects_callback(struct Scene *scene, BKE_scene_objects_Cb callback, void *data);
+
+/* iterators */
+void BKE_scene_collections_iterator_begin(struct BLI_Iterator *iter, void *data_in);
+void BKE_scene_collections_iterator_next(struct BLI_Iterator *iter);
+void BKE_scene_collections_iterator_end(struct BLI_Iterator *iter);
+
+void BKE_scene_objects_iterator_begin(struct BLI_Iterator *iter, void *data_in);
+void BKE_scene_objects_iterator_next(struct BLI_Iterator *iter);
+void BKE_scene_objects_iterator_end(struct BLI_Iterator *iter);
+
+#define FOREACH_SCENE_COLLECTION(_id, _instance) \
+ ITER_BEGIN(BKE_scene_collections_iterator_begin, \
+ BKE_scene_collections_iterator_next, \
+ BKE_scene_collections_iterator_end, \
+ _id, SceneCollection *, _instance)
+
+#define FOREACH_SCENE_COLLECTION_END \
+ ITER_END
+
+#define FOREACH_SCENE_OBJECT(scene, _instance) \
+ ITER_BEGIN(BKE_scene_objects_iterator_begin, \
+ BKE_scene_objects_iterator_next, \
+ BKE_scene_objects_iterator_end, \
+ scene, Object *, _instance)
+
+#define FOREACH_SCENE_OBJECT_END \
+ ITER_END
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BKE_COLLECTION_H__ */
diff --git a/source/blender/blenkernel/BKE_collision.h b/source/blender/blenkernel/BKE_collision.h
index 8fedcd4ab06..0bf7f657f70 100644
--- a/source/blender/blenkernel/BKE_collision.h
+++ b/source/blender/blenkernel/BKE_collision.h
@@ -148,7 +148,7 @@ void collision_get_collider_velocity(float vel_old[3], float vel_new[3], struct
/////////////////////////////////////////////////
/* explicit control over layer mask and dupli recursion */
-struct Object **get_collisionobjects_ext(struct Scene *scene, struct Object *self, struct Group *group, int layer, unsigned int *numcollobj, unsigned int modifier_type, bool dupli);
+struct Object **get_collisionobjects_ext(struct Scene *scene, struct Object *self, struct Group *group, unsigned int *numcollobj, unsigned int modifier_type, bool dupli);
struct Object **get_collisionobjects(struct Scene *scene, struct Object *self, struct Group *group, unsigned int *numcollobj, unsigned int modifier_type);
diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h
index 4e0eb5c65ac..cf7e2908360 100644
--- a/source/blender/blenkernel/BKE_constraint.h
+++ b/source/blender/blenkernel/BKE_constraint.h
@@ -40,6 +40,7 @@ struct ListBase;
struct Object;
struct Scene;
struct bPoseChannel;
+struct EvaluationContext;
/* ---------------------------------------------------------------------------- */
#ifdef __cplusplus
@@ -102,7 +103,7 @@ typedef struct bConstraintTypeInfo {
/* evaluation */
/* set the ct->matrix for the given constraint target (at the given ctime) */
- void (*get_target_matrix)(struct bConstraint *con, struct bConstraintOb *cob, struct bConstraintTarget *ct, float ctime);
+ void (*get_target_matrix)(const struct EvaluationContext *eval_ctx, struct bConstraint *con, struct bConstraintOb *cob, struct bConstraintTarget *ct, float ctime);
/* evaluate the constraint for the given time */
void (*evaluate_constraint)(struct bConstraint *con, struct bConstraintOb *cob, struct ListBase *targets);
} bConstraintTypeInfo;
@@ -147,9 +148,10 @@ void BKE_constraints_clear_evalob(struct bConstraintOb *cob);
void BKE_constraint_mat_convertspace(
struct Object *ob, struct bPoseChannel *pchan, float mat[4][4], short from, short to, const bool keep_scale);
-void BKE_constraint_target_matrix_get(struct Scene *scene, struct bConstraint *con, int n, short ownertype, void *ownerdata, float mat[4][4], float ctime);
-void BKE_constraint_targets_for_solving_get(struct bConstraint *con, struct bConstraintOb *ob, struct ListBase *targets, float ctime);
-void BKE_constraints_solve(struct ListBase *conlist, struct bConstraintOb *cob, float ctime);
+void BKE_constraint_target_matrix_get(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct bConstraint *con,
+ int n, short ownertype, void *ownerdata, float mat[4][4], float ctime);
+void BKE_constraint_targets_for_solving_get(const struct EvaluationContext *eval_ctx, struct bConstraint *con, struct bConstraintOb *ob, struct ListBase *targets, float ctime);
+void BKE_constraints_solve(const struct EvaluationContext *eval_ctx, struct ListBase *conlist, struct bConstraintOb *cob, float ctime);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_context.h b/source/blender/blenkernel/BKE_context.h
index 4da6a61cbfa..121c276d5f2 100644
--- a/source/blender/blenkernel/BKE_context.h
+++ b/source/blender/blenkernel/BKE_context.h
@@ -40,15 +40,21 @@ extern "C" {
struct ARegion;
struct bScreen;
struct CacheFile;
+struct Depsgraph;
+struct LayerCollection;
struct ListBase;
struct Main;
struct Object;
+struct Base;
struct PointerRNA;
struct ReportList;
struct Scene;
+struct SceneCollection;
+struct ViewLayer;
struct ScrArea;
struct SpaceLink;
struct View3D;
+struct ViewRender;
struct RegionView3D;
struct StructRNA;
struct ToolSettings;
@@ -64,10 +70,12 @@ struct bGPDpalettecolor;
struct bGPDbrush;
struct wmWindow;
struct wmWindowManager;
+struct RenderEngineType;
struct SpaceText;
struct SpaceImage;
struct SpaceClip;
struct ID;
+struct EvaluationContext;
/* Structs */
@@ -110,7 +118,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 +149,15 @@ void CTX_py_dict_set(bContext *C, void *value);
struct wmWindowManager *CTX_wm_manager(const bContext *C);
struct wmWindow *CTX_wm_window(const bContext *C);
+struct WorkSpace *CTX_wm_workspace(const bContext *C);
struct bScreen *CTX_wm_screen(const bContext *C);
struct ScrArea *CTX_wm_area(const bContext *C);
struct SpaceLink *CTX_wm_space_data(const bContext *C);
struct ARegion *CTX_wm_region(const bContext *C);
void *CTX_wm_region_data(const bContext *C);
struct ARegion *CTX_wm_menu(const bContext *C);
+struct wmManipulatorGroup *CTX_wm_manipulator_group(const bContext *C);
+struct wmMsgBus *CTX_wm_message_bus(const bContext *C);
struct ReportList *CTX_wm_reports(const bContext *C);
struct View3D *CTX_wm_view3d(const bContext *C);
@@ -173,6 +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);
@@ -239,9 +252,15 @@ int ctx_data_list_count(const bContext *C, int (*func)(const bContext *, ListBas
struct Main *CTX_data_main(const bContext *C);
struct Scene *CTX_data_scene(const bContext *C);
+struct LayerCollection *CTX_data_layer_collection(const bContext *C);
+struct SceneCollection *CTX_data_scene_collection(const bContext *C);
+struct ViewLayer *CTX_data_view_layer(const bContext *C);
+struct ViewRender *CTX_data_view_render(const bContext *C);
+struct RenderEngineType *CTX_data_engine_type(const bContext *C);
struct ToolSettings *CTX_data_tool_settings(const bContext *C);
const char *CTX_data_mode_string(const bContext *C);
+int CTX_data_mode_enum_ex(const struct Object *obedit, const struct Object *ob);
int CTX_data_mode_enum(const bContext *C);
void CTX_data_main_set(bContext *C, struct Main *bmain);
@@ -296,6 +315,9 @@ int CTX_data_visible_gpencil_layers(const bContext *C, ListBase *list);
int CTX_data_editable_gpencil_layers(const bContext *C, ListBase *list);
int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list);
+struct Depsgraph *CTX_data_depsgraph(const bContext *C);
+
+void CTX_data_eval_ctx(const bContext *C, struct EvaluationContext *eval_ctx);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_crazyspace.h b/source/blender/blenkernel/BKE_crazyspace.h
index ee6c5c57678..31542cd6f8a 100644
--- a/source/blender/blenkernel/BKE_crazyspace.h
+++ b/source/blender/blenkernel/BKE_crazyspace.h
@@ -38,23 +38,24 @@ struct Scene;
struct Object;
struct BMEditMesh;
struct Mesh;
+struct EvaluationContext;
/* crazyspace.c */
float (*BKE_crazyspace_get_mapped_editverts(
- struct Scene *scene, struct Object *obedit))[3];
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *obedit))[3];
void BKE_crazyspace_set_quats_editmesh(
struct BMEditMesh *em, float (*origcos)[3], float (*mappedcos)[3], float (*quats)[4],
const bool use_select);
void BKE_crazyspace_set_quats_mesh(
struct Mesh *me, float (*origcos)[3], float (*mappedcos)[3], float (*quats)[4]);
int BKE_crazyspace_get_first_deform_matrices_editbmesh(
- struct Scene *, struct Object *, struct BMEditMesh *em,
+ const struct EvaluationContext *eval_ctx, struct Scene *, struct Object *, struct BMEditMesh *em,
float (**deformmats)[3][3], float (**deformcos)[3]);
int BKE_sculpt_get_first_deform_matrices(
- struct Scene *scene, struct Object *ob,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob,
float (**deformmats)[3][3], float (**deformcos)[3]);
void BKE_crazyspace_build_sculpt(
- struct Scene *scene, struct Object *ob,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob,
float (**deformmats)[3][3], float (**deformcos)[3]);
#ifdef __cplusplus
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 175fa1dad79..fbd05552255 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -36,6 +36,7 @@
struct BezTriple;
struct Curve;
struct EditNurb;
+struct EvaluationContext;
struct GHash;
struct ListBase;
struct Main;
@@ -122,13 +123,14 @@ void BKE_curve_editNurb_keyIndex_free(struct GHash **keyindex);
void BKE_curve_editNurb_free(struct Curve *cu);
struct ListBase *BKE_curve_editNurbs_get(struct Curve *cu);
-float *BKE_curve_make_orco(struct Scene *scene, struct Object *ob, int *r_numVerts);
+float *BKE_curve_make_orco(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, int *r_numVerts);
float *BKE_curve_surf_make_orco(struct Object *ob);
void BKE_curve_bevelList_free(struct ListBase *bev);
void BKE_curve_bevelList_make(struct Object *ob, struct ListBase *nurbs, bool for_render);
-void BKE_curve_bevel_make(struct Scene *scene, struct Object *ob, struct ListBase *disp,
- const bool for_render, const bool use_render_resolution);
+void BKE_curve_bevel_make(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *disp,
+ const bool for_render, const bool use_render_resolution);
void BKE_curve_forward_diff_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride);
void BKE_curve_forward_diff_tangent_bezier(float q0, float q1, float q2, float q3, float *p, int it, int stride);
@@ -215,10 +217,17 @@ void BKE_nurb_handles_test(struct Nurb *nu, const bool use_handles);
/* **** Depsgraph evaluation **** */
-struct EvaluationContext;
-
-void BKE_curve_eval_geometry(struct EvaluationContext *eval_ctx,
- struct Curve *curve);
+void BKE_curve_eval_geometry(
+ const struct EvaluationContext *eval_ctx,
+ struct Curve *curve);
+
+/* Draw Cache */
+enum {
+ BKE_CURVE_BATCH_DIRTY_ALL = 0,
+ BKE_CURVE_BATCH_DIRTY_SELECT,
+};
+void BKE_curve_batch_cache_dirty(struct Curve *cu, int mode);
+void BKE_curve_batch_cache_free(struct Curve *cu);
/* curve_decimate.c */
unsigned int BKE_curve_decimate_bezt_array(
diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h
index 2cdda34b9b5..51cd4da183a 100644
--- a/source/blender/blenkernel/BKE_customdata.h
+++ b/source/blender/blenkernel/BKE_customdata.h
@@ -376,15 +376,14 @@ void CustomData_validate_layer_name(const struct CustomData *data, int type, con
bool CustomData_verify_versions(struct CustomData *data, int index);
/*BMesh specific customdata stuff*/
-void CustomData_to_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata,
- struct CustomData *ldata, int totloop, int totpoly);
-void CustomData_from_bmeshpoly(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata, int total);
-void CustomData_bmesh_update_active_layers(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata);
-void CustomData_bmesh_do_versions_update_active_layers(struct CustomData *fdata, struct CustomData *pdata, struct CustomData *ldata);
+void CustomData_to_bmeshpoly(struct CustomData *fdata, struct CustomData *ldata, int totloop);
+void CustomData_from_bmeshpoly(struct CustomData *fdata, struct CustomData *ldata, int total);
+void CustomData_bmesh_update_active_layers(struct CustomData *fdata, struct CustomData *ldata);
+void CustomData_bmesh_do_versions_update_active_layers(struct CustomData *fdata, struct CustomData *ldata);
void CustomData_bmesh_init_pool(struct CustomData *data, int totelem, const char htype);
#ifndef NDEBUG
-bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *pdata, CustomData *ldata, bool fallback);
+bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *ldata, bool fallback);
#endif
/* External file storage */
diff --git a/source/blender/blenkernel/BKE_data_transfer.h b/source/blender/blenkernel/BKE_data_transfer.h
index 2ee9d8d2408..d5f0313ca64 100644
--- a/source/blender/blenkernel/BKE_data_transfer.h
+++ b/source/blender/blenkernel/BKE_data_transfer.h
@@ -42,6 +42,7 @@ struct Object;
struct Scene;
struct SpaceTransform;
struct ReportList;
+struct EvaluationContext;
/* Warning, those def are stored in files (TransferData modifier), *DO NOT* modify those values. */
enum {
@@ -129,11 +130,12 @@ enum {
};
void BKE_object_data_transfer_layout(
- struct Scene *scene, struct Object *ob_src, struct Object *ob_dst, const int data_types, const bool use_delete,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob_src,
+ struct Object *ob_dst, const int data_types, const bool use_delete,
const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX]);
bool BKE_object_data_transfer_mesh(
- struct Scene *scene,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
struct Object *ob_src, struct Object *ob_dst, const int data_types, const bool use_create,
const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode,
struct SpaceTransform *space_transform, const bool auto_transform,
@@ -142,7 +144,7 @@ bool BKE_object_data_transfer_mesh(
const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup,
struct ReportList *reports);
bool BKE_object_data_transfer_dm(
- struct Scene *scene,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
struct Object *ob_src, struct Object *ob_dst, struct DerivedMesh *dm_dst,
const int data_types, bool use_create,
const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode,
diff --git a/source/blender/blenkernel/BKE_depsgraph.h b/source/blender/blenkernel/BKE_depsgraph.h
deleted file mode 100644
index 40564aeabe9..00000000000
--- a/source/blender/blenkernel/BKE_depsgraph.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2004 Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-#ifndef __BKE_DEPSGRAPH_H__
-#define __BKE_DEPSGRAPH_H__
-
-/** \file BKE_depsgraph.h
- * \ingroup bke
- */
-
-/* Dependency Graph
- *
- * The dependency graph tracks relations between datablocks, and is used to
- * determine which datablocks need to be update based on dependencies and
- * visibility.
- *
- * It does not itself execute changes in objects, but rather sorts the objects
- * in the appropriate order and sets flags indicating they should be updated.
- */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct ID;
-struct Main;
-struct Object;
-struct Scene;
-
-/* Dependency graph evaluation context
- *
- * This structure stores all the local dependency graph data,
- * which is needed for it's evaluation,
- */
-typedef struct EvaluationContext {
- int mode; /* evaluation mode */
- float ctime; /* evaluation time */
-} EvaluationContext;
-
-typedef enum eEvaluationMode {
- DAG_EVAL_VIEWPORT = 0, /* evaluate for OpenGL viewport */
- DAG_EVAL_PREVIEW = 1, /* evaluate for render with preview settings */
- DAG_EVAL_RENDER = 2, /* evaluate for render purposes */
-} eEvaluationMode;
-
-/* DagNode->eval_flags */
-enum {
- /* Regardless to curve->path animation flag path is to be evaluated anyway,
- * to meet dependencies with such a things as curve modifier and other guys
- * who're using curve deform, where_on_path and so.
- */
- DAG_EVAL_NEED_CURVE_PATH = 1,
- /* Scene evaluation would need to have object's data on CPU,
- * meaning no GPU shortcuts is allowed.
- */
- DAG_EVAL_NEED_CPU = 2,
-};
-
-/* Global initialization/deinitialization */
-void DAG_init(void);
-void DAG_exit(void);
-
-/* Build and Update
- *
- * DAG_scene_relations_update will rebuild the dependency graph for a given
- * scene if needed, and sort objects in the scene.
- *
- * DAG_relations_tag_update will clear all dependency graphs and mark them to
- * be rebuilt later. The graph is not rebuilt immediately to avoid slowdowns
- * when this function is call multiple times from different operators.
- *
- * DAG_scene_relations_rebuild forces an immediaterebuild of the dependency
- * graph, this is only needed in rare cases
- */
-
-void DAG_scene_relations_update(struct Main *bmain, struct Scene *sce);
-void DAG_scene_relations_validate(struct Main *bmain, struct Scene *sce);
-void DAG_relations_tag_update(struct Main *bmain);
-void DAG_scene_relations_rebuild(struct Main *bmain, struct Scene *scene);
-void DAG_scene_free(struct Scene *sce);
-
-/* Update Tagging
- *
- * DAG_scene_update_flags will mark all objects that depend on time (animation,
- * physics, ..) to be recalculated, used when changing the current frame.
- *
- * DAG_on_visible_update will mark all objects that are visible for the first
- * time to be updated, for example on file load or changing layer visibility.
- *
- * DAG_id_tag_update will mark a given datablock to be updated. The flag indicates
- * a specific subset to be update (only object transform and data for now).
- *
- * DAG_id_type_tag marks a particular datablock type as having changing. This does
- * not cause any updates but is used by external render engines to detect if for
- * example a datablock was removed. */
-
-void DAG_scene_update_flags(struct Main *bmain, struct Scene *sce, unsigned int lay, const bool do_time, const bool do_invisible_flush);
-void DAG_on_visible_update(struct Main *bmain, const bool do_time);
-
-void DAG_id_tag_update(struct ID *id, short flag);
-void DAG_id_tag_update_ex(struct Main *bmain, struct ID *id, short flag);
-void DAG_id_type_tag(struct Main *bmain, short idtype);
-int DAG_id_type_tagged(struct Main *bmain, short idtype);
-
-/* Flushing Tags
- *
- * DAG_scene_flush_update flushes object recalculation flags immediately to other
- * dependencies. Do not use outside of depsgraph.c, this will be removed.
- *
- * DAG_ids_flush_tagged will flush datablock update flags flags to dependencies,
- * use this right before updating to mark all the needed datablocks for update.
- *
- * DAG_ids_check_recalc and DAG_ids_clear_recalc are used for external render
- * engines to detect changes. */
-
-void DAG_scene_flush_update(struct Main *bmain, struct Scene *sce, unsigned int lay, const short do_time);
-void DAG_ids_flush_tagged(struct Main *bmain);
-void DAG_ids_check_recalc(struct Main *bmain, struct Scene *scene, bool time);
-void DAG_ids_clear_recalc(struct Main *bmain);
-
-/* Armature: sorts the bones according to dependencies between them */
-
-void DAG_pose_sort(struct Object *ob);
-
-/* Editors: callbacks to notify editors of datablock changes */
-
-void DAG_editors_update_cb(void (*id_func)(struct Main *bmain, struct ID *id),
- void (*scene_func)(struct Main *bmain, struct Scene *scene, int updated),
- void (*scene_pre_func)(struct Main *bmain, struct Scene *scene, bool time));
-
-void DAG_editors_update_pre(struct Main *bmain, struct Scene *scene, bool time);
-
-/* ** Threaded update ** */
-
-/* Initialize the DAG for threaded update. */
-void DAG_threaded_update_begin(struct Scene *scene,
- void (*func)(void *node, void *user_data),
- void *user_data);
-
-void DAG_threaded_update_handle_node_updated(void *node_v,
- void (*func)(void *node, void *user_data),
- void *user_data);
-
-/* Debugging: print dependency graph for scene or armature object to console */
-
-void DAG_print_dependencies(struct Main *bmain, struct Scene *scene, struct Object *ob);
-
-/* ************************ DAG querying ********************* */
-
-struct Object *DAG_get_node_object(void *node_v);
-const char *DAG_get_node_name(struct Scene *scene, void *node_v);
-short DAG_get_eval_flags_for_object(struct Scene *scene, void *object);
-bool DAG_is_acyclic(struct Scene *scene);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h
index 9625f05192a..c2229976dd9 100644
--- a/source/blender/blenkernel/BKE_displist.h
+++ b/source/blender/blenkernel/BKE_displist.h
@@ -86,23 +86,30 @@ void BKE_displist_count(struct ListBase *lb, int *totvert, int *totface, int *to
void BKE_displist_free(struct ListBase *lb);
bool BKE_displist_has_faces(struct ListBase *lb);
-void BKE_displist_make_surf(struct Scene *scene, struct Object *ob, struct ListBase *dispbase, struct DerivedMesh **r_dm_final,
- const bool for_render, const bool for_orco, const bool use_render_resolution);
-void BKE_displist_make_curveTypes(struct Scene *scene, struct Object *ob, const bool for_orco);
-void BKE_displist_make_curveTypes_forRender(struct Scene *scene, struct Object *ob, struct ListBase *dispbase, struct DerivedMesh **r_dm_final,
- const bool for_orco, const bool use_render_resolution);
-void BKE_displist_make_curveTypes_forOrco(struct Scene *scene, struct Object *ob, struct ListBase *dispbase);
-void BKE_displist_make_mball(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
-void BKE_displist_make_mball_forRender(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *dispbase);
+void BKE_displist_make_surf(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *dispbase,
+ struct DerivedMesh **r_dm_final, const bool for_render, const bool for_orco, const bool use_render_resolution);
+void BKE_displist_make_curveTypes(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, const bool for_orco);
+void BKE_displist_make_curveTypes_forRender(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *dispbase,
+ struct DerivedMesh **r_dm_final, const bool for_orco, const bool use_render_resolution);
+void BKE_displist_make_curveTypes_forOrco(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *dispbase);
+void BKE_displist_make_mball(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
+void BKE_displist_make_mball_forRender(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ListBase *dispbase);
bool BKE_displist_surfindex_get(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4);
void BKE_displist_fill(struct ListBase *dispbase, struct ListBase *to, const float normal_proj[3], const bool flipnormal);
-float BKE_displist_calc_taper(struct Scene *scene, struct Object *taperobj, int cur, int tot);
+float BKE_displist_calc_taper(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *taperobj, int cur, int tot);
/* add Orco layer to the displist object which has got derived mesh and return orco */
-float *BKE_displist_make_orco(struct Scene *scene, struct Object *ob, struct DerivedMesh *dm_final,
- const bool for_render, const bool use_render_resolution);
+float *BKE_displist_make_orco(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm_final,
+ const bool for_render, const bool use_render_resolution);
void BKE_displist_minmax(struct ListBase *dispbase, float min[3], float max[3]);
diff --git a/source/blender/blenkernel/BKE_dynamicpaint.h b/source/blender/blenkernel/BKE_dynamicpaint.h
index 5abb53d4c52..21c900a7f0d 100644
--- a/source/blender/blenkernel/BKE_dynamicpaint.h
+++ b/source/blender/blenkernel/BKE_dynamicpaint.h
@@ -28,6 +28,8 @@
*/
struct Scene;
+struct ViewLayer;
+struct EvaluationContext;
/* Actual surface point */
typedef struct PaintSurfaceData {
@@ -60,7 +62,8 @@ typedef struct PaintWavePoint {
short state;
} PaintWavePoint;
-struct DerivedMesh *dynamicPaint_Modifier_do(struct DynamicPaintModifierData *pmd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm);
+struct DerivedMesh *dynamicPaint_Modifier_do(struct DynamicPaintModifierData *pmd, const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct Object *ob, struct DerivedMesh *dm);
void dynamicPaint_Modifier_free(struct DynamicPaintModifierData *pmd);
void dynamicPaint_Modifier_copy(struct DynamicPaintModifierData *pmd, struct DynamicPaintModifierData *tsmd);
@@ -83,7 +86,7 @@ struct DynamicPaintSurface *get_activeSurface(struct DynamicPaintCanvasSettings
/* image sequence baking */
int dynamicPaint_createUVSurface(struct Scene *scene, struct DynamicPaintSurface *surface, float *progress, short *do_update);
-int dynamicPaint_calculateFrame(struct DynamicPaintSurface *surface, struct Scene *scene, struct Object *cObject, int frame);
+int dynamicPaint_calculateFrame(struct DynamicPaintSurface *surface, const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *cObject, int frame);
void dynamicPaint_outputSurfaceImage(struct DynamicPaintSurface *surface, char *filename, short output_layer);
/* PaintPoint state */
diff --git a/source/blender/blenkernel/BKE_editmesh.h b/source/blender/blenkernel/BKE_editmesh.h
index 55a9db9b1e5..af1aeff230f 100644
--- a/source/blender/blenkernel/BKE_editmesh.h
+++ b/source/blender/blenkernel/BKE_editmesh.h
@@ -40,6 +40,7 @@ struct Mesh;
struct Scene;
struct DerivedMesh;
struct MeshStatVis;
+struct EvaluationContext;
/**
* This structure is used for mesh edit-mode.
@@ -88,7 +89,6 @@ BMEditMesh *BKE_editmesh_copy(BMEditMesh *em);
BMEditMesh *BKE_editmesh_from_object(struct Object *ob);
void BKE_editmesh_free_derivedmesh(BMEditMesh *em);
void BKE_editmesh_free(BMEditMesh *em);
-void BKE_editmesh_update_linked_customdata(BMEditMesh *em);
void BKE_editmesh_color_free(BMEditMesh *em);
void BKE_editmesh_color_ensure(BMEditMesh *em, const char htype);
@@ -99,6 +99,7 @@ float (*BKE_editmesh_vertexCos_get_orco(BMEditMesh *em, int *r_numVerts))[3]
void BKE_editmesh_statvis_calc(BMEditMesh *em, struct DerivedMesh *dm,
const struct MeshStatVis *statvis);
-float (*BKE_editmesh_vertexCos_get(struct BMEditMesh *em, struct Scene *scene, int *r_numVerts))[3];
+float (*BKE_editmesh_vertexCos_get(
+ const struct EvaluationContext *eval_ctx, struct BMEditMesh *em, struct Scene *scene, int *r_numVerts))[3];
#endif /* __BKE_EDITMESH_H__ */
diff --git a/source/blender/blenkernel/BKE_editmesh_tangent.h b/source/blender/blenkernel/BKE_editmesh_tangent.h
new file mode 100644
index 00000000000..9553fbc1a5c
--- /dev/null
+++ b/source/blender/blenkernel/BKE_editmesh_tangent.h
@@ -0,0 +1,40 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Joseph Eagar.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BKE_EDITMESH_TANGENT_H__
+#define __BKE_EDITMESH_TANGENT_H__
+
+/** \file BKE_editmesh_tangent.h
+ * \ingroup bke
+ */
+
+void BKE_editmesh_loop_tangent_calc(
+ BMEditMesh *em, bool calc_active_tangent,
+ const char (*tangent_names)[MAX_NAME], int tangent_names_len,
+ const float (*poly_normals)[3],
+ const float (*loop_normals)[3],
+ const float (*vert_orco)[3],
+ CustomData *dm_loopdata_out,
+ const uint dm_loopdata_out_len,
+ short *tangent_mask_curr_p);
+
+#endif /* __BKE_EDITMESH_TANGENT_H__ */
diff --git a/source/blender/blenkernel/BKE_effect.h b/source/blender/blenkernel/BKE_effect.h
index aa45132cbe9..6fa19d4aaf6 100644
--- a/source/blender/blenkernel/BKE_effect.h
+++ b/source/blender/blenkernel/BKE_effect.h
@@ -44,6 +44,7 @@ struct Group;
struct ParticleSimulationData;
struct ParticleData;
struct ParticleKey;
+struct EvaluationContext;
struct EffectorWeights *BKE_add_effector_weights(struct Group *group);
struct PartDeflect *object_add_collision_fields(int type);
@@ -93,6 +94,7 @@ typedef struct EffectorData {
typedef struct EffectorCache {
struct EffectorCache *next, *prev;
+ const struct EvaluationContext *eval_ctx;
struct Scene *scene;
struct Object *ob;
struct ParticleSystem *psys;
@@ -110,9 +112,11 @@ typedef struct EffectorCache {
} EffectorCache;
void free_partdeflect(struct PartDeflect *pd);
-struct ListBase *pdInitEffectors(struct Scene *scene, struct Object *ob_src, struct ParticleSystem *psys_src, struct EffectorWeights *weights, bool for_simulation);
+struct ListBase *pdInitEffectors(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob_src, struct ParticleSystem *psys_src,
+ struct EffectorWeights *weights, bool for_simulation);
void pdEndEffectors(struct ListBase **effectors);
-void pdPrecalculateEffectors(struct ListBase *effectors);
+void pdPrecalculateEffectors(const struct EvaluationContext *eval_ctx, struct ListBase *effectors);
void pdDoEffectors(struct ListBase *effectors, struct ListBase *colliders, struct EffectorWeights *weights, struct EffectedPoint *point, float *force, float *impulse);
void pd_point_from_particle(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleKey *state, struct EffectedPoint *point);
diff --git a/source/blender/blenkernel/BKE_fluidsim.h b/source/blender/blenkernel/BKE_fluidsim.h
index 6501c968abc..4ec58b2a0e5 100644
--- a/source/blender/blenkernel/BKE_fluidsim.h
+++ b/source/blender/blenkernel/BKE_fluidsim.h
@@ -36,10 +36,11 @@ struct Object;
struct Scene;
struct FluidsimSettings;
struct MVert;
+struct EvaluationContext;
/* old interface */
-void initElbeemMesh(struct Scene *scene, struct Object *ob,
+void initElbeemMesh(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob,
int *numVertices, float **vertices,
int *numTriangles, int **triangles,
int useGlobalCoords, int modifierIndex);
diff --git a/source/blender/blenkernel/BKE_freestyle.h b/source/blender/blenkernel/BKE_freestyle.h
index 1045fde0039..f7368683d93 100644
--- a/source/blender/blenkernel/BKE_freestyle.h
+++ b/source/blender/blenkernel/BKE_freestyle.h
@@ -49,7 +49,7 @@ typedef struct FreestyleModuleSettings FreestyleModuleSettings;
/* FreestyleConfig */
void BKE_freestyle_config_init(FreestyleConfig *config);
-void BKE_freestyle_config_free(FreestyleConfig *config);
+void BKE_freestyle_config_free(FreestyleConfig *config, const bool do_id_user);
void BKE_freestyle_config_copy(FreestyleConfig *new_config, FreestyleConfig *config, const int flag);
/* FreestyleConfig.modules */
diff --git a/source/blender/blenkernel/BKE_global.h b/source/blender/blenkernel/BKE_global.h
index 790c8051ace..80a8f750d20 100644
--- a/source/blender/blenkernel/BKE_global.h
+++ b/source/blender/blenkernel/BKE_global.h
@@ -128,10 +128,11 @@ enum {
G_DEBUG_DEPSGRAPH_NO_THREADS = (1 << 11), /* single threaded depsgraph */
G_DEBUG_GPU = (1 << 12), /* gpu debug */
G_DEBUG_IO = (1 << 13), /* IO Debugging (for Collada, ...)*/
+ G_DEBUG_GPU_SHADERS = (1 << 14), /* GLSL shaders */
};
#define G_DEBUG_ALL (G_DEBUG | G_DEBUG_FFMPEG | G_DEBUG_PYTHON | G_DEBUG_EVENTS | G_DEBUG_WM | G_DEBUG_JOBS | \
- G_DEBUG_FREESTYLE | G_DEBUG_DEPSGRAPH | G_DEBUG_GPU_MEM | G_DEBUG_IO)
+ G_DEBUG_FREESTYLE | G_DEBUG_DEPSGRAPH | G_DEBUG_GPU_MEM | G_DEBUG_IO | G_DEBUG_GPU_SHADERS)
/* G.fileflags */
diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h
index e07dd259970..74255cfc941 100644
--- a/source/blender/blenkernel/BKE_group.h
+++ b/source/blender/blenkernel/BKE_group.h
@@ -41,17 +41,45 @@ struct Object;
struct Scene;
void BKE_group_free(struct Group *group);
+void BKE_group_init(struct Group *group);
struct Group *BKE_group_add(struct Main *bmain, const char *name);
void BKE_group_copy_data(struct Main *bmain, struct Group *group_dst, const struct Group *group_src, const int flag);
struct Group *BKE_group_copy(struct Main *bmain, const struct Group *group);
void BKE_group_make_local(struct Main *bmain, struct Group *group, const bool lib_local);
-bool BKE_group_object_add(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
-bool BKE_group_object_unlink(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base);
+bool BKE_group_object_add(struct Group *group, struct Object *ob);
+bool BKE_group_object_unlink(struct Group *group, struct Object *ob);
struct Group *BKE_group_object_find(struct Group *group, struct Object *ob);
bool BKE_group_object_exists(struct Group *group, struct Object *ob);
bool BKE_group_object_cyclic_check(struct Main *bmain, struct Object *object, struct Group *group);
bool BKE_group_is_animated(struct Group *group, struct Object *parent);
-void BKE_group_handle_recalc_and_update(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *parent, struct Group *group);
+void BKE_group_handle_recalc_and_update(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *parent, struct Group *group);
+
+/* Dependency graph evaluation. */
+
+void BKE_group_eval_view_layers(const struct EvaluationContext *eval_ctx,
+ struct Group *group);
+
+/* Helper macros. */
+
+#define FOREACH_GROUP_BASE(_group, _base) \
+ for (Base *_base = (Base *)(_group)->view_layer->object_bases.first; \
+ _base; \
+ _base = _base->next) \
+ {
+
+#define FOREACH_GROUP_BASE_END \
+ }
+
+#define FOREACH_GROUP_OBJECT(_group, _object) \
+ for (Base *_base = (Base *)(_group)->view_layer->object_bases.first; \
+ _base; \
+ _base = _base->next) \
+ { \
+ Object *_object = _base->object; \
+ BLI_assert(_object != NULL);
+
+#define FOREACH_GROUP_OBJECT_END \
+ }
#endif /* __BKE_GROUP_H__ */
diff --git a/source/blender/blenkernel/BKE_idprop.h b/source/blender/blenkernel/BKE_idprop.h
index 5d8cd02756d..055c530d255 100644
--- a/source/blender/blenkernel/BKE_idprop.h
+++ b/source/blender/blenkernel/BKE_idprop.h
@@ -91,6 +91,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 */);
diff --git a/source/blender/blenkernel/BKE_lamp.h b/source/blender/blenkernel/BKE_lamp.h
index 3673e657b33..aa655c66477 100644
--- a/source/blender/blenkernel/BKE_lamp.h
+++ b/source/blender/blenkernel/BKE_lamp.h
@@ -50,8 +50,6 @@ struct Lamp *BKE_lamp_localize(struct Lamp *la) ATTR_WARN_UNUSED_RESULT;
void BKE_lamp_make_local(struct Main *bmain, struct Lamp *la, const bool lib_local);
void BKE_lamp_free(struct Lamp *la);
-void lamp_drivers_update(struct Scene *scene, struct Lamp *la, float ctime);
-
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_lattice.h b/source/blender/blenkernel/BKE_lattice.h
index f7d006785d2..1cdf193f054 100644
--- a/source/blender/blenkernel/BKE_lattice.h
+++ b/source/blender/blenkernel/BKE_lattice.h
@@ -43,6 +43,7 @@ struct Scene;
struct DerivedMesh;
struct BPoint;
struct MDeformVert;
+struct EvaluationContext;
void BKE_lattice_resize(struct Lattice *lt, int u, int v, int w, struct Object *ltOb);
void BKE_lattice_init(struct Lattice *lt);
@@ -61,10 +62,11 @@ void end_latt_deform(struct LatticeDeformData *lattice_deform_data);
bool object_deform_mball(struct Object *ob, struct ListBase *dispbase);
void outside_lattice(struct Lattice *lt);
-void curve_deform_verts(struct Scene *scene, struct Object *cuOb, struct Object *target,
- struct DerivedMesh *dm, float (*vertexCos)[3],
- int numVerts, const char *vgroup, short defaxis);
-void curve_deform_vector(struct Scene *scene, struct Object *cuOb, struct Object *target,
+void curve_deform_verts(
+ struct Object *cuOb, struct Object *target,
+ struct DerivedMesh *dm, float (*vertexCos)[3],
+ int numVerts, const char *vgroup, short defaxis);
+void curve_deform_vector(struct Object *cuOb, struct Object *target,
float orco[3], float vec[3], float mat[3][3], int no_rot_axis);
void lattice_deform_verts(struct Object *laOb, struct Object *target,
@@ -77,7 +79,7 @@ void armature_deform_verts(struct Object *armOb, struct Object *target,
float (*BKE_lattice_vertexcos_get(struct Object *ob, int *r_numVerts))[3];
void BKE_lattice_vertexcos_apply(struct Object *ob, float (*vertexCos)[3]);
-void BKE_lattice_modifiers_calc(struct Scene *scene, struct Object *ob);
+void BKE_lattice_modifiers_calc(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
struct MDeformVert *BKE_lattice_deform_verts_get(struct Object *lattice);
struct BPoint *BKE_lattice_active_point_get(struct Lattice *lt);
@@ -101,7 +103,15 @@ void BKE_lattice_bitmap_from_flag(struct Lattice *lt, unsigned int *bitmap, cons
struct EvaluationContext;
-void BKE_lattice_eval_geometry(struct EvaluationContext *eval_ctx,
+void BKE_lattice_eval_geometry(const struct EvaluationContext *eval_ctx,
struct Lattice *latt);
+/* Draw Cache */
+enum {
+ BKE_LATTICE_BATCH_DIRTY_ALL = 0,
+ BKE_LATTICE_BATCH_DIRTY_SELECT,
+};
+void BKE_lattice_batch_cache_dirty(struct Lattice *lt, int mode);
+void BKE_lattice_batch_cache_free(struct Lattice *lt);
+
#endif /* __BKE_LATTICE_H__ */
diff --git a/source/blender/blenkernel/BKE_layer.h b/source/blender/blenkernel/BKE_layer.h
new file mode 100644
index 00000000000..77f760a7843
--- /dev/null
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -0,0 +1,292 @@
+/*
+ * ***** 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"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define TODO_LAYER_SYNC_FILTER /* syncing of filter_objects across all trees */
+#define TODO_LAYER_OVERRIDE /* CollectionOverride */
+#define TODO_LAYER_OPERATORS /* collection mamanger and property panel operators */
+#define TODO_LAYER /* generic todo */
+
+#define ROOT_PROP "root"
+
+struct Base;
+struct EvaluationContext;
+struct Group;
+struct ID;
+struct IDProperty;
+struct LayerCollection;
+struct ListBase;
+struct Main;
+struct Object;
+struct RenderEngine;
+struct Scene;
+struct SceneCollection;
+struct ViewLayer;
+struct WorkSpace;
+
+void BKE_layer_exit(void);
+
+struct ViewLayer *BKE_view_layer_from_scene_get(const struct Scene *scene);
+struct ViewLayer *BKE_view_layer_from_workspace_get(const struct Scene *scene, const struct WorkSpace *workspace);
+struct ViewLayer *BKE_view_layer_add(struct Scene *scene, const char *name);
+struct ViewLayer *BKE_view_layer_group_add(struct Group *group);
+
+/* DEPRECATED */
+struct ViewLayer *BKE_view_layer_context_active_PLACEHOLDER(const struct Scene *scene);
+
+void BKE_view_layer_free(struct ViewLayer *view_layer);
+void BKE_view_layer_free_ex(struct ViewLayer *view_layer, const bool do_id_user);
+
+void BKE_view_layer_selected_objects_tag(struct ViewLayer *view_layer, const int tag);
+
+struct Object *BKE_view_layer_camera_find(struct ViewLayer *view_layer);
+struct ViewLayer *BKE_view_layer_first_from_id(const struct ID *owner_id);
+struct ViewLayer *BKE_view_layer_find_from_collection(const struct ID *owner_id, struct LayerCollection *lc);
+struct Base *BKE_view_layer_base_find(struct ViewLayer *view_layer, struct Object *ob);
+void BKE_view_layer_base_deselect_all(struct ViewLayer *view_layer);
+void BKE_view_layer_base_select(struct ViewLayer *view_layer, struct Base *selbase);
+
+void BKE_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);
+
+void BKE_layer_collection_free(struct ViewLayer *view_layer, struct LayerCollection *lc);
+
+struct LayerCollection *BKE_layer_collection_get_active(struct ViewLayer *view_layer);
+struct LayerCollection *BKE_layer_collection_get_active_ensure(struct Scene *scene, struct ViewLayer *view_layer);
+
+int BKE_layer_collection_count(struct ViewLayer *view_layer);
+
+struct LayerCollection *BKE_layer_collection_from_index(struct ViewLayer *view_layer, const int index);
+int BKE_layer_collection_findindex(struct ViewLayer *view_layer, const struct LayerCollection *lc);
+
+bool BKE_layer_collection_move_above(const struct ID *owner_id, struct LayerCollection *lc_dst, struct LayerCollection *lc_src);
+bool BKE_layer_collection_move_below(const struct ID *owner_id, struct LayerCollection *lc_dst, struct LayerCollection *lc_src);
+bool BKE_layer_collection_move_into(const struct ID *owner_id, struct LayerCollection *lc_dst, struct LayerCollection *lc_src);
+
+void BKE_layer_collection_resync(const struct ID *owner_id, const struct SceneCollection *sc);
+
+struct LayerCollection *BKE_collection_link(struct ViewLayer *view_layer, struct SceneCollection *sc);
+
+void BKE_collection_unlink(struct ViewLayer *view_layer, struct LayerCollection *lc);
+
+void BKE_collection_enable(struct ViewLayer *view_layer, struct LayerCollection *lc);
+
+bool BKE_view_layer_has_collection(struct ViewLayer *view_layer, const struct SceneCollection *sc);
+bool BKE_scene_has_object(struct Scene *scene, struct Object *ob);
+
+/* syncing */
+
+void BKE_layer_sync_new_scene_collection(struct ID *owner_id, const struct SceneCollection *sc_parent, struct SceneCollection *sc);
+void BKE_layer_sync_object_link(const struct ID *owner_id, struct SceneCollection *sc, struct Object *ob);
+void BKE_layer_sync_object_unlink(const struct ID *owner_id, struct SceneCollection *sc, struct Object *ob);
+
+/* override */
+
+void BKE_override_view_layer_datablock_add(struct ViewLayer *view_layer, int id_type, const char *data_path, const struct ID *owner_id);
+void BKE_override_view_layer_int_add(struct ViewLayer *view_layer, int id_type, const char *data_path, const int value);
+
+void BKE_override_layer_collection_boolean_add(struct LayerCollection *layer_collection, int id_type, const char *data_path, const bool value);
+
+/* engine settings */
+typedef void (*EngineSettingsCB)(struct RenderEngine *engine, struct IDProperty *props);
+
+struct IDProperty *BKE_layer_collection_engine_evaluated_get(struct Object *ob, const int type, const char *engine_name);
+struct IDProperty *BKE_layer_collection_engine_collection_get(struct LayerCollection *lc, const int type, const char *engine_name);
+struct IDProperty *BKE_layer_collection_engine_scene_get(struct Scene *scene, const int type, const char *engine_name);
+void BKE_layer_collection_engine_settings_callback_register(struct Main *bmain, const char *engine_name, EngineSettingsCB func);
+void BKE_layer_collection_engine_settings_callback_free(void);
+void BKE_layer_collection_engine_settings_create(struct IDProperty *root);
+void BKE_layer_collection_engine_settings_validate_scene(struct Scene *scene);
+void BKE_layer_collection_engine_settings_validate_collection(struct LayerCollection *lc);
+
+struct IDProperty *BKE_view_layer_engine_evaluated_get(struct ViewLayer *view_layer, const int type, const char *engine_name);
+struct IDProperty *BKE_view_layer_engine_layer_get(struct ViewLayer *view_layer, const int type, const char *engine_name);
+struct IDProperty *BKE_view_layer_engine_scene_get(struct Scene *scene, const int type, const char *engine_name);
+void BKE_view_layer_engine_settings_callback_register(struct Main *bmain, const char *engine_name, EngineSettingsCB func);
+void BKE_view_layer_engine_settings_callback_free(void);
+void BKE_view_layer_engine_settings_validate_scene(struct Scene *scene);
+void BKE_view_layer_engine_settings_validate_layer(struct ViewLayer *view_layer);
+void BKE_view_layer_engine_settings_create(struct IDProperty *root);
+
+void BKE_collection_engine_property_add_float(struct IDProperty *props, const char *name, float value);
+void BKE_collection_engine_property_add_float_array(
+ struct IDProperty *props, const char *name, const float *values, const int array_length);
+void BKE_collection_engine_property_add_int(struct IDProperty *props, const char *name, int value);
+void BKE_collection_engine_property_add_bool(struct IDProperty *props, const char *name, bool value);
+
+int BKE_collection_engine_property_value_get_int(struct IDProperty *props, const char *name);
+float BKE_collection_engine_property_value_get_float(struct IDProperty *props, const char *name);
+const float *BKE_collection_engine_property_value_get_float_array(struct IDProperty *props, const char *name);
+bool BKE_collection_engine_property_value_get_bool(struct IDProperty *props, const char *name);
+void BKE_collection_engine_property_value_set_int(struct IDProperty *props, const char *name, int value);
+void BKE_collection_engine_property_value_set_float(struct IDProperty *props, const char *name, float value);
+void BKE_collection_engine_property_value_set_float_array(struct IDProperty *props, const char *name, const float *values);
+void BKE_collection_engine_property_value_set_bool(struct IDProperty *props, const char *name, bool value);
+
+/* evaluation */
+
+void BKE_layer_eval_layer_collection_pre(const struct EvaluationContext *eval_ctx,
+ struct ID *owner_id,
+ struct ViewLayer *view_layer);
+void BKE_layer_eval_layer_collection(const struct EvaluationContext *eval_ctx,
+ struct LayerCollection *layer_collection,
+ struct LayerCollection *parent_layer_collection);
+void BKE_layer_eval_layer_collection_post(const struct EvaluationContext *eval_ctx,
+ struct ViewLayer *view_layer);
+
+/* iterators */
+
+void BKE_selected_objects_iterator_begin(BLI_Iterator *iter, void *data_in);
+void BKE_selected_objects_iterator_next(BLI_Iterator *iter);
+void BKE_selected_objects_iterator_end(BLI_Iterator *iter);
+
+void BKE_visible_objects_iterator_begin(BLI_Iterator *iter, void *data_in);
+void BKE_visible_objects_iterator_next(BLI_Iterator *iter);
+void BKE_visible_objects_iterator_end(BLI_Iterator *iter);
+
+void BKE_renderable_objects_iterator_begin(BLI_Iterator *iter, void *data_in);
+void BKE_renderable_objects_iterator_next(BLI_Iterator *iter);
+void BKE_renderable_objects_iterator_end(BLI_Iterator *iter);
+
+void BKE_selected_bases_iterator_begin(BLI_Iterator *iter, void *data_in);
+void BKE_selected_bases_iterator_next(BLI_Iterator *iter);
+void BKE_selected_bases_iterator_end(BLI_Iterator *iter);
+
+void BKE_visible_bases_iterator_begin(BLI_Iterator *iter, void *data_in);
+void BKE_visible_bases_iterator_next(BLI_Iterator *iter);
+void BKE_visible_bases_iterator_end(BLI_Iterator *iter);
+
+#define FOREACH_SELECTED_OBJECT(view_layer, _instance) \
+ ITER_BEGIN(BKE_selected_objects_iterator_begin, \
+ BKE_selected_objects_iterator_next, \
+ BKE_selected_objects_iterator_end, \
+ view_layer, Object *, _instance)
+
+#define FOREACH_SELECTED_OBJECT_END \
+ ITER_END
+
+#define FOREACH_VISIBLE_OBJECT(view_layer, _instance) \
+ ITER_BEGIN(BKE_visible_objects_iterator_begin, \
+ BKE_visible_objects_iterator_next, \
+ BKE_visible_objects_iterator_end, \
+ view_layer, Object *, _instance)
+
+#define FOREACH_VISIBLE_OBJECT_END \
+ ITER_END
+
+#define FOREACH_SELECTED_BASE(view_layer, _instance) \
+ ITER_BEGIN(BKE_selected_bases_iterator_begin, \
+ BKE_selected_bases_iterator_next, \
+ BKE_selected_bases_iterator_end, \
+ view_layer, Base *, _instance)
+
+#define FOREACH_SELECTED_BASE_END \
+ ITER_END
+
+#define FOREACH_VISIBLE_BASE(view_layer, _instance) \
+ ITER_BEGIN(BKE_visible_bases_iterator_begin, \
+ BKE_visible_bases_iterator_next, \
+ BKE_visible_bases_iterator_end, \
+ view_layer, Base *, _instance)
+
+#define FOREACH_VISIBLE_BASE_END \
+ ITER_END
+
+
+#define FOREACH_OBJECT(view_layer, _instance) \
+{ \
+ Object *_instance; \
+ Base *base; \
+ for (base = (view_layer)->object_bases.first; base; base = base->next) { \
+ _instance = base->object;
+
+#define FOREACH_OBJECT_END \
+ } \
+}
+
+#define FOREACH_OBJECT_FLAG(scene, view_layer, flag, _instance) \
+{ \
+ IteratorBeginCb func_begin; \
+ IteratorCb func_next, func_end; \
+ void *data_in; \
+ \
+ if (flag == SELECT) { \
+ func_begin = &BKE_selected_objects_iterator_begin; \
+ func_next = &BKE_selected_objects_iterator_next; \
+ func_end = &BKE_selected_objects_iterator_end; \
+ data_in = (view_layer); \
+ } \
+ else { \
+ func_begin = BKE_scene_objects_iterator_begin; \
+ func_next = BKE_scene_objects_iterator_next; \
+ func_end = BKE_scene_objects_iterator_end; \
+ data_in = (scene); \
+ } \
+ ITER_BEGIN(func_begin, func_next, func_end, data_in, Object *, _instance)
+
+
+#define FOREACH_OBJECT_FLAG_END \
+ ITER_END \
+}
+
+typedef struct ObjectsRenderableIteratorData {
+ struct Scene *scene;
+
+ struct {
+ struct ViewLayer *view_layer;
+ struct Base *base;
+ struct Scene *set;
+ } iter;
+} ObjectsRenderableIteratorData;
+
+#define FOREACH_OBJECT_RENDERABLE(scene_, _instance) \
+ ObjectsRenderableIteratorData data_ = { \
+ .scene = (scene_), \
+ }; \
+ ITER_BEGIN(BKE_renderable_objects_iterator_begin, \
+ BKE_renderable_objects_iterator_next, \
+ BKE_renderable_objects_iterator_end, \
+ &data_, Object *, _instance)
+
+
+#define FOREACH_OBJECT_RENDERABLE_END \
+ ITER_END
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BKE_LAYER_H__ */
diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h
index eb66d4edf0f..0abf99415c7 100644
--- a/source/blender/blenkernel/BKE_library.h
+++ b/source/blender/blenkernel/BKE_library.h
@@ -148,6 +148,7 @@ bool id_make_local(struct Main *bmain, struct ID *id, const bool test, const boo
bool id_single_user(struct bContext *C, struct ID *id, struct PointerRNA *ptr, struct PropertyRNA *prop);
bool id_copy(struct Main *bmain, const struct ID *id, struct ID **newid, bool test);
bool BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, const int flag, const bool test);
+void BKE_id_swap(struct Main *bmain, struct ID *id_a, struct ID *id_b);
void id_sort_by_name(struct ListBase *lb, struct ID *id);
void BKE_id_expand_local(struct Main *bmain, struct ID *id);
void BKE_id_copy_ensure_local(struct Main *bmain, const struct ID *old_id, struct ID *new_id);
@@ -158,7 +159,7 @@ void id_clear_lib_data_ex(struct Main *bmain, struct ID *id, const bool id_in_ma
struct ListBase *which_libbase(struct Main *mainlib, short type);
-#define MAX_LIBARRAY 35
+#define MAX_LIBARRAY 37
int set_listbasepointers(struct Main *main, struct ListBase *lb[MAX_LIBARRAY]);
/* Main API */
diff --git a/source/blender/blenkernel/BKE_library_override.h b/source/blender/blenkernel/BKE_library_override.h
new file mode 100644
index 00000000000..35672cb5ded
--- /dev/null
+++ b/source/blender/blenkernel/BKE_library_override.h
@@ -0,0 +1,87 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Bastien Montagne.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BKE_LIBRARY_OVERRIDE_H__
+#define __BKE_LIBRARY_OVERRIDE_H__
+
+/** \file BKE_library_override.h
+ * \ingroup bke
+ * \since December 2016
+ * \author mont29
+ */
+
+struct ID;
+struct IDOverrideStatic;
+struct IDOverrideStaticProperty;
+struct IDOverrideStaticPropertyOperation;
+struct Main;
+
+struct IDOverrideStatic *BKE_override_static_init(struct ID *local_id, struct ID *reference_id);
+void BKE_override_static_copy(struct ID *dst_id, const struct ID *src_id);
+void BKE_override_static_clear(struct IDOverrideStatic *override);
+void BKE_override_static_free(struct IDOverrideStatic **override);
+
+struct ID *BKE_override_static_create_from_id(struct Main *bmain, struct ID *reference_id);
+bool BKE_override_static_create_from_tag(struct Main *bmain);
+
+struct IDOverrideStaticProperty *BKE_override_static_property_find(struct IDOverrideStatic *override, const char *rna_path);
+struct IDOverrideStaticProperty *BKE_override_static_property_get(struct IDOverrideStatic *override, const char *rna_path, bool *r_created);
+void BKE_override_static_property_delete(struct IDOverrideStatic *override, struct IDOverrideStaticProperty *override_property);
+
+struct IDOverrideStaticPropertyOperation *BKE_override_static_property_operation_find(
+ struct IDOverrideStaticProperty *override_property,
+ const char *subitem_refname, const char *subitem_locname,
+ const int subitem_refindex, const int subitem_locindex, const bool strict, bool *r_strict);
+struct IDOverrideStaticPropertyOperation *BKE_override_static_property_operation_get(
+ struct IDOverrideStaticProperty *override_property, const short operation,
+ const char *subitem_refname, const char *subitem_locname,
+ const int subitem_refindex, const int subitem_locindex,
+ const bool strict, bool *r_strict, bool *r_created);
+void BKE_override_static_property_operation_delete(
+ struct IDOverrideStaticProperty *override_property, struct IDOverrideStaticPropertyOperation *override_property_operation);
+
+bool BKE_override_static_status_check_local(struct ID *local);
+bool BKE_override_static_status_check_reference(struct ID *local);
+
+bool BKE_override_static_operations_create(struct ID *local);
+void BKE_main_override_static_operations_create(struct Main *bmain);
+
+void BKE_override_static_update(struct Main *bmain, struct ID *local);
+void BKE_main_override_static_update(struct Main *bmain);
+
+
+/* Storage (.blend file writing) part. */
+
+/* For now, we just use a temp main list. */
+typedef struct Main OverrideStaticStorage;
+
+OverrideStaticStorage *BKE_override_static_operations_store_initialize(void);
+struct ID *BKE_override_static_operations_store_start(OverrideStaticStorage *override_storage, struct ID *local);
+void BKE_override_static_operations_store_end(OverrideStaticStorage *override_storage, struct ID *local);
+void BKE_override_static_operations_store_finalize(OverrideStaticStorage *override_storage);
+
+
+
+#endif /* __BKE_LIBRARY_OVERRIDE_H__ */
diff --git a/source/blender/blenkernel/BKE_library_query.h b/source/blender/blenkernel/BKE_library_query.h
index d6e7d98f371..b66fc0aab16 100644
--- a/source/blender/blenkernel/BKE_library_query.h
+++ b/source/blender/blenkernel/BKE_library_query.h
@@ -56,6 +56,9 @@ enum {
* How to handle that kind of cases totally depends on what caller code is doing... */
IDWALK_CB_LOOPBACK = (1 << 4),
+ /** That ID is used as static override's reference by its owner. */
+ IDWALK_CB_STATIC_OVERRIDE_REFERENCE = (1 << 5),
+
/**
* Adjusts #ID.us reference-count.
* \note keep in sync with 'newlibadr_us' use in readfile.c
diff --git a/source/blender/blenkernel/BKE_library_remap.h b/source/blender/blenkernel/BKE_library_remap.h
index fd37fd762f4..3425ca011b7 100644
--- a/source/blender/blenkernel/BKE_library_remap.h
+++ b/source/blender/blenkernel/BKE_library_remap.h
@@ -51,6 +51,8 @@ enum {
* This is needed e.g. in reload scenario, since we have to ensure remapping of Armature data of local proxy
* is also performed. Usual nightmare... */
ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE = 1 << 4,
+ /* Do not remap static override pointers. */
+ ID_REMAP_SKIP_STATIC_OVERRIDE = 1 << 5,
};
/* Note: Requiring new_id to be non-null, this *may* not be the case ultimately, but makes things simpler for now. */
diff --git a/source/blender/blenkernel/BKE_lightprobe.h b/source/blender/blenkernel/BKE_lightprobe.h
new file mode 100644
index 00000000000..a769b6653d7
--- /dev/null
+++ b/source/blender/blenkernel/BKE_lightprobe.h
@@ -0,0 +1,46 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BKE_LIGHTPROBE_H__
+#define __BKE_LIGHTPROBE_H__
+
+/** \file BKE_lightprobe.h
+ * \ingroup bke
+ * \brief General operations for probes.
+ */
+
+struct Main;
+struct LightProbe;
+
+void BKE_lightprobe_init(struct LightProbe *probe);
+void *BKE_lightprobe_add(struct Main *bmain, const char *name);
+void BKE_lightprobe_copy_data(struct Main *bmain, struct LightProbe *probe_dst, const struct LightProbe *probe_src, const int flag);
+struct LightProbe *BKE_lightprobe_copy(struct Main *bmain, const struct LightProbe *probe);
+void BKE_lightprobe_make_local(struct Main *bmain, struct LightProbe *probe, const bool lib_local);
+void BKE_lightprobe_free(struct LightProbe *probe);
+
+#endif /* __BKE_LIGHTPROBE_H__ */
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index d8318bfcf5d..79f56cf25ef 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -108,6 +108,7 @@ typedef struct Main {
ListBase vfont;
ListBase text;
ListBase speaker;
+ ListBase lightprobe;
ListBase sound;
ListBase group;
ListBase armature;
@@ -123,6 +124,7 @@ typedef struct Main {
ListBase mask;
ListBase linestyle;
ListBase cachefiles;
+ ListBase workspaces;
char id_tag_update[MAX_LIBARRAY];
diff --git a/source/blender/blenkernel/BKE_mask.h b/source/blender/blenkernel/BKE_mask.h
index 5598f0dc473..8b9fea071b0 100644
--- a/source/blender/blenkernel/BKE_mask.h
+++ b/source/blender/blenkernel/BKE_mask.h
@@ -145,7 +145,6 @@ void BKE_mask_update_display(struct Mask *mask, float ctime);
void BKE_mask_evaluate_all_masks(struct Main *bmain, float ctime, const bool do_newframe);
void BKE_mask_evaluate(struct Mask *mask, const float ctime, const bool do_newframe);
void BKE_mask_layer_evaluate(struct MaskLayer *masklay, const float ctime, const bool do_newframe);
-void BKE_mask_update_scene(struct Main *bmain, struct Scene *scene);
void BKE_mask_parent_init(struct MaskParent *parent);
void BKE_mask_calc_handle_adjacent_interp(struct MaskSpline *spline, struct MaskSplinePoint *point, const float u);
void BKE_mask_calc_tangent_polyline(struct MaskSpline *spline, struct MaskSplinePoint *point, float t[2]);
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index f7850913014..f4c98fc0aea 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -87,6 +87,10 @@ short BKE_object_material_slot_find_index(struct Object *ob, struct Material *ma
bool BKE_object_material_slot_add(struct Object *ob);
bool BKE_object_material_slot_remove(struct Object *ob);
+struct Image *BKE_object_material_edit_image_get(struct Object *ob, short mat_nr);
+struct Image **BKE_object_material_edit_image_get_array(struct Object *ob);
+bool BKE_object_material_edit_image_set(struct Object *ob, short mat_nr, struct Image *image);
+
void BKE_texpaint_slot_refresh_cache(struct Scene *scene, struct Material *ma);
void BKE_texpaint_slots_refresh_object(struct Scene *scene, struct Object *ob);
@@ -106,17 +110,17 @@ bool material_in_material(struct Material *parmat, struct Material *mat);
void ramp_blend(int type, float r_col[3], const float fac, const float col[3]);
-/* driver update hacks */
-void material_drivers_update(struct Scene *scene, struct Material *mat, float ctime);
-
/* copy/paste */
void clear_matcopybuf(void);
void free_matcopybuf(void);
void copy_matcopybuf(struct Material *ma);
void paste_matcopybuf(struct Material *ma);
-/* handle backward compatibility for tface/materials called from doversion */
-int do_version_tface(struct Main *main);
+/* Evaluation. */
+
+struct EvaluationContext;
+
+void BKE_material_eval(const struct EvaluationContext *eval_ctx, struct Material *material);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_mball.h b/source/blender/blenkernel/BKE_mball.h
index f02704ba903..9db277f95fb 100644
--- a/source/blender/blenkernel/BKE_mball.h
+++ b/source/blender/blenkernel/BKE_mball.h
@@ -73,7 +73,18 @@ void BKE_mball_select_swap(struct MetaBall *mb);
struct EvaluationContext;
-void BKE_mball_eval_geometry(struct EvaluationContext *eval_ctx,
+void BKE_mball_eval_geometry(const struct EvaluationContext *eval_ctx,
struct MetaBall *mball);
+/* Draw Cache */
+
+void BKE_mball_element_calc_display_m3x4(float r_scale_xform[3][4],
+ const float obmat[4][4],
+ const float local_pos[3]);
+
+enum {
+ BKE_MBALL_BATCH_DIRTY_ALL = 0,
+};
+void BKE_mball_batch_cache_dirty(struct MetaBall *mb, int mode);
+void BKE_mball_batch_cache_free(struct MetaBall *mb);
#endif
diff --git a/source/blender/blenkernel/BKE_mball_tessellate.h b/source/blender/blenkernel/BKE_mball_tessellate.h
index 361f31b704c..40cdc80e280 100644
--- a/source/blender/blenkernel/BKE_mball_tessellate.h
+++ b/source/blender/blenkernel/BKE_mball_tessellate.h
@@ -28,7 +28,7 @@ struct Object;
struct Scene;
void BKE_mball_polygonize(
- struct EvaluationContext *eval_ctx, struct Scene *scene,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
struct Object *ob, struct ListBase *dispbase);
void BKE_mball_cubeTable_free(void);
diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h
index f3b2b653e3d..5ee3b9be5f9 100644
--- a/source/blender/blenkernel/BKE_mesh.h
+++ b/source/blender/blenkernel/BKE_mesh.h
@@ -35,6 +35,7 @@ struct ID;
struct BMeshCreateParams;
struct BoundBox;
struct EdgeHash;
+struct EvaluationContext;
struct ListBase;
struct LinkNode;
struct BLI_Stack;
@@ -92,6 +93,9 @@ struct Mesh *BKE_mesh_copy(struct Main *bmain, const struct Mesh *me);
void BKE_mesh_update_customdata_pointers(struct Mesh *me, const bool do_ensure_tess_cd);
void BKE_mesh_ensure_skin_customdata(struct Mesh *me);
+bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me);
+bool BKE_mesh_clear_facemap_customdata(struct Mesh *me);
+
void BKE_mesh_make_local(struct Main *bmain, struct Mesh *me, const bool lib_local);
void BKE_mesh_boundbox_calc(struct Mesh *me, float r_loc[3], float r_size[3]);
void BKE_mesh_texspace_calc(struct Mesh *me);
@@ -115,7 +119,7 @@ void BKE_mesh_from_nurbs_displist(
struct Object *ob, struct ListBase *dispbase, const bool use_orco_uv, const char *obdata_name);
void BKE_mesh_from_nurbs(struct Object *ob);
void BKE_mesh_to_curve_nurblist(struct DerivedMesh *dm, struct ListBase *nurblist, const int edge_users_test);
-void BKE_mesh_to_curve(struct Scene *scene, struct Object *ob);
+void BKE_mesh_to_curve(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
void BKE_mesh_material_index_remove(struct Mesh *me, short index);
void BKE_mesh_material_index_clear(struct Mesh *me);
void BKE_mesh_material_remap(struct Mesh *me, const unsigned int *remap, unsigned int remap_len);
@@ -125,6 +129,7 @@ const char *BKE_mesh_cmp(struct Mesh *me1, struct Mesh *me2, float thresh);
struct BoundBox *BKE_mesh_boundbox_get(struct Object *ob);
void BKE_mesh_texspace_get(struct Mesh *me, float r_loc[3], float r_rot[3], float r_size[3]);
+void BKE_mesh_texspace_get_reference(struct Mesh *me, short **r_texflag, float **r_loc, float **r_rot, float **r_size);
void BKE_mesh_texspace_copy_from_object(struct Mesh *me, struct Object *ob);
bool BKE_mesh_uv_cdlayer_rename_index(struct Mesh *me, const int poly_index, const int loop_index, const int face_index,
@@ -135,7 +140,7 @@ float (*BKE_mesh_vertexCos_get(const struct Mesh *me, int *r_numVerts))[3];
void BKE_mesh_split_faces(struct Mesh *mesh, bool free_loop_normals);
-struct Mesh *BKE_mesh_new_from_object(struct Main *bmain, struct Scene *sce, struct Object *ob,
+struct Mesh *BKE_mesh_new_from_object(const struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *sce, struct Object *ob,
int apply_modifiers, int settings, int calc_tessface, int calc_undeformed);
/* vertex level transformations & checks (no derived mesh) */
@@ -188,13 +193,6 @@ void BKE_mesh_calc_normals_looptri(
const struct MLoop *mloop,
const struct MLoopTri *looptri, int looptri_num,
float (*r_tri_nors)[3]);
-void BKE_mesh_loop_tangents_ex(
- const struct MVert *mverts, const int numVerts, const struct MLoop *mloops,
- float (*r_looptangent)[4], float (*loopnors)[3], const struct MLoopUV *loopuv,
- const int numLoops, const struct MPoly *mpolys, const int numPolys,
- struct ReportList *reports);
-void BKE_mesh_loop_tangents(
- struct Mesh *mesh, const char *uvmap, float (*r_looptangents)[4], struct ReportList *reports);
/**
* References a contiguous loop-fan with normal offset vars.
@@ -297,7 +295,7 @@ void BKE_mesh_loops_to_mface_corners(
const int numTex, const int numCol,
const bool hasPCol, const bool hasOrigSpace, const bool hasLNor);
void BKE_mesh_loops_to_tessdata(
- struct CustomData *fdata, struct CustomData *ldata, struct CustomData *pdata, struct MFace *mface,
+ struct CustomData *fdata, struct CustomData *ldata, struct MFace *mface,
int *polyindices, unsigned int (*loopindices)[4], const int num_faces);
void BKE_mesh_tangent_loops_to_tessdata(
struct CustomData *fdata, struct CustomData *ldata, struct MFace *mface,
@@ -375,7 +373,6 @@ void BKE_mesh_calc_relative_deform(
/* *** mesh_validate.c *** */
int BKE_mesh_validate(struct Mesh *me, const int do_verbose, const int cddata_check_mask);
-void BKE_mesh_cd_validate(struct Mesh *me);
int BKE_mesh_validate_material_indices(struct Mesh *me);
bool BKE_mesh_validate_arrays(
@@ -405,11 +402,20 @@ void BKE_mesh_calc_edges(struct Mesh *mesh, bool update, const bool select);
/* **** Depsgraph evaluation **** */
-struct EvaluationContext;
-
-void BKE_mesh_eval_geometry(struct EvaluationContext *eval_ctx,
+void BKE_mesh_eval_geometry(const struct EvaluationContext *eval_ctx,
struct Mesh *mesh);
+/* Draw Cache */
+enum {
+ BKE_MESH_BATCH_DIRTY_ALL = 0,
+ BKE_MESH_BATCH_DIRTY_MAYBE_ALL,
+ BKE_MESH_BATCH_DIRTY_SELECT,
+ BKE_MESH_BATCH_DIRTY_SHADING,
+ BKE_MESH_BATCH_DIRTY_SCULPT_COORDS,
+};
+void BKE_mesh_batch_cache_dirty(struct Mesh *me, int mode);
+void BKE_mesh_batch_cache_free(struct Mesh *me);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_mesh_tangent.h b/source/blender/blenkernel/BKE_mesh_tangent.h
new file mode 100644
index 00000000000..cb3100c1c2f
--- /dev/null
+++ b/source/blender/blenkernel/BKE_mesh_tangent.h
@@ -0,0 +1,61 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __BKE_MESH_TANGENT_H__
+#define __BKE_MESH_TANGENT_H__
+
+void BKE_mesh_calc_loop_tangent_single_ex(
+ const struct MVert *mverts, const int numVerts, const struct MLoop *mloops,
+ float (*r_looptangent)[4], float (*loopnors)[3], const struct MLoopUV *loopuv,
+ const int numLoops, const struct MPoly *mpolys, const int numPolys,
+ struct ReportList *reports);
+void BKE_mesh_calc_loop_tangent_single(
+ struct Mesh *mesh, const char *uvmap, float (*r_looptangents)[4], struct ReportList *reports);
+
+void BKE_mesh_calc_loop_tangent_ex(
+ const struct MVert *mvert,
+ const struct MPoly *mpoly, const uint mpoly_len,
+ const struct MLoop *mloop,
+ const struct MLoopTri *looptri, const uint looptri_len,
+
+ struct CustomData *loopdata,
+ bool calc_active_tangent,
+ const char (*tangent_names)[64], int tangent_names_len,
+ const float (*poly_normals)[3],
+ const float (*loop_normals)[3],
+ const float (*vert_orco)[3],
+ /* result */
+ struct CustomData *loopdata_out,
+ const uint loopdata_out_len,
+ short *tangent_mask_curr_p);
+
+/* Helpers */
+void BKE_mesh_add_loop_tangent_named_layer_for_uv(
+ struct CustomData *uv_data, struct CustomData *tan_data, int numLoopData,
+ const char *layer_name);
+
+#define DM_TANGENT_MASK_ORCO (1 << 9)
+void BKE_mesh_calc_loop_tangent_step_0(
+ const struct CustomData *loopData, bool calc_active_tangent,
+ const char (*tangent_names)[64], int tangent_names_count,
+ bool *rcalc_act, bool *rcalc_ren, int *ract_uv_n, int *rren_uv_n,
+ char *ract_uv_name, char *rren_uv_name, short *rtangent_mask);
+
+#endif /* __BKE_MESH_TANGENT_H__ */
+
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index 30c47a4b192..451823aedf5 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -36,8 +36,10 @@ struct ID;
struct DerivedMesh;
struct DagForest;
struct DagNode;
+struct EvaluationContext;
struct Object;
struct Scene;
+struct ViewLayer;
struct ListBase;
struct bArmature;
struct Main;
@@ -157,25 +159,27 @@ typedef struct ModifierTypeInfo {
* the object it can obtain it from the derivedData argument if non-NULL,
* and otherwise the ob argument.
*/
- void (*deformVerts)(struct ModifierData *md, struct Object *ob,
- struct DerivedMesh *derivedData,
+ void (*deformVerts)(struct ModifierData *md, const struct EvaluationContext *eval_ctx,
+ struct Object *ob, struct DerivedMesh *derivedData,
float (*vertexCos)[3], int numVerts,
ModifierApplyFlag flag);
/* Like deformMatricesEM but called from object mode (for supporting modifiers in sculpt mode) */
- void (*deformMatrices)(struct ModifierData *md, struct Object *ob,
- struct DerivedMesh *derivedData,
+ void (*deformMatrices)(struct ModifierData *md, const struct EvaluationContext *eval_ctx,
+ struct Object *ob, struct DerivedMesh *derivedData,
float (*vertexCos)[3], float (*defMats)[3][3], int numVerts);
/* Like deformVerts but called during editmode (for supporting modifiers)
*/
- void (*deformVertsEM)(struct ModifierData *md, struct Object *ob,
- struct BMEditMesh *editData, struct DerivedMesh *derivedData,
+ void (*deformVertsEM)(struct ModifierData *md, const struct EvaluationContext *eval_ctx,
+ struct Object *ob, struct BMEditMesh *editData,
+ struct DerivedMesh *derivedData,
float (*vertexCos)[3], int numVerts);
/* Set deform matrix per vertex for crazyspace correction */
- void (*deformMatricesEM)(struct ModifierData *md, struct Object *ob,
- struct BMEditMesh *editData, struct DerivedMesh *derivedData,
+ void (*deformMatricesEM)(struct ModifierData *md, const struct EvaluationContext *eval_ctx,
+ struct Object *ob, struct BMEditMesh *editData,
+ struct DerivedMesh *derivedData,
float (*vertexCos)[3], float (*defMats)[3][3], int numVerts);
/********************* Non-deform modifier functions *********************/
@@ -199,8 +203,8 @@ typedef struct ModifierTypeInfo {
* The modifier may reuse the derivedData argument (i.e. return it in
* modified form), but must not release it.
*/
- struct DerivedMesh *(*applyModifier)(struct ModifierData *md, struct Object *ob,
- struct DerivedMesh *derivedData,
+ struct DerivedMesh *(*applyModifier)(struct ModifierData *md, const struct EvaluationContext *eval_ctx,
+ struct Object *ob, struct DerivedMesh *derivedData,
ModifierApplyFlag flag);
/* Like applyModifier but called during editmode (for supporting
@@ -210,10 +214,9 @@ typedef struct ModifierTypeInfo {
* are expected from editmode objects. The same qualifications regarding
* derivedData apply as for applyModifier.
*/
- struct DerivedMesh *(*applyModifierEM)(struct ModifierData *md, struct Object *ob,
- struct BMEditMesh *editData,
- struct DerivedMesh *derivedData,
- ModifierApplyFlag flag);
+ struct DerivedMesh *(*applyModifierEM)(struct ModifierData *md, const struct EvaluationContext *eval_ctx,
+ struct Object *ob, struct BMEditMesh *editData,
+ struct DerivedMesh *derivedData, ModifierApplyFlag flag);
/********************* Optional functions *********************/
@@ -260,20 +263,10 @@ typedef struct ModifierTypeInfo {
*/
bool (*isDisabled)(struct ModifierData *md, int userRenderParams);
- /* Add the appropriate relations to the DEP graph depending on the
- * modifier data.
- *
- * This function is optional.
- */
- void (*updateDepgraph)(struct ModifierData *md, struct DagForest *forest,
- struct Main *bmain, struct Scene *scene,
- struct Object *ob, struct DagNode *obNode);
-
/* Add the appropriate relations to the dependency graph.
*
* This function is optional.
*/
- /* TODO(sergey): Remove once we finally switched to the new depsgraph. */
void (*updateDepsgraph)(struct ModifierData *md,
struct Main *bmain,
struct Scene *scene,
@@ -427,24 +420,24 @@ const char *modifier_path_relbase(struct Object *ob);
/* wrappers for modifier callbacks */
struct DerivedMesh *modwrap_applyModifier(
- ModifierData *md, struct Object *ob,
- struct DerivedMesh *dm,
+ ModifierData *md, const struct EvaluationContext *eval_ctx,
+ struct Object *ob, struct DerivedMesh *dm,
ModifierApplyFlag flag);
struct DerivedMesh *modwrap_applyModifierEM(
- ModifierData *md, struct Object *ob,
- struct BMEditMesh *em,
+ ModifierData *md, const struct EvaluationContext *eval_ctx,
+ struct Object *ob, struct BMEditMesh *em,
struct DerivedMesh *dm,
ModifierApplyFlag flag);
void modwrap_deformVerts(
- ModifierData *md, struct Object *ob,
- struct DerivedMesh *dm,
+ ModifierData *md, const struct EvaluationContext *eval_ctx,
+ struct Object *ob, struct DerivedMesh *dm,
float (*vertexCos)[3], int numVerts,
ModifierApplyFlag flag);
void modwrap_deformVertsEM(
- ModifierData *md, struct Object *ob,
+ ModifierData *md, const struct EvaluationContext *eval_ctx, struct Object *ob,
struct BMEditMesh *em, struct DerivedMesh *dm,
float (*vertexCos)[3], int numVerts);
diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h
index 178751d1640..761bb7e8acb 100644
--- a/source/blender/blenkernel/BKE_multires.h
+++ b/source/blender/blenkernel/BKE_multires.h
@@ -34,6 +34,7 @@
enum MultiresModifiedFlags;
struct DerivedMesh;
+struct EvaluationContext;
struct MDisps;
struct Mesh;
struct ModifierData;
@@ -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(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct MultiresModifierData *mmd,
struct Object *ob);
void multiresModifier_del_levels(struct MultiresModifierData *, struct Object *, int direction);
void multiresModifier_base_apply(struct MultiresModifierData *mmd, struct Object *ob);
void multiresModifier_subdivide(struct MultiresModifierData *mmd, struct Object *ob, int updateblock, int simple);
void multiresModifier_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(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct MultiresModifierData *mmd,
struct Object *dst, struct Object *src);
-int multiresModifier_reshapeFromDM(struct Scene *scene, struct MultiresModifierData *mmd,
+int multiresModifier_reshapeFromDM(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct MultiresModifierData *mmd,
struct Object *ob, struct DerivedMesh *srcdm);
-int multiresModifier_reshapeFromDeformMod(struct Scene *scene, struct MultiresModifierData *mmd,
+int multiresModifier_reshapeFromDeformMod(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct MultiresModifierData *mmd,
struct Object *ob, struct ModifierData *md);
void multires_stitch_grids(struct Object *);
@@ -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(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
+void multiresModifier_prepare_join(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct Object *to_ob);
int multires_mdisp_corners(struct MDisps *s);
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 1a31a74ee0a..3156749070e 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -74,6 +74,7 @@ struct PointerRNA;
struct RenderData;
struct Scene;
struct Tex;
+struct ViewRender;
struct SpaceNode;
struct ARegion;
struct ColorManagedViewSettings;
@@ -251,8 +252,9 @@ typedef struct bNodeType {
#define NODE_CLASS_LAYOUT 100
/* nodetype->compatibility */
-#define NODE_OLD_SHADING 1
-#define NODE_NEW_SHADING 2
+#define NODE_OLD_SHADING (1 << 0)
+#define NODE_NEW_SHADING (1 << 1)
+#define NODE_NEWER_SHADING (1 << 2)
/* node resize directions */
#define NODE_RESIZE_TOP 1
@@ -281,7 +283,7 @@ typedef struct bNodeTreeType {
/* callbacks */
void (*free_cache)(struct bNodeTree *ntree);
void (*free_node_cache)(struct bNodeTree *ntree, struct bNode *node);
- void (*foreach_nodeclass)(struct Scene *scene, void *calldata, bNodeClassCallback func); /* iteration over all node classes */
+ void (*foreach_nodeclass)(struct ViewRender *view_render, void *calldata, bNodeClassCallback func); /* iteration over all node classes */
/* Check visibility in the node editor */
int (*poll)(const struct bContext *C, struct bNodeTreeType *ntreetype);
/* Select a node tree from the context */
@@ -689,6 +691,13 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
}
/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Node Tree
+ */
+
+void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, const int layer_index);
+
/* -------------------------------------------------------------------- */
/** \name Shader Nodes
*/
@@ -788,6 +797,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
/* custom defines options for Material node */
@@ -807,6 +817,7 @@ extern void (*node_shader_lamp_loop)(struct ShadeInput *, struct ShadeResult *);
void set_node_shader_lamp_loop(void (*lamp_loop_func)(struct ShadeInput *, struct ShadeResult *));
void ntreeGPUMaterialNodes(struct bNodeTree *ntree, struct GPUMaterial *mat, short compatibility);
+void ntreeGPUMaterialDomain(struct bNodeTree *ntree, bool *has_surface_output, bool *has_volume_output);
/** \} */
@@ -977,7 +988,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,
@@ -1042,4 +1053,16 @@ int ntreeTexExecTree(struct bNodeTree *ntree, struct TexResult *target,
void init_nodesystem(void);
void free_nodesystem(void);
+/* -------------------------------------------------------------------- */
+/* evaluation support, */
+
+struct EvaluationContext;
+
+void BKE_nodetree_copy_default_values(struct bNodeTree *ntree_dst,
+ const struct bNodeTree *ntree_src);
+
+void BKE_nodetree_shading_params_eval(const struct EvaluationContext *eval_ctx,
+ struct bNodeTree *ntree_dst,
+ const struct bNodeTree *ntree_src);
+
#endif /* __BKE_NODE_H__ */
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 4d232e9ed6c..d98c52aa91a 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -38,6 +38,7 @@ extern "C" {
struct Base;
struct EvaluationContext;
struct Scene;
+struct ViewLayer;
struct Object;
struct BoundBox;
struct View3D;
@@ -50,7 +51,7 @@ struct HookModifierData;
struct ModifierData;
void BKE_object_workob_clear(struct Object *workob);
-void BKE_object_workob_calc_parent(struct Scene *scene, struct Object *ob, struct Object *workob);
+void BKE_object_workob_calc_parent(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct Object *workob);
void BKE_object_transform_copy(struct Object *ob_tar, const struct Object *ob_src);
struct SoftBody *copy_softbody(const struct SoftBody *sb, const int flag);
@@ -62,7 +63,6 @@ void BKE_object_free_particlesystems(struct Object *ob);
void BKE_object_free_softbody(struct Object *ob);
void BKE_object_free_bulletsoftbody(struct Object *ob);
void BKE_object_free_curve_cache(struct Object *ob);
-void BKE_object_update_base_layer(struct Scene *scene, struct Object *ob);
void BKE_object_free(struct Object *ob);
void BKE_object_free_derived_caches(struct Object *ob);
@@ -83,15 +83,27 @@ bool BKE_object_is_in_editmode(struct Object *ob);
bool BKE_object_is_in_editmode_vgroup(struct Object *ob);
bool BKE_object_is_in_wpaint_select_vert(struct Object *ob);
+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(
struct Main *bmain,
int type, const char *name)
ATTR_NONNULL(1) ATTR_RETURNS_NONNULL;
struct Object *BKE_object_add(
- struct Main *bmain, struct Scene *scene,
+ struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer,
int type, const char *name)
- ATTR_NONNULL(1, 2) ATTR_RETURNS_NONNULL;
+ ATTR_NONNULL(1, 2, 3) ATTR_RETURNS_NONNULL;
+struct Object *BKE_object_add_from(
+ struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer,
+ int type, const char *name, struct Object *ob_src)
+ ATTR_NONNULL(1, 2, 3, 6) ATTR_RETURNS_NONNULL;
void *BKE_object_obdata_add_from_type(
struct Main *bmain,
int type, const char *name)
@@ -101,9 +113,9 @@ void BKE_object_lod_add(struct Object *ob);
void BKE_object_lod_sort(struct Object *ob);
bool BKE_object_lod_remove(struct Object *ob, int level);
void BKE_object_lod_update(struct Object *ob, const float camera_position[3]);
-bool BKE_object_lod_is_usable(struct Object *ob, struct Scene *scene);
-struct Object *BKE_object_lod_meshob_get(struct Object *ob, struct Scene *scene);
-struct Object *BKE_object_lod_matob_get(struct Object *ob, struct Scene *scene);
+bool BKE_object_lod_is_usable(struct Object *ob, struct ViewLayer *view_layer);
+struct Object *BKE_object_lod_meshob_get(struct Object *ob, struct ViewLayer *view_layer);
+struct Object *BKE_object_lod_matob_get(struct Object *ob, struct ViewLayer *view_layer);
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);
@@ -125,11 +137,12 @@ void BKE_object_matrix_local_get(struct Object *ob, float mat[4][4]);
bool BKE_object_pose_context_check(struct Object *ob);
struct Object *BKE_object_pose_armature_get(struct Object *ob);
-void BKE_object_get_parent_matrix(struct Scene *scene, struct Object *ob, struct Object *par, float parentmat[4][4]);
-void BKE_object_where_is_calc(struct Scene *scene, struct Object *ob);
-void BKE_object_where_is_calc_ex(struct Scene *scene, struct RigidBodyWorld *rbw, struct Object *ob, float r_originmat[3][3]);
-void BKE_object_where_is_calc_time(struct Scene *scene, struct Object *ob, float ctime);
-void BKE_object_where_is_calc_time_ex(struct Scene *scene, struct Object *ob, float ctime,
+void BKE_object_get_parent_matrix(struct Scene *scene, struct Object *ob,
+ struct Object *par, float parentmat[4][4]);
+void BKE_object_where_is_calc(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
+void BKE_object_where_is_calc_ex(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct RigidBodyWorld *rbw, struct Object *ob, float r_originmat[3][3]);
+void BKE_object_where_is_calc_time(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, float ctime);
+void BKE_object_where_is_calc_time_ex(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, float ctime,
struct RigidBodyWorld *rbw, float r_originmat[3][3]);
void BKE_object_where_is_calc_mat4(struct Scene *scene, struct Object *ob, float obmat[4][4]);
@@ -152,8 +165,7 @@ bool BKE_object_minmax_dupli(struct Scene *scene, struct Object *ob, float r_min
void BKE_object_foreach_display_point(struct Object *ob, float obmat[4][4],
void (*func_cb)(const float[3], void *), void *user_data);
void BKE_scene_foreach_display_point(struct Scene *scene,
- struct View3D *v3d,
- const short flag,
+ struct ViewLayer *view_layer,
void (*func_cb)(const float[3], void *), void *user_data);
bool BKE_object_parent_loop_check(const struct Object *parent, const struct Object *ob);
@@ -178,41 +190,54 @@ void BKE_object_tfm_protected_restore(struct Object *ob,
const short protectflag);
/* Dependency graph evaluation callbacks. */
-void BKE_object_eval_local_transform(struct EvaluationContext *eval_ctx,
+void BKE_object_eval_local_transform(const struct EvaluationContext *eval_ctx,
struct Object *ob);
-void BKE_object_eval_parent(struct EvaluationContext *eval_ctx,
+void BKE_object_eval_parent(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob);
-void BKE_object_eval_constraints(struct EvaluationContext *eval_ctx,
+void BKE_object_eval_constraints(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob);
-void BKE_object_eval_done(struct EvaluationContext *eval_ctx, struct Object *ob);
+void BKE_object_eval_done(const struct EvaluationContext *eval_ctx, struct Object *ob);
-bool BKE_object_eval_proxy_copy(struct EvaluationContext *eval_ctx,
+bool BKE_object_eval_proxy_copy(const struct EvaluationContext *eval_ct,
struct Object *object);
-void BKE_object_eval_uber_transform(struct EvaluationContext *eval_ctx,
+void BKE_object_eval_uber_transform(const struct EvaluationContext *eval_ctx,
struct Object *ob);
-void BKE_object_eval_uber_data(struct EvaluationContext *eval_ctx,
+void BKE_object_eval_uber_data(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob);
-void BKE_object_eval_cloth(struct EvaluationContext *eval_ctx,
+void BKE_object_eval_cloth(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *object);
-
-void BKE_object_eval_transform_all(struct EvaluationContext *eval_ctx,
+void BKE_object_eval_transform_all(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *object);
-void BKE_object_handle_data_update(struct EvaluationContext *eval_ctx,
- struct Scene *scene,
- struct Object *ob);
-void BKE_object_handle_update(struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob);
-void BKE_object_handle_update_ex(struct EvaluationContext *eval_ctx,
- struct Scene *scene, struct Object *ob,
- struct RigidBodyWorld *rbw,
- const bool do_proxy_update);
+void BKE_object_eval_update_shading(const struct EvaluationContext *eval_ctx,
+ struct Object *object);
+void BKE_object_data_select_update(const struct EvaluationContext *eval_ctx,
+ struct ID *object_data);
+
+void BKE_object_eval_flush_base_flags(const struct EvaluationContext *eval_ctx,
+ struct Object *object, struct Base *base,
+ const bool is_from_set);
+
+void BKE_object_handle_data_update(
+ const struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob);
+void BKE_object_handle_update(
+ const struct EvaluationContext *eval_ctx,
+ struct Scene *scene, struct Object *ob);
+void BKE_object_handle_update_ex(
+ const struct EvaluationContext *eval_ctx,
+ struct Scene *scene, struct Object *ob,
+ struct RigidBodyWorld *rbw,
+ const bool do_proxy_update);
+
void BKE_object_sculpt_modifiers_changed(struct Object *ob);
int BKE_object_obdata_texspace_get(struct Object *ob, short **r_texflag, float **r_loc, float **r_size, float **r_rot);
@@ -255,17 +280,16 @@ typedef enum eObjectSet {
OB_SET_ALL /* All Objects */
} eObjectSet;
-struct LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter);
+struct LinkNode *BKE_object_relational_superset(struct ViewLayer *view_layer, eObjectSet objectSet, eObRelationTypes includeFilter);
struct LinkNode *BKE_object_groups(struct Object *ob);
-void BKE_object_groups_clear(struct Scene *scene, struct Base *base, struct Object *object);
+void BKE_object_groups_clear(struct Object *object);
struct KDTree *BKE_object_as_kdtree(struct Object *ob, int *r_tot);
bool BKE_object_modifier_use_time(struct Object *ob, struct ModifierData *md);
-bool BKE_object_modifier_update_subframe(struct Scene *scene, struct Object *ob, bool update_mesh,
- int parent_recursion, float frame,
- int type);
+bool BKE_object_modifier_update_subframe(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob,
+ bool update_mesh, int parent_recursion, float frame, int type);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_object_facemap.h b/source/blender/blenkernel/BKE_object_facemap.h
new file mode 100644
index 00000000000..2607e5aa2dd
--- /dev/null
+++ b/source/blender/blenkernel/BKE_object_facemap.h
@@ -0,0 +1,53 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Antony Riakiotakis
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BKE_OBJECT_FACEMAP_H__
+#define __BKE_OBJECT_FACEMAP_H__
+
+/** \file BKE_object_facemap.h
+ * \ingroup bke
+ * \brief Functions for dealing with object face-maps.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bFaceMap;
+struct ListBase;
+struct Object;
+
+struct bFaceMap *BKE_object_facemap_add(struct Object *ob);
+struct bFaceMap *BKE_object_facemap_add_name(struct Object *ob, const char *name);
+void BKE_object_facemap_remove(struct Object *ob, struct bFaceMap *fmap);
+void BKE_object_facemap_clear(struct Object *ob);
+
+int BKE_object_facemap_name_index(struct Object *ob, const char *name);
+void BKE_object_facemap_unique_name(struct Object *ob, struct bFaceMap *fmap);
+struct bFaceMap *BKE_object_facemap_find_name(struct Object *ob, const char *name);
+void BKE_object_facemap_copy_list(struct ListBase *outbase, const struct ListBase *inbase);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __BKE_OBJECT_FACEMAP_H__ */
diff --git a/source/blender/blenkernel/BKE_outliner_treehash.h b/source/blender/blenkernel/BKE_outliner_treehash.h
index 454edb40c4e..b82bc692402 100644
--- a/source/blender/blenkernel/BKE_outliner_treehash.h
+++ b/source/blender/blenkernel/BKE_outliner_treehash.h
@@ -36,8 +36,9 @@ void *BKE_outliner_treehash_create_from_treestore(struct BLI_mempool *treestore)
/* full rebuild for already allocated hashtable */
void *BKE_outliner_treehash_rebuild_from_treestore(void *treehash, struct BLI_mempool *treestore);
-/* full rebuild for already allocated hashtable */
+/* Add/remove hashtable elements */
void BKE_outliner_treehash_add_element(void *treehash, struct TreeStoreElem *elem);
+void BKE_outliner_treehash_remove_element(void *treehash, struct TreeStoreElem *elem);
/* find first unused element with specific type, nr and id */
struct TreeStoreElem *BKE_outliner_treehash_lookup_unused(void *treehash, short type, short nr, struct ID *id);
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index cc02d8b547e..b952859e508 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -52,11 +52,13 @@ struct PaletteColor;
struct PBVH;
struct ReportList;
struct Scene;
+struct ViewLayer;
struct Sculpt;
struct StrokeCache;
struct Tex;
struct ImagePool;
struct UnifiedPaintSettings;
+struct EvaluationContext;
enum eOverlayFlags;
@@ -89,8 +91,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);
@@ -124,7 +126,7 @@ void BKE_paint_cavity_curve_preset(struct Paint *p, int preset);
short 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(
+ const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Sculpt *sd, struct Object *ob,
+ bool need_pmap, bool need_mask);
struct MultiresModifierData *BKE_sculpt_multires_active(struct Scene *scene, struct Object *ob);
int BKE_sculpt_mask_layers_ensure(struct Object *ob,
struct MultiresModifierData *mmd);
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 2c72373c2a9..8bc521c515f 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -62,6 +62,8 @@ struct RNG;
struct BVHTreeRay;
struct BVHTreeRayHit;
struct EdgeHash;
+struct EvaluationContext;
+struct ViewLayer;
#define PARTICLE_COLLISION_MAX_COLLISIONS 10
@@ -77,6 +79,7 @@ struct EdgeHash;
/* common stuff that many particle functions need */
typedef struct ParticleSimulationData {
+ const struct EvaluationContext *eval_ctx;
struct Scene *scene;
struct Object *ob;
struct ParticleSystem *psys;
@@ -295,7 +298,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 ViewLayer *view_layer, struct ParticleSystem *psys);
bool psys_check_enabled(struct Object *ob, struct ParticleSystem *psys, const bool use_render_params);
bool psys_check_edited(struct ParticleSystem *psys);
@@ -336,9 +339,9 @@ void psys_reset(struct ParticleSystem *psys, int mode);
void psys_find_parents(struct ParticleSimulationData *sim, const bool use_render_params);
void psys_cache_paths(struct ParticleSimulationData *sim, float cfra, const bool use_render_params);
-void psys_cache_edit_paths(struct Scene *scene, struct Object *ob, struct PTCacheEdit *edit, float cfra, const bool use_render_params);
+void psys_cache_edit_paths(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct PTCacheEdit *edit, float cfra, const bool use_render_params);
void psys_cache_child_paths(struct ParticleSimulationData *sim, float cfra, const bool editupdate, const bool use_render_params);
-int do_guides(struct ParticleSettings *part, struct ListBase *effectors, ParticleKey *state, int pa_num, float time);
+int do_guides(const struct EvaluationContext *eval_ctx, struct ParticleSettings *part, struct ListBase *effectors, ParticleKey *state, int pa_num, float time);
void precalc_guides(struct ParticleSimulationData *sim, struct ListBase *effectors);
float psys_get_timestep(struct ParticleSimulationData *sim);
float psys_get_child_time(struct ParticleSystem *psys, struct ChildParticle *cpa, float cfra, float *birthtime, float *dietime);
@@ -370,7 +373,7 @@ void psys_tasks_create(struct ParticleThreadContext *ctx, int startpart, int end
void psys_tasks_free(struct ParticleTask *tasks, int numtasks);
void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3]);
-void psys_apply_hair_lattice(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
+void psys_apply_hair_lattice(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
/* particle_system.c */
struct ParticleSystem *psys_get_target_system(struct Object *ob, struct ParticleTarget *pt);
@@ -385,7 +388,7 @@ void psys_check_boid_data(struct ParticleSystem *psys);
void psys_get_birth_coords(struct ParticleSimulationData *sim, struct ParticleData *pa, struct ParticleKey *state, float dtime, float cfra);
-void particle_system_update(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, const bool use_render_params);
+void particle_system_update(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob, struct ParticleSystem *psys, const bool use_render_params);
/* Callback format for performing operations on ID-pointers for particle systems */
typedef void (*ParticleSystemIDFunc)(struct ParticleSystem *psys, struct ID **idpoin, void *userdata, int cb_flag);
@@ -477,8 +480,20 @@ typedef struct ParticleRenderData {
struct EvaluationContext;
-void BKE_particle_system_eval_init(struct EvaluationContext *eval_ctx,
+void BKE_particle_system_settings_eval(const struct EvaluationContext *eval_ctx,
+ struct ParticleSystem *psys);
+void BKE_particle_system_settings_recalc_clear(struct EvaluationContext *UNUSED(eval_ctx),
+ struct ParticleSettings *particle_settings);
+
+void BKE_particle_system_eval_init(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob);
#endif
+
+/* Draw Cache */
+enum {
+ BKE_PARTICLE_BATCH_DIRTY_ALL = 0,
+};
+void BKE_particle_batch_cache_dirty(struct ParticleSystem *psys, int mode);
+void BKE_particle_batch_cache_free(struct ParticleSystem *psys);
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index f619133ee4b..5f37aa25de7 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -30,6 +30,7 @@
#include "BLI_ghash.h"
#include "BLI_utildefines.h"
+struct Gwn_Batch;
struct CCGElem;
struct CCGKey;
struct CCGDerivedMesh;
@@ -132,6 +133,9 @@ void BKE_pbvh_node_draw(PBVHNode *node, void *data);
void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3],
int (*setMaterial)(int matnr, void *attribs), bool wireframe, bool fast);
void BKE_pbvh_draw_BB(PBVH *bvh);
+void BKE_pbvh_draw_cb(
+ PBVH *bvh, float (*planes)[4], float (*fnors)[3], bool fast,
+ void (*draw_fn)(void *user_data, struct Gwn_Batch *batch), void *user_data);
/* PBVH Access */
typedef enum {
@@ -369,6 +373,7 @@ bool BKE_pbvh_node_vert_update_check_any(PBVH *bvh, PBVHNode *node);
//void BKE_pbvh_node_BB_reset(PBVHNode *node);
//void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3]);
+bool pbvh_has_mask(PBVH *bvh);
void pbvh_show_diffuse_color_set(PBVH *bvh, bool show_diffuse_color);
void pbvh_show_mask_set(PBVH *bvh, bool show_mask);
diff --git a/source/blender/blenkernel/BKE_pointcache.h b/source/blender/blenkernel/BKE_pointcache.h
index f0819c8d79d..9a5a9e9e56a 100644
--- a/source/blender/blenkernel/BKE_pointcache.h
+++ b/source/blender/blenkernel/BKE_pointcache.h
@@ -90,6 +90,7 @@ struct ParticleKey;
struct ParticleSystem;
struct PointCache;
struct Scene;
+struct ViewLayer;
struct SmokeModifierData;
struct SoftBody;
struct RigidBodyWorld;
@@ -186,6 +187,8 @@ typedef struct PTCacheID {
typedef struct PTCacheBaker {
struct Main *main;
struct Scene *scene;
+ struct ViewLayer *view_layer;
+ struct Depsgraph *depsgraph;
int bake;
int render;
int anim_init;
@@ -319,7 +322,7 @@ struct PointCache *BKE_ptcache_copy_list(struct ListBase *ptcaches_new, const st
/********************** Baking *********************/
/* Bakes cache with cache_step sized jumps in time, not accurate but very fast. */
-void BKE_ptcache_quick_cache_all(struct Main *bmain, struct Scene *scene);
+void BKE_ptcache_quick_cache_all(struct Main *bmain, struct Scene *scene, struct ViewLayer *view_layer);
/* Bake cache or simulate to current frame with settings defined in the baker. */
void BKE_ptcache_bake(struct PTCacheBaker *baker);
diff --git a/source/blender/blenkernel/BKE_rigidbody.h b/source/blender/blenkernel/BKE_rigidbody.h
index 3c7274ca3c5..6aa43665427 100644
--- a/source/blender/blenkernel/BKE_rigidbody.h
+++ b/source/blender/blenkernel/BKE_rigidbody.h
@@ -37,6 +37,7 @@
struct RigidBodyWorld;
struct RigidBodyOb;
+struct EvaluationContext;
struct Scene;
struct Object;
@@ -99,21 +100,19 @@ void BKE_rigidbody_aftertrans_update(struct Object *ob, float loc[3], float rot[
void BKE_rigidbody_sync_transforms(struct RigidBodyWorld *rbw, struct Object *ob, float ctime);
bool BKE_rigidbody_check_sim_running(struct RigidBodyWorld *rbw, float ctime);
void BKE_rigidbody_cache_reset(struct RigidBodyWorld *rbw);
-void BKE_rigidbody_rebuild_world(struct Scene *scene, float ctime);
-void BKE_rigidbody_do_simulation(struct Scene *scene, float ctime);
+void BKE_rigidbody_rebuild_world(const struct EvaluationContext *eval_ctx, struct Scene *scene, float ctime);
+void BKE_rigidbody_do_simulation(const struct EvaluationContext *eval_ctx, struct Scene *scene, float ctime);
/* -------------------- */
/* Depsgraph evaluation */
-struct EvaluationContext;
-
-void BKE_rigidbody_rebuild_sim(struct EvaluationContext *eval_ctx,
+void BKE_rigidbody_rebuild_sim(const struct EvaluationContext *eval_ctx,
struct Scene *scene);
-void BKE_rigidbody_eval_simulation(struct EvaluationContext *eval_ctx,
+void BKE_rigidbody_eval_simulation(const struct EvaluationContext *eval_ctx,
struct Scene *scene);
-void BKE_rigidbody_object_sync_transforms(struct EvaluationContext *eval_ctx,
+void BKE_rigidbody_object_sync_transforms(const struct EvaluationContext *eval_ctx,
struct Scene *scene,
struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_scene.h b/source/blender/blenkernel/BKE_scene.h
index 481aff3cfa6..bb435df136d 100644
--- a/source/blender/blenkernel/BKE_scene.h
+++ b/source/blender/blenkernel/BKE_scene.h
@@ -38,43 +38,55 @@ extern "C" {
#endif
struct AviCodecData;
-struct Base;
+struct Depsgraph;
struct EvaluationContext;
struct Main;
struct Object;
struct RenderData;
-struct SceneRenderLayer;
struct Scene;
+struct SceneCollection;
+struct ViewLayer;
struct UnitSettings;
-struct Main;
+struct ViewRender;
+struct WorkSpace;
-#define SCE_COPY_NEW 0
-#define SCE_COPY_EMPTY 1
-#define SCE_COPY_LINK_OB 2
-#define SCE_COPY_LINK_DATA 3
-#define SCE_COPY_FULL 4
+typedef enum eSceneCopyMethod {
+ SCE_COPY_NEW = 0,
+ SCE_COPY_EMPTY = 1,
+ SCE_COPY_LINK_OB = 2,
+ SCE_COPY_LINK_DATA = 3,
+ SCE_COPY_FULL = 4,
+} eSceneCopyMethod;
/* Use as the contents of a 'for' loop: for (SETLOOPER(...)) { ... */
#define SETLOOPER(_sce_basis, _sce_iter, _base) \
- _sce_iter = _sce_basis, _base = _setlooper_base_step(&_sce_iter, NULL); \
+ _sce_iter = _sce_basis, _base = _setlooper_base_step(&_sce_iter, BKE_view_layer_from_scene_get(_sce_basis), NULL); \
+ _base; \
+ _base = _setlooper_base_step(&_sce_iter, NULL, _base)
+
+#define SETLOOPER_VIEW_LAYER(_sce_basis, _view_layer, _sce_iter, _base) \
+ _sce_iter = _sce_basis, _base = _setlooper_base_step(&_sce_iter, _view_layer, NULL); \
_base; \
- _base = _setlooper_base_step(&_sce_iter, _base)
+ _base = _setlooper_base_step(&_sce_iter, NULL, _base)
-struct Base *_setlooper_base_step(struct Scene **sce_iter, struct Base *base);
+#define SETLOOPER_SET_ONLY(_sce_basis, _sce_iter, _base) \
+ _sce_iter = _sce_basis, _base = _setlooper_base_step(&_sce_iter, NULL, NULL); \
+ _base; \
+ _base = _setlooper_base_step(&_sce_iter, NULL, _base)
+
+struct Base *_setlooper_base_step(struct Scene **sce_iter, struct ViewLayer *view_layer, struct Base *base);
void free_avicodecdata(struct AviCodecData *acd);
+void BKE_scene_free_ex(struct Scene *sce, const bool do_id_user);
void BKE_scene_free(struct Scene *sce);
void BKE_scene_init(struct Scene *sce);
struct Scene *BKE_scene_add(struct Main *bmain, const char *name);
-/* base functions */
-struct Base *BKE_scene_base_find_by_name(struct Scene *scene, const char *name);
-struct Base *BKE_scene_base_find(struct Scene *scene, struct Object *ob);
-struct Base *BKE_scene_base_add(struct Scene *sce, struct Object *ob);
-void BKE_scene_base_unlink(struct Scene *sce, struct Base *base);
-void BKE_scene_base_deselect_all(struct Scene *sce);
-void BKE_scene_base_select(struct Scene *sce, struct Base *selbase);
+void BKE_scene_remove_rigidbody_object(struct Scene *scene, struct Object *ob);
+
+bool BKE_scene_object_find(struct Scene *scene, struct Object *ob);
+struct Object *BKE_scene_object_find_by_name(struct Scene *scene, const char *name);
/* Scene base iteration function.
* Define struct here, so no need to bother with alloc/free it.
@@ -87,11 +99,14 @@ typedef struct SceneBaseIter {
int phase;
} SceneBaseIter;
-int BKE_scene_base_iter_next(struct EvaluationContext *eval_ctx, struct SceneBaseIter *iter,
- struct Scene **scene, int val, struct Base **base, struct Object **ob);
+int BKE_scene_base_iter_next(
+ const struct EvaluationContext *eval_ctx, struct SceneBaseIter *iter,
+ struct Scene **scene, int val, struct Base **base, struct Object **ob);
-void BKE_scene_base_flag_to_objects(struct Scene *scene);
+void BKE_scene_base_flag_to_objects(struct ViewLayer *view_layer);
void BKE_scene_base_flag_from_objects(struct Scene *scene);
+void BKE_scene_object_base_flag_sync_from_base(struct Base *base);
+void BKE_scene_object_base_flag_sync_from_object(struct Base *base);
void BKE_scene_set_background(struct Main *bmain, struct Scene *sce);
struct Scene *BKE_scene_set_name(struct Main *bmain, const char *name);
@@ -102,7 +117,8 @@ void BKE_scene_groups_relink(struct Scene *sce);
void BKE_scene_make_local(struct Main *bmain, struct Scene *sce, const bool lib_local);
-struct Object *BKE_scene_camera_find(struct Scene *sc);
+struct Scene *BKE_scene_find_from_collection(const struct Main *bmain, const struct SceneCollection *scene_collection);
+
#ifdef DURIAN_CAMERA_SWITCH
struct Object *BKE_scene_camera_switch_find(struct Scene *scene); // DURIAN_CAMERA_SWITCH
#endif
@@ -119,12 +135,18 @@ float BKE_scene_frame_get_from_ctime(const struct Scene *scene, const float fram
void BKE_scene_frame_set(struct Scene *scene, double cfra);
/* ** Scene evaluation ** */
-void BKE_scene_update_tagged(struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *sce);
-void BKE_scene_update_for_newframe(struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *sce, unsigned int lay);
-void BKE_scene_update_for_newframe_ex(struct EvaluationContext *eval_ctx, struct Main *bmain, struct Scene *sce, unsigned int lay, bool do_invisible_flush);
-struct SceneRenderLayer *BKE_scene_add_render_layer(struct Scene *sce, const char *name);
-bool BKE_scene_remove_render_layer(struct Main *main, struct Scene *scene, struct SceneRenderLayer *srl);
+void BKE_scene_graph_update_tagged(struct EvaluationContext *eval_ctx,
+ struct Depsgraph *depsgraph,
+ struct Main *bmain,
+ struct Scene *scene,
+ struct ViewLayer *view_layer);
+
+void BKE_scene_graph_update_for_newframe(struct EvaluationContext *eval_ctx,
+ struct Depsgraph *depsgraph,
+ struct Main *bmain,
+ struct Scene *scene,
+ struct ViewLayer *view_layer);
struct SceneRenderView *BKE_scene_add_render_view(struct Scene *sce, const char *name);
bool BKE_scene_remove_render_view(struct Scene *scene, struct SceneRenderView *srv);
@@ -142,6 +164,7 @@ bool BKE_scene_use_spherical_stereo(struct Scene *scene);
bool BKE_scene_uses_blender_internal(const struct Scene *scene);
bool BKE_scene_uses_blender_game(const struct Scene *scene);
+bool BKE_scene_uses_blender_eevee(const struct Scene *scene);
void BKE_scene_disable_color_management(struct Scene *scene);
bool BKE_scene_check_color_management_enabled(const struct Scene *scene);
@@ -152,6 +175,22 @@ int BKE_render_num_threads(const struct RenderData *r);
int BKE_render_preview_pixel_size(const struct RenderData *r);
+/**********************************/
+
+struct ViewRender *BKE_viewrender_get(struct Scene *scene, struct WorkSpace *workspace);
+void BKE_viewrender_init(struct ViewRender *view_render);
+void BKE_viewrender_free(struct ViewRender *view_render);
+void BKE_viewrender_copy(struct ViewRender *view_render_dst, const struct ViewRender *view_render_src);
+bool BKE_viewrender_use_new_shading_nodes(const struct ViewRender *view_render);
+bool BKE_viewrender_use_shading_nodes_custom(const struct ViewRender *view_render);
+bool BKE_viewrender_use_world_space_shading(const struct ViewRender *view_render);
+bool BKE_viewrender_use_spherical_stereo(const struct ViewRender *view_render);
+bool BKE_viewrender_uses_blender_internal(const struct ViewRender *view_render);
+bool BKE_viewrender_uses_blender_game(const struct ViewRender *view_render);
+bool BKE_viewrender_uses_blender_eevee(const struct ViewRender *view_render);
+
+/**********************************/
+
double BKE_scene_unit_scale(const struct UnitSettings *unit, const int unit_type, double value);
/* multiview */
@@ -171,6 +210,13 @@ void BKE_scene_multiview_view_prefix_get(struct Scene *scene, const char
void BKE_scene_multiview_videos_dimensions_get(const struct RenderData *rd, const size_t width, const size_t height, size_t *r_width, size_t *r_height);
int BKE_scene_multiview_num_videos_get(const struct RenderData *rd);
+/* depsgraph */
+void BKE_scene_allocate_depsgraph_hash(struct Scene *scene);
+void BKE_scene_ensure_depsgraph_hash(struct Scene *scene);
+void BKE_scene_free_depsgraph_hash(struct Scene *scene);
+
+struct Depsgraph *BKE_scene_get_depsgraph(struct Scene *scene, struct ViewLayer *view_layer, bool allocate);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_screen.h b/source/blender/blenkernel/BKE_screen.h
index 14e978b23f2..6669f3103da 100644
--- a/source/blender/blenkernel/BKE_screen.h
+++ b/source/blender/blenkernel/BKE_screen.h
@@ -42,6 +42,7 @@ struct Panel;
struct Scene;
struct ScrArea;
struct SpaceType;
+struct TransformOrientation;
struct View3D;
struct bContext;
struct bContextDataResult;
@@ -49,10 +50,13 @@ struct bScreen;
struct uiLayout;
struct uiList;
struct wmKeyConfig;
+struct wmManipulatorMap;
struct wmNotifier;
struct wmWindow;
struct wmWindowManager;
+struct WorkSpace;
struct GPUFXSettings;
+struct wmMsgBus;
#include "BLI_compiler_attrs.h"
@@ -81,7 +85,9 @@ typedef struct SpaceType {
/* exit is called when the area is hidden or removed */
void (*exit)(struct wmWindowManager *, struct ScrArea *);
/* Listeners can react to bContext changes */
- void (*listener)(struct bScreen *sc, struct ScrArea *, struct wmNotifier *);
+ void (*listener)(struct bScreen *sc, struct ScrArea *,
+ struct wmNotifier *, struct Scene *scene,
+ struct WorkSpace *workspace);
/* refresh context, called after filereads, ED_area_tag_refresh() */
void (*refresh)(const struct bContext *, struct ScrArea *);
@@ -96,6 +102,9 @@ typedef struct SpaceType {
/* on startup, define dropboxes for spacetype+regions */
void (*dropboxes)(void);
+ /* initialize manipulator-map-types and manipulator-group-types with the region */
+ void (*manipulators)(void);
+
/* return context data */
int (*context)(const struct bContext *, const char *, struct bContextDataResult *);
@@ -129,8 +138,15 @@ typedef struct ARegionType {
/* draw entirely, view changes should be handled here */
void (*draw)(const struct bContext *, struct ARegion *);
/* contextual changes should be handled here */
- void (*listener)(struct bScreen *sc, struct ScrArea *, struct ARegion *, struct wmNotifier *);
-
+ void (*listener)(struct bScreen *, struct ScrArea *, struct ARegion *,
+ struct wmNotifier *, const struct Scene *scene);
+ /* Optional callback to generate subscriptions. */
+ void (*message_subscribe)(
+ const struct bContext *C,
+ struct WorkSpace *workspace, struct Scene *scene,
+ struct bScreen *sc, struct ScrArea *sa, struct ARegion *ar,
+ struct wmMsgBus *mbus);
+
void (*free)(struct ARegion *);
/* split region, copy data optionally */
@@ -284,6 +300,9 @@ void BKE_spacedata_id_unref(struct ScrArea *sa, struct SpaceLink *sl, struct ID
struct ARegion *BKE_area_region_copy(struct SpaceType *st, struct ARegion *ar);
void BKE_area_region_free(struct SpaceType *st, struct ARegion *ar);
void BKE_screen_area_free(struct ScrArea *sa);
+/* Manipulator-maps of a region need to be freed with the region. Uses callback to avoid low-level call. */
+void BKE_region_callback_free_manipulatormap_set(void (*callback)(struct wmManipulatorMap *));
+void BKE_region_callback_refresh_tag_manipulatormap_set(void (*callback)(struct wmManipulatorMap *));
struct ARegion *BKE_area_find_region_type(struct ScrArea *sa, int type);
struct ARegion *BKE_area_find_region_active_win(struct ScrArea *sa);
@@ -299,12 +318,16 @@ unsigned int BKE_screen_view3d_layer_active(
unsigned int BKE_screen_view3d_layer_all(const struct bScreen *sc) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
+void BKE_screen_manipulator_tag_refresh(struct bScreen *sc);
+
void BKE_screen_view3d_sync(struct View3D *v3d, struct Scene *scene);
-void BKE_screen_view3d_scene_sync(struct bScreen *sc);
-void BKE_screen_view3d_main_sync(ListBase *screen_lb, struct Scene *scene);
-void BKE_screen_view3d_twmode_remove(struct View3D *v3d, const int i);
-void BKE_screen_view3d_main_twmode_remove(ListBase *screen_lb, struct Scene *scene, const int i);
+void BKE_screen_view3d_scene_sync(struct bScreen *sc, struct Scene *scene);
+void BKE_screen_transform_orientation_remove(
+ const struct bScreen *screen, const struct WorkSpace *workspace,
+ const struct TransformOrientation *orientation) ATTR_NONNULL();
void BKE_screen_gpu_fx_validate(struct GPUFXSettings *fx_settings);
+bool BKE_screen_is_fullscreen_area(const struct bScreen *screen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
+bool BKE_screen_is_used(const struct bScreen *screen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
/* zoom factor conversion */
float BKE_screen_view3d_zoom_to_fac(float camzoom);
diff --git a/source/blender/blenkernel/BKE_sequencer.h b/source/blender/blenkernel/BKE_sequencer.h
index 6c9dc12b44f..2264167eca1 100644
--- a/source/blender/blenkernel/BKE_sequencer.h
+++ b/source/blender/blenkernel/BKE_sequencer.h
@@ -432,7 +432,8 @@ enum {
};
typedef struct ImBuf *(*SequencerDrawView)(
- struct Scene *scene, struct Object *camera, int width, int height,
+ const struct EvaluationContext *eval_ctx, struct Scene *scene,
+ struct ViewLayer *view_layer, struct Object *camera, int width, int height,
unsigned int flag, unsigned int draw_flags, int drawtype, int alpha_mode,
int samples, const char *viewname,
struct GPUFX *fx, struct GPUOffScreen *ofs, char err_out[256]);
diff --git a/source/blender/blenkernel/BKE_smoke.h b/source/blender/blenkernel/BKE_smoke.h
index 20366f00df6..64d70e8e209 100644
--- a/source/blender/blenkernel/BKE_smoke.h
+++ b/source/blender/blenkernel/BKE_smoke.h
@@ -35,7 +35,9 @@
typedef float (*bresenham_callback)(float *result, float *input, int res[3], int *pixel, float *tRay, float correct);
-struct DerivedMesh *smokeModifier_do(struct SmokeModifierData *smd, struct Scene *scene, struct Object *ob, struct DerivedMesh *dm);
+struct DerivedMesh *smokeModifier_do(struct SmokeModifierData *smd, const struct EvaluationContext *eval_ctx,
+ struct Scene *scene,
+ struct Object *ob, struct DerivedMesh *dm);
void smoke_reallocate_fluid(struct SmokeDomainSettings *sds, float dx, int res[3], int free_old);
void smoke_reallocate_highres_fluid(struct SmokeDomainSettings *sds, float dx, int res[3], int free_old);
diff --git a/source/blender/blenkernel/BKE_softbody.h b/source/blender/blenkernel/BKE_softbody.h
index 486fe8ed5a8..e2255bdb779 100644
--- a/source/blender/blenkernel/BKE_softbody.h
+++ b/source/blender/blenkernel/BKE_softbody.h
@@ -34,6 +34,7 @@
struct Object;
struct Scene;
struct SoftBody;
+struct EvaluationContext;
typedef struct BodyPoint {
float origS[3], origE[3], origT[3], pos[3], vec[3], force[3];
@@ -59,7 +60,8 @@ extern void sbFree(struct SoftBody *sb);
extern void sbFreeSimulation(struct SoftBody *sb);
/* do one simul step, reading and writing vertex locs from given array */
-extern void sbObjectStep(struct Scene *scene, struct Object *ob, float framnr, float (*vertexCos)[3], int numVerts);
+extern void sbObjectStep(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob,
+ float framnr, float (*vertexCos)[3], int numVerts);
/* makes totally fresh start situation, resets time */
extern void sbObjectToSoftbody(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_sound.h b/source/blender/blenkernel/BKE_sound.h
index 6f8274fabc8..98fb4f47339 100644
--- a/source/blender/blenkernel/BKE_sound.h
+++ b/source/blender/blenkernel/BKE_sound.h
@@ -35,8 +35,8 @@
#define SOUND_WAVE_SAMPLES_PER_SECOND 250
-#ifdef WITH_SYSTEM_AUDASPACE
-# include AUD_DEVICE_H
+#if defined(WITH_AUDASPACE)
+# include <AUD_Device.h>
#endif
struct bSound;
@@ -84,7 +84,7 @@ void BKE_sound_copy_data(struct Main *bmain, struct bSound *sound_dst, const str
void BKE_sound_make_local(struct Main *bmain, struct bSound *sound, const bool lib_local);
-#if defined(__AUD_C_API_H__) || defined(WITH_SYSTEM_AUDASPACE)
+#if defined(WITH_AUDASPACE)
AUD_Device *BKE_sound_mixdown(struct Scene *scene, AUD_DeviceSpecs specs, int start, float volume);
#endif
@@ -149,6 +149,4 @@ float BKE_sound_get_length(struct bSound *sound);
char **BKE_sound_get_device_names(void);
-bool BKE_sound_is_jack_supported(void);
-
#endif /* __BKE_SOUND_H__ */
diff --git a/source/blender/blenkernel/BKE_tracking.h b/source/blender/blenkernel/BKE_tracking.h
index 13302caa09d..5da87de1cc9 100644
--- a/source/blender/blenkernel/BKE_tracking.h
+++ b/source/blender/blenkernel/BKE_tracking.h
@@ -47,6 +47,7 @@ struct MovieDistortion;
struct Camera;
struct Object;
struct Scene;
+struct EvaluationContext;
struct rcti;
/* **** Common functions **** */
diff --git a/source/blender/blenkernel/BKE_workspace.h b/source/blender/blenkernel/BKE_workspace.h
new file mode 100644
index 00000000000..9f989f7ae8f
--- /dev/null
+++ b/source/blender/blenkernel/BKE_workspace.h
@@ -0,0 +1,155 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file BKE_workspace.h
+ * \ingroup bke
+ */
+
+#ifndef __BKE_WORKSPACE_H__
+#define __BKE_WORKSPACE_H__
+
+#include "BLI_compiler_attrs.h"
+
+struct bScreen;
+struct EvaluationContext;
+struct Main;
+struct Scene;
+struct TransformOrientation;
+struct ViewLayer;
+
+/**
+ * Plan is to store the object-mode per workspace, not per object anymore.
+ * However, there's quite some work to be done for that, so for now, there is just a basic
+ * implementation of an object <-> workspace object-mode syncing for testing, with some known
+ * problems. Main problem being that the modes can get out of sync when changing object selection.
+ * Would require a pile of temporary changes to always sync modes when changing selection. So just
+ * leaving this here for some testing until object-mode is really a workspace level setting.
+ */
+#define USE_WORKSPACE_MODE
+
+
+/* -------------------------------------------------------------------- */
+/* Create, delete, init */
+
+struct WorkSpace *BKE_workspace_add(struct Main *bmain, const char *name);
+void BKE_workspace_free(struct WorkSpace *workspace);
+void BKE_workspace_remove(struct Main *bmain, struct WorkSpace *workspace);
+
+struct WorkSpaceInstanceHook *BKE_workspace_instance_hook_create(const struct Main *bmain);
+void BKE_workspace_instance_hook_free(const struct Main *bmain, struct WorkSpaceInstanceHook *hook);
+
+struct WorkSpaceLayout *BKE_workspace_layout_add(
+ struct WorkSpace *workspace,
+ struct bScreen *screen,
+ const char *name) ATTR_NONNULL();
+void BKE_workspace_layout_remove(
+ struct Main *bmain,
+ struct WorkSpace *workspace, struct WorkSpaceLayout *layout) ATTR_NONNULL();
+
+void BKE_workspace_relations_free(
+ ListBase *relation_list);
+
+
+/* -------------------------------------------------------------------- */
+/* General Utils */
+
+void BKE_workspace_view_layer_remove_references(
+ const struct Main *bmain,
+ const struct ViewLayer *view_layer) ATTR_NONNULL();
+
+void BKE_workspace_transform_orientation_remove(
+ struct WorkSpace *workspace, struct TransformOrientation *orientation) ATTR_NONNULL();
+struct TransformOrientation *BKE_workspace_transform_orientation_find(
+ const struct WorkSpace *workspace, const int index) ATTR_NONNULL();
+int BKE_workspace_transform_orientation_get_index(
+ const struct WorkSpace *workspace, const struct TransformOrientation *orientation) ATTR_NONNULL();
+
+struct WorkSpaceLayout *BKE_workspace_layout_find(
+ const struct WorkSpace *workspace, const struct bScreen *screen) ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT;
+struct WorkSpaceLayout *BKE_workspace_layout_find_global(
+ const struct Main *bmain, const struct bScreen *screen,
+ struct WorkSpace **r_workspace) ATTR_NONNULL(1, 2);
+
+struct WorkSpaceLayout *BKE_workspace_layout_iter_circular(
+ const struct WorkSpace *workspace, struct WorkSpaceLayout *start,
+ bool (*callback)(const struct WorkSpaceLayout *layout, void *arg),
+ void *arg, const bool iter_backward);
+
+
+/* -------------------------------------------------------------------- */
+/* Getters/Setters */
+
+#define GETTER_ATTRS ATTR_NONNULL() ATTR_WARN_UNUSED_RESULT
+#define SETTER_ATTRS ATTR_NONNULL(1)
+
+struct WorkSpace *BKE_workspace_active_get(struct WorkSpaceInstanceHook *hook) GETTER_ATTRS;
+void BKE_workspace_active_set(struct WorkSpaceInstanceHook *hook, struct WorkSpace *workspace) SETTER_ATTRS;
+struct WorkSpaceLayout *BKE_workspace_active_layout_get(const struct WorkSpaceInstanceHook *hook) GETTER_ATTRS;
+void BKE_workspace_active_layout_set(struct WorkSpaceInstanceHook *hook, struct WorkSpaceLayout *layout) SETTER_ATTRS;
+struct bScreen *BKE_workspace_active_screen_get(const struct WorkSpaceInstanceHook *hook) GETTER_ATTRS;
+void BKE_workspace_active_screen_set(
+ struct WorkSpaceInstanceHook *hook, struct WorkSpace *workspace, struct bScreen *screen) SETTER_ATTRS;
+#ifdef USE_WORKSPACE_MODE
+enum eObjectMode BKE_workspace_object_mode_get(
+ const struct WorkSpace *workspace,
+ const struct Scene *scene) GETTER_ATTRS;
+void BKE_workspace_object_mode_set(
+ struct WorkSpace *workspace,
+ struct Scene *scene,
+ const enum eObjectMode mode) SETTER_ATTRS;
+#endif
+struct Base *BKE_workspace_active_base_get(const struct WorkSpace *workspace, const struct Scene *scene);
+struct ListBase *BKE_workspace_transform_orientations_get(struct WorkSpace *workspace) GETTER_ATTRS;
+struct ViewLayer *BKE_workspace_view_layer_get(
+ const struct WorkSpace *workspace,
+ const struct Scene *scene) GETTER_ATTRS;
+void BKE_workspace_view_layer_set(
+ struct WorkSpace *workspace,
+ struct ViewLayer *layer,
+ struct Scene *scene) SETTER_ATTRS;
+struct ListBase *BKE_workspace_layouts_get(struct WorkSpace *workspace) GETTER_ATTRS;
+
+const char *BKE_workspace_layout_name_get(const struct WorkSpaceLayout *layout) GETTER_ATTRS;
+void BKE_workspace_layout_name_set(
+ struct WorkSpace *workspace, struct WorkSpaceLayout *layout, const char *new_name) ATTR_NONNULL();
+struct bScreen *BKE_workspace_layout_screen_get(const struct WorkSpaceLayout *layout) GETTER_ATTRS;
+void BKE_workspace_layout_screen_set(struct WorkSpaceLayout *layout, struct bScreen *screen) SETTER_ATTRS;
+
+struct WorkSpaceLayout *BKE_workspace_hook_layout_for_workspace_get(
+ const struct WorkSpaceInstanceHook *hook, const struct WorkSpace *workspace) GETTER_ATTRS;
+void BKE_workspace_hook_layout_for_workspace_set(
+ struct WorkSpaceInstanceHook *hook, struct WorkSpace *workspace, struct WorkSpaceLayout *layout) ATTR_NONNULL();
+
+struct ViewRender *BKE_workspace_view_render_get(struct WorkSpace *workspace) GETTER_ATTRS;
+
+/* flags */
+bool BKE_workspace_use_scene_settings_get(const struct WorkSpace *workspace) GETTER_ATTRS;
+void BKE_workspace_use_scene_settings_set(struct WorkSpace *workspace, bool value) SETTER_ATTRS;
+
+/* Update / evaluate */
+void BKE_workspace_update_tagged(struct EvaluationContext *eval_ctx,
+ struct Main *bmain,
+ struct WorkSpace *workspace,
+ struct Scene *scene);
+
+#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 dfa367afeb2..b69c14535c6 100644
--- a/source/blender/blenkernel/BKE_world.h
+++ b/source/blender/blenkernel/BKE_world.h
@@ -44,5 +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);
+/* Evaluation. */
+
+struct EvaluationContext;
+
+void BKE_world_eval(const struct EvaluationContext *eval_ctx, struct World *world);
+
#endif
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 3fc2c3f8eb0..279068c440e 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -30,6 +30,7 @@ set(INC
../blenloader
../blentranslation
../depsgraph
+ ../draw
../gpu
../ikplugin
../imbuf
@@ -86,6 +87,7 @@ set(SRC
intern/camera.c
intern/cdderivedmesh.c
intern/cloth.c
+ intern/collection.c
intern/collision.c
intern/colorband.c
intern/colortools.c
@@ -98,12 +100,12 @@ set(SRC
intern/customdata_file.c
intern/data_transfer.c
intern/deform.c
- intern/depsgraph.c
intern/displist.c
intern/dynamicpaint.c
intern/editderivedmesh.c
intern/editmesh.c
intern/editmesh_bvh.c
+ intern/editmesh_tangent.c
intern/effect.c
intern/fcurve.c
intern/fluidsim.c
@@ -123,6 +125,7 @@ set(SRC
intern/lattice.c
intern/library.c
intern/library_idmap.c
+ intern/library_override.c
intern/library_query.c
intern/library_remap.c
intern/linestyle.c
@@ -136,6 +139,7 @@ set(SRC
intern/mesh_evaluate.c
intern/mesh_mapping.c
intern/mesh_remap.c
+ intern/mesh_tangent.c
intern/mesh_validate.c
intern/modifier.c
intern/modifiers_bmesh.c
@@ -144,6 +148,7 @@ set(SRC
intern/nla.c
intern/node.c
intern/object.c
+ intern/object_facemap.c
intern/object_deform.c
intern/object_dupli.c
intern/object_update.c
@@ -159,6 +164,8 @@ set(SRC
intern/pbvh_bmesh.c
intern/pointcache.c
intern/property.c
+ intern/layer.c
+ intern/lightprobe.c
intern/report.c
intern/rigidbody.c
intern/sca.c
@@ -187,6 +194,7 @@ set(SRC
intern/tracking_stabilize.c
intern/tracking_util.c
intern/unit.c
+ intern/workspace.c
intern/world.c
intern/writeavi.c
intern/writeframeserver.c
@@ -216,6 +224,7 @@ set(SRC
BKE_ccg.h
BKE_cdderivedmesh.h
BKE_cloth.h
+ BKE_collection.h
BKE_collision.h
BKE_colorband.h
BKE_colortools.h
@@ -227,11 +236,11 @@ set(SRC
BKE_customdata_file.h
BKE_data_transfer.h
BKE_deform.h
- BKE_depsgraph.h
BKE_displist.h
BKE_dynamicpaint.h
BKE_editmesh.h
BKE_editmesh_bvh.h
+ BKE_editmesh_tangent.h
BKE_effect.h
BKE_fcurve.h
BKE_fluidsim.h
@@ -250,6 +259,7 @@ set(SRC
BKE_lattice.h
BKE_library.h
BKE_library_idmap.h
+ BKE_library_override.h
BKE_library_query.h
BKE_library_remap.h
BKE_linestyle.h
@@ -261,12 +271,14 @@ set(SRC
BKE_mesh.h
BKE_mesh_mapping.h
BKE_mesh_remap.h
+ BKE_mesh_tangent.h
BKE_modifier.h
BKE_movieclip.h
BKE_multires.h
BKE_nla.h
BKE_node.h
BKE_object.h
+ BKE_object_facemap.h
BKE_object_deform.h
BKE_ocean.h
BKE_outliner_treehash.h
@@ -276,6 +288,8 @@ set(SRC
BKE_pbvh.h
BKE_pointcache.h
BKE_property.h
+ BKE_layer.h
+ BKE_lightprobe.h
BKE_report.h
BKE_rigidbody.h
BKE_sca.h
@@ -294,11 +308,11 @@ set(SRC
BKE_texture.h
BKE_tracking.h
BKE_unit.h
+ BKE_workspace.h
BKE_world.h
BKE_writeavi.h
BKE_writeframeserver.h
- depsgraph_private.h
nla_private.h
tracking_private.h
intern/CCGSubSurf.h
@@ -324,7 +338,7 @@ if(WIN32)
endif()
if(WITH_AUDASPACE)
- add_definitions(${AUDASPACE_DEFINITIONS})
+ add_definitions(-DWITH_AUDASPACE)
list(APPEND INC_SYS
${AUDASPACE_C_INCLUDE_DIRS}
@@ -412,6 +426,10 @@ if(WITH_PYTHON)
)
add_definitions(-DWITH_PYTHON)
+ if(WITH_PYTHON_SAFETY)
+ add_definitions(-DWITH_PYTHON_SAFETY)
+ endif()
+
if(WITH_PYTHON_SECURITY)
add_definitions(-DWITH_PYTHON_SECURITY)
endif()
@@ -528,8 +546,4 @@ endif()
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX")
#endif()
-if(WITH_LEGACY_DEPSGRAPH)
- add_definitions(-DWITH_LEGACY_DEPSGRAPH)
-endif()
-
blender_add_lib(bf_blenkernel "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/blenkernel/depsgraph_private.h b/source/blender/blenkernel/depsgraph_private.h
deleted file mode 100644
index 69ca75836d9..00000000000
--- a/source/blender/blenkernel/depsgraph_private.h
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2004 Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/blenkernel/depsgraph_private.h
- * \ingroup bke
- */
-
-#ifndef __DEPSGRAPH_PRIVATE_H__
-#define __DEPSGRAPH_PRIVATE_H__
-
-#include "BKE_depsgraph.h"
-#include "DNA_constraint_types.h"
-#include "BKE_constraint.h"
-
-struct Scene;
-struct Group;
-struct EffectorWeights;
-struct ModifierData;
-
-/* **** DAG relation types *** */
-
-/* scene link to object */
-#define DAG_RL_SCENE (1 << 0)
-/* object link to data */
-#define DAG_RL_DATA (1 << 1)
-
-/* object changes object (parent, track, constraints) */
-#define DAG_RL_OB_OB (1 << 2)
-/* object changes obdata (hooks, constraints) */
-#define DAG_RL_OB_DATA (1 << 3)
-/* data changes object (vertex parent) */
-#define DAG_RL_DATA_OB (1 << 4)
-/* data changes data (deformers) */
-#define DAG_RL_DATA_DATA (1 << 5)
-
-#define DAG_NO_RELATION (1 << 6)
-
-#define DAG_RL_ALL_BUT_DATA (DAG_RL_SCENE | DAG_RL_OB_OB | DAG_RL_OB_DATA | DAG_RL_DATA_OB | DAG_RL_DATA_DATA)
-#define DAG_RL_ALL (DAG_RL_ALL_BUT_DATA | DAG_RL_DATA)
-
-
-#define DAGQUEUEALLOC 50
-
-enum {
- DAG_WHITE = 0,
- DAG_GRAY = 1,
- DAG_BLACK = 2
-};
-
-typedef struct DagAdjList {
- struct DagNode *node;
- short type;
- int count; /* number of identical arcs */
- unsigned int lay; // for flushing redraw/rebuild events
- const char *name;
- struct DagAdjList *next;
-} DagAdjList;
-
-
-typedef struct DagNode {
- int color;
- short type;
- float x, y, k;
- void *ob;
- void *first_ancestor;
- int ancestor_count;
- unsigned int lay; /* accumulated layers of its relations + itself */
- unsigned int scelay; /* layers due to being in scene */
- uint64_t customdata_mask; /* customdata mask */
- int lasttime; /* if lasttime != DagForest->time, this node was not evaluated yet for flushing */
- int BFS_dist; /* BFS distance */
- int DFS_dist; /* DFS distance */
- int DFS_dvtm; /* DFS discovery time */
- int DFS_fntm; /* DFS Finishing time */
- struct DagAdjList *child;
- struct DagAdjList *parent;
- struct DagNode *next;
-
- /* Threaded evaluation routines */
- uint32_t num_pending_parents; /* number of parents which are not updated yet
- * this node has got.
- * Used by threaded update for faster detect whether node could be
- * updated aready.
- */
- bool scheduled;
-
- /* Runtime flags mainly used to determine which extra data is to be evaluated
- * during object_handle_update(). Such an extra data is what depends on the
- * DAG topology, meaning this flags indicates the data evaluation of which
- * depends on the node dependencies.
- */
- short eval_flags;
-} DagNode;
-
-typedef struct DagNodeQueueElem {
- struct DagNode *node;
- struct DagNodeQueueElem *next;
-} DagNodeQueueElem;
-
-typedef struct DagNodeQueue {
- DagNodeQueueElem *first;
- DagNodeQueueElem *last;
- int count;
- int maxlevel;
- struct DagNodeQueue *freenodes;
-} DagNodeQueue;
-
-/* forest as we may have more than one DAG unconnected */
-typedef struct DagForest {
- ListBase DagNode;
- struct GHash *nodeHash;
- int numNodes;
- bool is_acyclic;
- int time; /* for flushing/tagging, compare with node->lasttime */
- bool ugly_hack_sorry; /* prevent type check */
- bool need_update;
-} DagForest;
-
-// queue operations
-DagNodeQueue *queue_create(int slots);
-void queue_raz(DagNodeQueue *queue);
-void push_queue(DagNodeQueue *queue, DagNode *node);
-void push_stack(DagNodeQueue *queue, DagNode *node);
-DagNode *pop_queue(DagNodeQueue *queue);
-DagNode *get_top_node_queue(DagNodeQueue *queue);
-void queue_delete(DagNodeQueue *queue);
-
-// Dag management
-DagForest *dag_init(void);
-DagForest *build_dag(struct Main *bmain, struct Scene *sce, short mask);
-void free_forest(struct DagForest *Dag);
-DagNode *dag_find_node(DagForest *forest, void *fob);
-DagNode *dag_add_node(DagForest *forest, void *fob);
-DagNode *dag_get_node(DagForest *forest, void *fob);
-DagNode *dag_get_sub_node(DagForest *forest, void *fob);
-void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, const char *name);
-
-typedef bool (*DagCollobjFilterFunction)(struct Object *obj, struct ModifierData *md);
-
-void dag_add_collision_relations(DagForest *dag, struct Scene *scene, Object *ob, DagNode *node, struct Group *group, int layer, unsigned int modifier_type, DagCollobjFilterFunction fn, bool dupli, const char *name);
-void dag_add_forcefield_relations(DagForest *dag, struct Scene *scene, Object *ob, DagNode *node, struct EffectorWeights *eff, bool add_absorption, int skip_forcefield, const char *name);
-
-void graph_print_queue(DagNodeQueue *nqueue);
-void graph_print_queue_dist(DagNodeQueue *nqueue);
-void graph_print_adj_list(DagForest *dag);
-
-#endif /* __DEPSGRAPH_PRIVATE_H__ */
diff --git a/source/blender/blenkernel/intern/CCGSubSurf.c b/source/blender/blenkernel/intern/CCGSubSurf.c
index 792e9195f12..68bcfa878ac 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf.c
@@ -42,7 +42,7 @@
# include "opensubdiv_converter_capi.h"
#endif
-#include "GL/glew.h"
+#include "GPU_glew.h"
/***/
diff --git a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
index f568bb94ac5..c26112d3724 100644
--- a/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
+++ b/source/blender/blenkernel/intern/CCGSubSurf_opensubdiv.c
@@ -43,7 +43,7 @@
#include "opensubdiv_capi.h"
#include "opensubdiv_converter_capi.h"
-#include "GL/glew.h"
+#include "GPU_glew.h"
#include "GPU_extensions.h"
#define OSD_LOG if (false) printf
@@ -995,7 +995,7 @@ void ccgSubSurf__sync_subdivUvs(CCGSubSurf *ss, bool subdiv_uvs)
void BKE_subsurf_osd_init(void)
{
- openSubdiv_init(GPU_legacy_support());
+ openSubdiv_init();
BLI_spin_init(&delete_spin);
}
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index 48edf55d76e..cfeca50a751 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"
@@ -76,11 +78,12 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm);
#include "BLI_sys_types.h" /* for intptr_t support */
#include "GPU_buffers.h"
-#include "GPU_glew.h"
#include "GPU_shader.h"
+#include "GPU_immediate.h"
#ifdef WITH_OPENSUBDIV
-# include "BKE_depsgraph.h"
+# include "DEG_depsgraph.h"
+# include "DEG_depsgraph_query.h"
# include "DNA_userdef_types.h"
#endif
@@ -347,7 +350,7 @@ void DM_init(
dm->numPolyData = numPolys;
DM_init_funcs(dm);
-
+
dm->needsFree = 1;
dm->auto_bump_scale = -1.0f;
dm->dirty = 0;
@@ -407,6 +410,7 @@ int DM_release(DerivedMesh *dm)
if (dm->needsFree) {
bvhcache_free(&dm->bvhCache);
GPU_drawobject_free(dm);
+
CustomData_free(&dm->vertData, dm->numVertData);
CustomData_free(&dm->edgeData, dm->numEdgeData);
CustomData_free(&dm->faceData, dm->numTessFaceData);
@@ -552,7 +556,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 +568,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 +600,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 +618,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 +634,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 +664,7 @@ void DM_generate_tangent_tessface_data(DerivedMesh *dm, bool generate)
}
if (loopindex)
MEM_freeN(loopindex);
- BLI_assert(CustomData_from_bmeshpoly_test(fdata, pdata, ldata, true));
+ BLI_assert(CustomData_from_bmeshpoly_test(fdata, ldata, true));
}
if (G.debug & G_DEBUG)
@@ -1147,7 +1149,7 @@ DerivedMesh *mesh_create_derived(Mesh *me, float (*vertCos)[3])
}
DerivedMesh *mesh_create_derived_for_modifier(
- Scene *scene, Object *ob,
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob,
ModifierData *md, int build_shapekey_layers)
{
Mesh *me = ob->data;
@@ -1173,7 +1175,7 @@ DerivedMesh *mesh_create_derived_for_modifier(
int numVerts;
float (*deformedVerts)[3] = BKE_mesh_vertexCos_get(me, &numVerts);
- modwrap_deformVerts(md, ob, NULL, deformedVerts, numVerts, 0);
+ modwrap_deformVerts(md, eval_ctx, ob, NULL, deformedVerts, numVerts, 0);
dm = mesh_create_derived(me, deformedVerts);
if (build_shapekey_layers)
@@ -1187,7 +1189,7 @@ DerivedMesh *mesh_create_derived_for_modifier(
if (build_shapekey_layers)
add_shapekey_layers(tdm, me, ob);
- dm = modwrap_applyModifier(md, ob, tdm, 0);
+ dm = modwrap_applyModifier(md, eval_ctx, ob, tdm, 0);
ASSERT_IS_VALID_DM(dm);
if (tdm != dm) tdm->release(tdm);
@@ -1752,7 +1754,7 @@ static void dm_ensure_display_normals(DerivedMesh *dm)
* - apply deform modifiers and input vertexco
*/
static void mesh_calc_modifiers(
- Scene *scene, Object *ob, float (*inputVertexCos)[3],
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float (*inputVertexCos)[3],
const bool useRenderParams, int useDeform,
const bool need_mapping, CustomDataMask dataMask,
const int index, const bool useCache, const bool build_shapekey_layers,
@@ -1863,7 +1865,7 @@ static void mesh_calc_modifiers(
if (!deformedVerts)
deformedVerts = BKE_mesh_vertexCos_get(me, &numVerts);
- modwrap_deformVerts(md, ob, NULL, deformedVerts, numVerts, deform_app_flags);
+ modwrap_deformVerts(md, eval_ctx, ob, NULL, deformedVerts, numVerts, deform_app_flags);
}
else {
break;
@@ -2004,7 +2006,7 @@ static void mesh_calc_modifiers(
}
}
- modwrap_deformVerts(md, ob, dm, deformedVerts, numVerts, deform_app_flags);
+ modwrap_deformVerts(md, eval_ctx, ob, dm, deformedVerts, numVerts, deform_app_flags);
}
else {
DerivedMesh *ndm;
@@ -2079,7 +2081,7 @@ static void mesh_calc_modifiers(
}
}
- ndm = modwrap_applyModifier(md, ob, dm, app_flags);
+ ndm = modwrap_applyModifier(md, eval_ctx, ob, dm, app_flags);
ASSERT_IS_VALID_DM(ndm);
if (ndm) {
@@ -2106,7 +2108,7 @@ static void mesh_calc_modifiers(
(mti->requiredDataMask ?
mti->requiredDataMask(ob, md) : 0));
- ndm = modwrap_applyModifier(md, ob, orcodm, (app_flags & ~MOD_APPLY_USECACHE) | MOD_APPLY_ORCO);
+ ndm = modwrap_applyModifier(md, eval_ctx, ob, orcodm, (app_flags & ~MOD_APPLY_USECACHE) | MOD_APPLY_ORCO);
ASSERT_IS_VALID_DM(ndm);
if (ndm) {
@@ -2124,7 +2126,7 @@ static void mesh_calc_modifiers(
nextmask &= ~CD_MASK_CLOTH_ORCO;
DM_set_only_copy(clothorcodm, nextmask | CD_MASK_ORIGINDEX);
- ndm = modwrap_applyModifier(md, ob, clothorcodm, (app_flags & ~MOD_APPLY_USECACHE) | MOD_APPLY_ORCO);
+ ndm = modwrap_applyModifier(md, eval_ctx, ob, clothorcodm, (app_flags & ~MOD_APPLY_USECACHE) | MOD_APPLY_ORCO);
ASSERT_IS_VALID_DM(ndm);
if (ndm) {
@@ -2307,8 +2309,8 @@ bool editbmesh_modifier_is_enabled(Scene *scene, ModifierData *md, DerivedMesh *
}
static void editbmesh_calc_modifiers(
- Scene *scene, Object *ob, BMEditMesh *em,
- CustomDataMask dataMask,
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob,
+ BMEditMesh *em, CustomDataMask dataMask,
/* return args */
DerivedMesh **r_cage, DerivedMesh **r_final)
{
@@ -2395,9 +2397,9 @@ static void editbmesh_calc_modifiers(
}
if (mti->deformVertsEM)
- modwrap_deformVertsEM(md, ob, em, dm, deformedVerts, numVerts);
+ modwrap_deformVertsEM(md, eval_ctx, ob, em, dm, deformedVerts, numVerts);
else
- modwrap_deformVerts(md, ob, dm, deformedVerts, numVerts, 0);
+ modwrap_deformVerts(md, eval_ctx, ob, dm, deformedVerts, numVerts, 0);
}
else {
DerivedMesh *ndm;
@@ -2442,10 +2444,10 @@ static void editbmesh_calc_modifiers(
DM_set_only_copy(orcodm, mask | CD_MASK_ORIGINDEX);
if (mti->applyModifierEM) {
- ndm = modwrap_applyModifierEM(md, ob, em, orcodm, MOD_APPLY_ORCO);
+ ndm = modwrap_applyModifierEM(md, eval_ctx, ob, em, orcodm, MOD_APPLY_ORCO);
}
else {
- ndm = modwrap_applyModifier(md, ob, orcodm, MOD_APPLY_ORCO);
+ ndm = modwrap_applyModifier(md, eval_ctx, ob, orcodm, MOD_APPLY_ORCO);
}
ASSERT_IS_VALID_DM(ndm);
@@ -2470,9 +2472,9 @@ static void editbmesh_calc_modifiers(
}
if (mti->applyModifierEM)
- ndm = modwrap_applyModifierEM(md, ob, em, dm, MOD_APPLY_USECACHE | MOD_APPLY_ALLOW_GPU);
+ ndm = modwrap_applyModifierEM(md, eval_ctx, ob, em, dm, MOD_APPLY_USECACHE | MOD_APPLY_ALLOW_GPU);
else
- ndm = modwrap_applyModifier(md, ob, dm, MOD_APPLY_USECACHE | MOD_APPLY_ALLOW_GPU);
+ ndm = modwrap_applyModifier(md, eval_ctx, ob, dm, MOD_APPLY_USECACHE | MOD_APPLY_ALLOW_GPU);
ASSERT_IS_VALID_DM(ndm);
if (ndm) {
@@ -2608,7 +2610,8 @@ static void editbmesh_calc_modifiers(
* we'll be using GPU backend of OpenSubdiv. This is so
* playback performance is kept as high as possible.
*/
-static bool calc_modifiers_skip_orco(Scene *scene,
+static bool calc_modifiers_skip_orco(const EvaluationContext *eval_ctx,
+ Scene *scene,
Object *ob,
bool use_render_params)
{
@@ -2624,7 +2627,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(eval_ctx->depsgraph, &ob->id) & DAG_EVAL_NEED_CPU) != 0) {
return false;
}
SubsurfModifierData *smd = (SubsurfModifierData *)last_md;
@@ -2636,7 +2639,7 @@ static bool calc_modifiers_skip_orco(Scene *scene,
#endif
static void mesh_build_data(
- Scene *scene, Object *ob, CustomDataMask dataMask,
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, CustomDataMask dataMask,
const bool build_shapekey_layers, const bool need_mapping)
{
BLI_assert(ob->type == OB_MESH);
@@ -2645,13 +2648,13 @@ static void mesh_build_data(
BKE_object_sculpt_modifiers_changed(ob);
#ifdef WITH_OPENSUBDIV
- if (calc_modifiers_skip_orco(scene, ob, false)) {
+ if (calc_modifiers_skip_orco(eval_ctx, scene, ob, false)) {
dataMask &= ~(CD_MASK_ORCO | CD_MASK_PREVIEW_MCOL);
}
#endif
mesh_calc_modifiers(
- scene, ob, NULL, false, 1, need_mapping, dataMask, -1, true, build_shapekey_layers,
+ eval_ctx, scene, ob, NULL, false, 1, need_mapping, dataMask, -1, true, build_shapekey_layers,
true,
&ob->derivedDeform, &ob->derivedFinal);
@@ -2666,13 +2669,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(eval_ctx, scene, scene->toolsettings->sculpt, ob, false, false);
}
BLI_assert(!(ob->derivedFinal->dirty & DM_DIRTY_NORMALS));
}
-static void editbmesh_build_data(Scene *scene, Object *obedit, BMEditMesh *em, CustomDataMask dataMask)
+static void editbmesh_build_data(
+ const struct EvaluationContext *eval_ctx, Scene *scene,
+ Object *obedit, BMEditMesh *em, CustomDataMask dataMask)
{
BKE_object_free_derived_caches(obedit);
BKE_object_sculpt_modifiers_changed(obedit);
@@ -2680,13 +2685,13 @@ static void editbmesh_build_data(Scene *scene, Object *obedit, BMEditMesh *em, C
BKE_editmesh_free_derivedmesh(em);
#ifdef WITH_OPENSUBDIV
- if (calc_modifiers_skip_orco(scene, obedit, false)) {
+ if (calc_modifiers_skip_orco(eval_ctx, scene, obedit, false)) {
dataMask &= ~(CD_MASK_ORCO | CD_MASK_PREVIEW_MCOL);
}
#endif
editbmesh_calc_modifiers(
- scene, obedit, em, dataMask,
+ eval_ctx, scene, obedit, em, dataMask,
&em->derivedCage, &em->derivedFinal);
DM_set_object_boundbox(obedit, em->derivedFinal);
@@ -2700,7 +2705,9 @@ static void editbmesh_build_data(Scene *scene, Object *obedit, BMEditMesh *em, C
static CustomDataMask object_get_datamask(const Scene *scene, Object *ob, bool *r_need_mapping)
{
- Object *actob = scene->basact ? scene->basact->object : NULL;
+ /* TODO(sergey): Avoid this linear list lookup. */
+ ViewLayer *view_layer = BKE_view_layer_context_active_PLACEHOLDER(scene);
+ Object *actob = view_layer->basact ? view_layer->basact->object : NULL;
CustomDataMask mask = ob->customdata_mask;
if (r_need_mapping) {
@@ -2737,23 +2744,24 @@ static CustomDataMask object_get_datamask(const Scene *scene, Object *ob, bool *
}
void makeDerivedMesh(
- Scene *scene, Object *ob, BMEditMesh *em,
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, BMEditMesh *em,
CustomDataMask dataMask, const bool build_shapekey_layers)
{
bool need_mapping;
dataMask |= object_get_datamask(scene, ob, &need_mapping);
if (em) {
- editbmesh_build_data(scene, ob, em, dataMask);
+ editbmesh_build_data(eval_ctx, scene, ob, em, dataMask);
}
else {
- mesh_build_data(scene, ob, dataMask, build_shapekey_layers, need_mapping);
+ mesh_build_data(eval_ctx, scene, ob, dataMask, build_shapekey_layers, need_mapping);
}
}
/***/
-DerivedMesh *mesh_get_derived_final(Scene *scene, Object *ob, CustomDataMask dataMask)
+DerivedMesh *mesh_get_derived_final(
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, CustomDataMask dataMask)
{
/* if there's no derived mesh or the last data mask used doesn't include
* the data we need, rebuild the derived mesh
@@ -2765,14 +2773,14 @@ DerivedMesh *mesh_get_derived_final(Scene *scene, Object *ob, CustomDataMask dat
((dataMask & ob->lastDataMask) != dataMask) ||
(need_mapping != ob->lastNeedMapping))
{
- mesh_build_data(scene, ob, dataMask, false, need_mapping);
+ mesh_build_data(eval_ctx, scene, ob, dataMask, false, need_mapping);
}
if (ob->derivedFinal) { BLI_assert(!(ob->derivedFinal->dirty & DM_DIRTY_NORMALS)); }
return ob->derivedFinal;
}
-DerivedMesh *mesh_get_derived_deform(Scene *scene, Object *ob, CustomDataMask dataMask)
+DerivedMesh *mesh_get_derived_deform(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, CustomDataMask dataMask)
{
/* if there's no derived mesh or the last data mask used doesn't include
* the data we need, rebuild the derived mesh
@@ -2785,37 +2793,37 @@ DerivedMesh *mesh_get_derived_deform(Scene *scene, Object *ob, CustomDataMask da
((dataMask & ob->lastDataMask) != dataMask) ||
(need_mapping != ob->lastNeedMapping))
{
- mesh_build_data(scene, ob, dataMask, false, need_mapping);
+ mesh_build_data(eval_ctx, scene, ob, dataMask, false, need_mapping);
}
return ob->derivedDeform;
}
-DerivedMesh *mesh_create_derived_render(Scene *scene, Object *ob, CustomDataMask dataMask)
+DerivedMesh *mesh_create_derived_render(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, CustomDataMask dataMask)
{
DerivedMesh *final;
mesh_calc_modifiers(
- scene, ob, NULL, true, 1, false, dataMask, -1, false, false, false,
+ eval_ctx, scene, ob, NULL, true, 1, false, dataMask, -1, false, false, false,
NULL, &final);
return final;
}
-DerivedMesh *mesh_create_derived_index_render(Scene *scene, Object *ob, CustomDataMask dataMask, int index)
+DerivedMesh *mesh_create_derived_index_render(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, CustomDataMask dataMask, int index)
{
DerivedMesh *final;
mesh_calc_modifiers(
- scene, ob, NULL, true, 1, false, dataMask, index, false, false, false,
+ eval_ctx, scene, ob, NULL, true, 1, false, dataMask, index, false, false, false,
NULL, &final);
return final;
}
DerivedMesh *mesh_create_derived_view(
- Scene *scene, Object *ob,
- CustomDataMask dataMask)
+ const struct EvaluationContext *eval_ctx, Scene *scene,
+ Object *ob, CustomDataMask dataMask)
{
DerivedMesh *final;
@@ -2826,7 +2834,7 @@ DerivedMesh *mesh_create_derived_view(
ob->transflag |= OB_NO_PSYS_UPDATE;
mesh_calc_modifiers(
- scene, ob, NULL, false, 1, false, dataMask, -1, false, false, false,
+ eval_ctx, scene, ob, NULL, false, 1, false, dataMask, -1, false, false, false,
NULL, &final);
ob->transflag &= ~OB_NO_PSYS_UPDATE;
@@ -2835,53 +2843,53 @@ DerivedMesh *mesh_create_derived_view(
}
DerivedMesh *mesh_create_derived_no_deform(
- Scene *scene, Object *ob, float (*vertCos)[3],
- CustomDataMask dataMask)
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob,
+ float (*vertCos)[3], CustomDataMask dataMask)
{
DerivedMesh *final;
mesh_calc_modifiers(
- scene, ob, vertCos, false, 0, false, dataMask, -1, false, false, false,
+ eval_ctx, scene, ob, vertCos, false, 0, false, dataMask, -1, false, false, false,
NULL, &final);
return final;
}
DerivedMesh *mesh_create_derived_no_virtual(
- Scene *scene, Object *ob, float (*vertCos)[3],
- CustomDataMask dataMask)
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob,
+ float (*vertCos)[3], CustomDataMask dataMask)
{
DerivedMesh *final;
mesh_calc_modifiers(
- scene, ob, vertCos, false, -1, false, dataMask, -1, false, false, false,
+ eval_ctx, scene, ob, vertCos, false, -1, false, dataMask, -1, false, false, false,
NULL, &final);
return final;
}
DerivedMesh *mesh_create_derived_physics(
- Scene *scene, Object *ob, float (*vertCos)[3],
- CustomDataMask dataMask)
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob,
+ float (*vertCos)[3], CustomDataMask dataMask)
{
DerivedMesh *final;
mesh_calc_modifiers(
- scene, ob, vertCos, false, -1, true, dataMask, -1, false, false, false,
+ eval_ctx, scene, ob, vertCos, false, -1, true, dataMask, -1, false, false, false,
NULL, &final);
return final;
}
DerivedMesh *mesh_create_derived_no_deform_render(
- Scene *scene, Object *ob,
- float (*vertCos)[3],
+ const struct EvaluationContext *eval_ctx, Scene *scene,
+ Object *ob, float (*vertCos)[3],
CustomDataMask dataMask)
{
DerivedMesh *final;
mesh_calc_modifiers(
- scene, ob, vertCos, true, 0, false, dataMask, -1, false, false, false,
+ eval_ctx, scene, ob, vertCos, true, 0, false, dataMask, -1, false, false, false,
NULL, &final);
return final;
@@ -2890,7 +2898,7 @@ DerivedMesh *mesh_create_derived_no_deform_render(
/***/
DerivedMesh *editbmesh_get_derived_cage_and_final(
- Scene *scene, Object *obedit, BMEditMesh *em,
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *obedit, BMEditMesh *em,
CustomDataMask dataMask,
/* return args */
DerivedMesh **r_final)
@@ -2903,7 +2911,7 @@ DerivedMesh *editbmesh_get_derived_cage_and_final(
if (!em->derivedCage ||
(em->lastDataMask & dataMask) != dataMask)
{
- editbmesh_build_data(scene, obedit, em, dataMask);
+ editbmesh_build_data(eval_ctx, scene, obedit, em, dataMask);
}
*r_final = em->derivedFinal;
@@ -2911,7 +2919,9 @@ DerivedMesh *editbmesh_get_derived_cage_and_final(
return em->derivedCage;
}
-DerivedMesh *editbmesh_get_derived_cage(Scene *scene, Object *obedit, BMEditMesh *em, CustomDataMask dataMask)
+DerivedMesh *editbmesh_get_derived_cage(
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *obedit, BMEditMesh *em,
+ CustomDataMask dataMask)
{
/* if there's no derived mesh or the last data mask used doesn't include
* the data we need, rebuild the derived mesh
@@ -2921,7 +2931,7 @@ DerivedMesh *editbmesh_get_derived_cage(Scene *scene, Object *obedit, BMEditMesh
if (!em->derivedCage ||
(em->lastDataMask & dataMask) != dataMask)
{
- editbmesh_build_data(scene, obedit, em, dataMask);
+ editbmesh_build_data(eval_ctx, scene, obedit, em, dataMask);
}
return em->derivedCage;
@@ -3058,234 +3068,6 @@ void mesh_get_mapped_verts_coords(DerivedMesh *dm, float (*r_cos)[3], const int
/* ******************* GLSL ******************** */
-/** \name Tangent Space Calculation
- * \{ */
-
-/* Necessary complexity to handle looptri's as quads for correct tangents */
-#define USE_LOOPTRI_DETECT_QUADS
-
-typedef struct {
- float (*precomputedFaceNormals)[3];
- float (*precomputedLoopNormals)[3];
- const MLoopTri *looptri;
- MLoopUV *mloopuv; /* texture coordinates */
- MPoly *mpoly; /* indices */
- MLoop *mloop; /* indices */
- MVert *mvert; /* vertices & normals */
- float (*orco)[3];
- float (*tangent)[4]; /* destination */
- int numTessFaces;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- /* map from 'fake' face index to looptri,
- * quads will point to the first looptri of the quad */
- const int *face_as_quad_map;
- int num_face_as_quad_map;
-#endif
-
-} SGLSLMeshToTangent;
-
-/* interface */
-#include "mikktspace.h"
-
-static int dm_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
-{
- SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- return pMesh->num_face_as_quad_map;
-#else
- return pMesh->numTessFaces;
-#endif
-}
-
-static int dm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
-{
-#ifdef USE_LOOPTRI_DETECT_QUADS
- SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
- if (pMesh->face_as_quad_map) {
- const MLoopTri *lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
- const MPoly *mp = &pMesh->mpoly[lt->poly];
- if (mp->totloop == 4) {
- return 4;
- }
- }
- return 3;
-#else
- UNUSED_VARS(pContext, face_num);
- return 3;
-#endif
-}
-
-static void dm_ts_GetPosition(
- const SMikkTSpaceContext *pContext, float r_co[3],
- const int face_num, const int vert_index)
-{
- //assert(vert_index >= 0 && vert_index < 4);
- SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
- const MLoopTri *lt;
- int loop_index;
- const float *co;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- if (pMesh->face_as_quad_map) {
- lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
- const MPoly *mp = &pMesh->mpoly[lt->poly];
- if (mp->totloop == 4) {
- loop_index = mp->loopstart + vert_index;
- goto finally;
- }
- /* fall through to regular triangle */
- }
- else {
- lt = &pMesh->looptri[face_num];
- }
-#else
- lt = &pMesh->looptri[face_num];
-#endif
- loop_index = lt->tri[vert_index];
-
-finally:
- co = pMesh->mvert[pMesh->mloop[loop_index].v].co;
- copy_v3_v3(r_co, co);
-}
-
-static void dm_ts_GetTextureCoordinate(
- const SMikkTSpaceContext *pContext, float r_uv[2],
- const int face_num, const int vert_index)
-{
- //assert(vert_index >= 0 && vert_index < 4);
- SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
- const MLoopTri *lt;
- int loop_index;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- if (pMesh->face_as_quad_map) {
- lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
- const MPoly *mp = &pMesh->mpoly[lt->poly];
- if (mp->totloop == 4) {
- loop_index = mp->loopstart + vert_index;
- goto finally;
- }
- /* fall through to regular triangle */
- }
- else {
- lt = &pMesh->looptri[face_num];
- }
-#else
- lt = &pMesh->looptri[face_num];
-#endif
- loop_index = lt->tri[vert_index];
-
-finally:
- if (pMesh->mloopuv != NULL) {
- const float *uv = pMesh->mloopuv[loop_index].uv;
- copy_v2_v2(r_uv, uv);
- }
- else {
- const float *orco = pMesh->orco[pMesh->mloop[loop_index].v];
- map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]);
- }
-}
-
-static void dm_ts_GetNormal(
- const SMikkTSpaceContext *pContext, float r_no[3],
- const int face_num, const int vert_index)
-{
- //assert(vert_index >= 0 && vert_index < 4);
- SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
- const MLoopTri *lt;
- int loop_index;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- if (pMesh->face_as_quad_map) {
- lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
- const MPoly *mp = &pMesh->mpoly[lt->poly];
- if (mp->totloop == 4) {
- loop_index = mp->loopstart + vert_index;
- goto finally;
- }
- /* fall through to regular triangle */
- }
- else {
- lt = &pMesh->looptri[face_num];
- }
-#else
- lt = &pMesh->looptri[face_num];
-#endif
- loop_index = lt->tri[vert_index];
-
-finally:
- if (pMesh->precomputedLoopNormals) {
- copy_v3_v3(r_no, pMesh->precomputedLoopNormals[loop_index]);
- }
- else if ((pMesh->mpoly[lt->poly].flag & ME_SMOOTH) == 0) { /* flat */
- if (pMesh->precomputedFaceNormals) {
- copy_v3_v3(r_no, pMesh->precomputedFaceNormals[lt->poly]);
- }
- else {
-#ifdef USE_LOOPTRI_DETECT_QUADS
- const MPoly *mp = &pMesh->mpoly[lt->poly];
- if (mp->totloop == 4) {
- normal_quad_v3(
- r_no,
- pMesh->mvert[pMesh->mloop[mp->loopstart + 0].v].co,
- pMesh->mvert[pMesh->mloop[mp->loopstart + 1].v].co,
- pMesh->mvert[pMesh->mloop[mp->loopstart + 2].v].co,
- pMesh->mvert[pMesh->mloop[mp->loopstart + 3].v].co);
- }
- else
-#endif
- {
- normal_tri_v3(
- r_no,
- pMesh->mvert[pMesh->mloop[lt->tri[0]].v].co,
- pMesh->mvert[pMesh->mloop[lt->tri[1]].v].co,
- pMesh->mvert[pMesh->mloop[lt->tri[2]].v].co);
- }
- }
- }
- else {
- const short *no = pMesh->mvert[pMesh->mloop[loop_index].v].no;
- normal_short_to_float_v3(r_no, no);
- }
-}
-
-static void dm_ts_SetTSpace(
- const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign,
- const int face_num, const int vert_index)
-{
- //assert(vert_index >= 0 && vert_index < 4);
- SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
- const MLoopTri *lt;
- int loop_index;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- if (pMesh->face_as_quad_map) {
- lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
- const MPoly *mp = &pMesh->mpoly[lt->poly];
- if (mp->totloop == 4) {
- loop_index = mp->loopstart + vert_index;
- goto finally;
- }
- /* fall through to regular triangle */
- }
- else {
- lt = &pMesh->looptri[face_num];
- }
-#else
- lt = &pMesh->looptri[face_num];
-#endif
- loop_index = lt->tri[vert_index];
-
- float *pRes;
-
-finally:
- pRes = pMesh->tangent[loop_index];
- copy_v3_v3(pRes, fvTangent);
- pRes[3] = fSign;
-}
-
void DM_calc_tangents_names_from_gpu(
const GPUVertexAttribs *gattribs,
char (*tangent_names)[MAX_NAME], int *r_tangent_names_count)
@@ -3299,28 +3081,6 @@ void DM_calc_tangents_names_from_gpu(
*r_tangent_names_count = count;
}
-static void DM_calc_loop_tangents_thread(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
-{
- struct SGLSLMeshToTangent *mesh2tangent = taskdata;
- /* new computation method */
- {
- SMikkTSpaceContext sContext = {NULL};
- SMikkTSpaceInterface sInterface = {NULL};
-
- sContext.m_pUserData = mesh2tangent;
- sContext.m_pInterface = &sInterface;
- sInterface.m_getNumFaces = dm_ts_GetNumFaces;
- sInterface.m_getNumVerticesOfFace = dm_ts_GetNumVertsOfFace;
- sInterface.m_getPosition = dm_ts_GetPosition;
- sInterface.m_getTexCoord = dm_ts_GetTextureCoordinate;
- sInterface.m_getNormal = dm_ts_GetNormal;
- sInterface.m_setTSpaceBasic = dm_ts_SetTSpace;
-
- /* 0 if failed */
- genTangSpaceDefault(&sContext);
- }
-}
-
void DM_add_named_tangent_layer_for_uv(
CustomData *uv_data, CustomData *tan_data, int numLoopData,
const char *layer_name)
@@ -3334,213 +3094,26 @@ void DM_add_named_tangent_layer_for_uv(
}
}
-/**
- * Here we get some useful information such as active uv layer name and search if it is already in tangent_names.
- * Also, we calculate tangent_mask that works as a descriptor of tangents state.
- * If tangent_mask has changed, then recalculate tangents.
- */
-void DM_calc_loop_tangents_step_0(
- const CustomData *loopData, bool calc_active_tangent,
- const char (*tangent_names)[MAX_NAME], int tangent_names_count,
- bool *rcalc_act, bool *rcalc_ren, int *ract_uv_n, int *rren_uv_n,
- char *ract_uv_name, char *rren_uv_name, short *rtangent_mask)
-{
- /* Active uv in viewport */
- int layer_index = CustomData_get_layer_index(loopData, CD_MLOOPUV);
- *ract_uv_n = CustomData_get_active_layer(loopData, CD_MLOOPUV);
- ract_uv_name[0] = 0;
- if (*ract_uv_n != -1) {
- strcpy(ract_uv_name, loopData->layers[*ract_uv_n + layer_index].name);
- }
-
- /* Active tangent in render */
- *rren_uv_n = CustomData_get_render_layer(loopData, CD_MLOOPUV);
- rren_uv_name[0] = 0;
- if (*rren_uv_n != -1) {
- strcpy(rren_uv_name, loopData->layers[*rren_uv_n + layer_index].name);
- }
-
- /* If active tangent not in tangent_names we take it into account */
- *rcalc_act = false;
- *rcalc_ren = false;
- for (int i = 0; i < tangent_names_count; i++) {
- if (tangent_names[i][0] == 0) {
- calc_active_tangent = true;
- }
- }
- if (calc_active_tangent) {
- *rcalc_act = true;
- *rcalc_ren = true;
- for (int i = 0; i < tangent_names_count; i++) {
- if (STREQ(ract_uv_name, tangent_names[i]))
- *rcalc_act = false;
- if (STREQ(rren_uv_name, tangent_names[i]))
- *rcalc_ren = false;
- }
- }
- *rtangent_mask = 0;
-
- const int uv_layer_num = CustomData_number_of_layers(loopData, CD_MLOOPUV);
- for (int n = 0; n < uv_layer_num; n++) {
- const char *name = CustomData_get_layer_name(loopData, CD_MLOOPUV, n);
- bool add = false;
- for (int i = 0; i < tangent_names_count; i++) {
- if (tangent_names[i][0] && STREQ(tangent_names[i], name)) {
- add = true;
- break;
- }
- }
- if ((*rcalc_act && ract_uv_name[0] && STREQ(ract_uv_name, name)) ||
- (*rcalc_ren && rren_uv_name[0] && STREQ(rren_uv_name, name)))
- {
- add = true;
- }
- if (add)
- *rtangent_mask |= 1 << n;
- }
-
- if (uv_layer_num == 0)
- *rtangent_mask |= DM_TANGENT_MASK_ORCO;
-}
-
void DM_calc_loop_tangents(
DerivedMesh *dm, bool calc_active_tangent,
- const char (*tangent_names)[MAX_NAME], int tangent_names_count)
-{
- int act_uv_n = -1;
- int ren_uv_n = -1;
- bool calc_act = false;
- bool calc_ren = false;
- char act_uv_name[MAX_NAME];
- char ren_uv_name[MAX_NAME];
- short tangent_mask = 0;
- DM_calc_loop_tangents_step_0(
- &dm->loopData, calc_active_tangent, tangent_names, tangent_names_count,
- &calc_act, &calc_ren, &act_uv_n, &ren_uv_n, act_uv_name, ren_uv_name, &tangent_mask);
- if ((dm->tangent_mask | tangent_mask) != dm->tangent_mask) {
- /* Check we have all the needed layers */
- MPoly *mpoly = dm->getPolyArray(dm);
- const MLoopTri *looptri = dm->getLoopTriArray(dm);
- int totface = dm->getNumLoopTri(dm);
- /* Allocate needed tangent layers */
- for (int i = 0; i < tangent_names_count; i++)
- if (tangent_names[i][0])
- DM_add_named_tangent_layer_for_uv(&dm->loopData, &dm->loopData, dm->numLoopData, tangent_names[i]);
- if ((tangent_mask & DM_TANGENT_MASK_ORCO) && CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, "") == -1)
- CustomData_add_layer_named(&dm->loopData, CD_TANGENT, CD_CALLOC, NULL, dm->numLoopData, "");
- if (calc_act && act_uv_name[0])
- DM_add_named_tangent_layer_for_uv(&dm->loopData, &dm->loopData, dm->numLoopData, act_uv_name);
- if (calc_ren && ren_uv_name[0])
- DM_add_named_tangent_layer_for_uv(&dm->loopData, &dm->loopData, dm->numLoopData, ren_uv_name);
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- int num_face_as_quad_map;
- int *face_as_quad_map = NULL;
-
- /* map faces to quads */
- if (totface != dm->getNumPolys(dm)) {
- /* over alloc, since we dont know how many ngon or quads we have */
-
- /* map fake face index to looptri */
- face_as_quad_map = MEM_malloc_arrayN(totface, sizeof(int), __func__);
- int k, j;
- for (k = 0, j = 0; j < totface; k++, j++) {
- face_as_quad_map[k] = j;
- /* step over all quads */
- if (mpoly[looptri[j].poly].totloop == 4) {
- j++; /* skips the nest looptri */
- }
- }
- num_face_as_quad_map = k;
- }
- else {
- num_face_as_quad_map = totface;
- }
-#endif
-
- /* Calculation */
- {
- TaskScheduler *scheduler = BLI_task_scheduler_get();
- TaskPool *task_pool;
- task_pool = BLI_task_pool_create(scheduler, NULL);
-
- dm->tangent_mask = 0;
- /* Calculate tangent layers */
- SGLSLMeshToTangent data_array[MAX_MTFACE];
- const int tangent_layer_num = CustomData_number_of_layers(&dm->loopData, CD_TANGENT);
- for (int n = 0; n < tangent_layer_num; n++) {
- int index = CustomData_get_layer_index_n(&dm->loopData, CD_TANGENT, n);
- BLI_assert(n < MAX_MTFACE);
- SGLSLMeshToTangent *mesh2tangent = &data_array[n];
- mesh2tangent->numTessFaces = totface;
-#ifdef USE_LOOPTRI_DETECT_QUADS
- mesh2tangent->face_as_quad_map = face_as_quad_map;
- mesh2tangent->num_face_as_quad_map = num_face_as_quad_map;
-#endif
- mesh2tangent->mvert = dm->getVertArray(dm);
- mesh2tangent->mpoly = dm->getPolyArray(dm);
- mesh2tangent->mloop = dm->getLoopArray(dm);
- mesh2tangent->looptri = dm->getLoopTriArray(dm);
- /* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled),
- * have to check this is valid...
- */
- mesh2tangent->precomputedLoopNormals = dm->getLoopDataArray(dm, CD_NORMAL);
- mesh2tangent->precomputedFaceNormals = CustomData_get_layer(&dm->polyData, CD_NORMAL);
-
- mesh2tangent->orco = NULL;
- mesh2tangent->mloopuv = CustomData_get_layer_named(&dm->loopData, CD_MLOOPUV, dm->loopData.layers[index].name);
-
- /* Fill the resulting tangent_mask */
- if (!mesh2tangent->mloopuv) {
- mesh2tangent->orco = dm->getVertDataArray(dm, CD_ORCO);
- if (!mesh2tangent->orco)
- continue;
-
- dm->tangent_mask |= DM_TANGENT_MASK_ORCO;
- }
- else {
- int uv_ind = CustomData_get_named_layer_index(&dm->loopData, CD_MLOOPUV, dm->loopData.layers[index].name);
- int uv_start = CustomData_get_layer_index(&dm->loopData, CD_MLOOPUV);
- BLI_assert(uv_ind != -1 && uv_start != -1);
- BLI_assert(uv_ind - uv_start < MAX_MTFACE);
- dm->tangent_mask |= 1 << (uv_ind - uv_start);
- }
-
- mesh2tangent->tangent = dm->loopData.layers[index].data;
- BLI_task_pool_push(task_pool, DM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW);
- }
-
- BLI_assert(dm->tangent_mask == tangent_mask);
- BLI_task_pool_work_and_wait(task_pool);
- BLI_task_pool_free(task_pool);
- }
-#ifdef USE_LOOPTRI_DETECT_QUADS
- if (face_as_quad_map) {
- MEM_freeN(face_as_quad_map);
- }
-#undef USE_LOOPTRI_DETECT_QUADS
-
-#endif
-
- /* Update active layer index */
- int act_uv_index = CustomData_get_layer_index_n(&dm->loopData, CD_MLOOPUV, act_uv_n);
- if (act_uv_index != -1) {
- int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, dm->loopData.layers[act_uv_index].name);
- CustomData_set_layer_active_index(&dm->loopData, CD_TANGENT, tan_index);
- } /* else tangent has been built from orco */
-
- /* Update render layer index */
- int ren_uv_index = CustomData_get_layer_index_n(&dm->loopData, CD_MLOOPUV, ren_uv_n);
- if (ren_uv_index != -1) {
- int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, dm->loopData.layers[ren_uv_index].name);
- CustomData_set_layer_render_index(&dm->loopData, CD_TANGENT, tan_index);
- } /* else tangent has been built from orco */
- }
+ const char (*tangent_names)[MAX_NAME], int tangent_names_len)
+{
+ BKE_mesh_calc_loop_tangent_ex(
+ dm->getVertArray(dm),
+ dm->getPolyArray(dm), dm->getNumPolys(dm),
+ dm->getLoopArray(dm),
+ dm->getLoopTriArray(dm), dm->getNumLoopTri(dm),
+ &dm->loopData,
+ calc_active_tangent,
+ tangent_names, tangent_names_len,
+ CustomData_get_layer(&dm->polyData, CD_NORMAL),
+ dm->getLoopDataArray(dm, CD_NORMAL),
+ dm->getVertDataArray(dm, CD_ORCO), /* may be NULL */
+ /* result */
+ &dm->loopData, dm->getNumLoops(dm),
+ &dm->tangent_mask);
}
-/** \} */
-
-
void DM_calc_auto_bump_scale(DerivedMesh *dm)
{
/* int totvert = dm->getNumVerts(dm); */ /* UNUSED */
@@ -3969,7 +3542,6 @@ BLI_INLINE void navmesh_intToCol(int i, float col[3])
static void navmesh_drawColored(DerivedMesh *dm)
{
- int a, glmode;
MVert *mvert = (MVert *)CustomData_get_layer(&dm->vertData, CD_MVERT);
MFace *mface = (MFace *)CustomData_get_layer(&dm->faceData, CD_MFACE);
int *polygonIdx = (int *)CustomData_get_layer(&dm->polyData, CD_RECAST);
@@ -3984,43 +3556,42 @@ static void navmesh_drawColored(DerivedMesh *dm)
dm->drawEdges(dm, 0, 1);
#endif
- /* if (GPU_buffer_legacy(dm) ) */ /* TODO - VBO draw code, not high priority - campbell */
- {
- DEBUG_VBO("Using legacy code. drawNavMeshColored\n");
- glBegin(glmode = GL_QUADS);
- for (a = 0; a < dm->numTessFaceData; a++, mface++) {
- int new_glmode = mface->v4 ? GL_QUADS : GL_TRIANGLES;
- int pi = polygonIdx[a];
- if (pi <= 0) {
- zero_v3(col);
- }
- else {
- navmesh_intToCol(pi, col);
- }
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ unsigned int color = GWN_vertformat_attr_add(format, "color", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- if (new_glmode != glmode) {
- glEnd();
- glBegin(glmode = new_glmode);
- }
- glColor3fv(col);
- glVertex3fv(mvert[mface->v1].co);
- glVertex3fv(mvert[mface->v2].co);
- glVertex3fv(mvert[mface->v3].co);
- if (mface->v4) {
- glVertex3fv(mvert[mface->v4].co);
- }
+ immBindBuiltinProgram(GPU_SHADER_3D_FLAT_COLOR);
+
+ /* Note: batch drawing API would let us share vertices */
+ immBeginAtMost(GWN_PRIM_TRIS, dm->numTessFaceData * 6);
+ for (int a = 0; a < dm->numTessFaceData; a++, mface++) {
+ int pi = polygonIdx[a];
+ if (pi <= 0) {
+ zero_v3(col);
+ }
+ else {
+ navmesh_intToCol(pi, col);
}
- glEnd();
- }
-}
-static void navmesh_DM_drawFacesTex(
- DerivedMesh *dm,
- DMSetDrawOptionsTex UNUSED(setDrawOptions),
- DMCompareDrawOptions UNUSED(compareDrawOptions),
- void *UNUSED(userData), DMDrawFlag UNUSED(flag))
-{
- navmesh_drawColored(dm);
+ immSkipAttrib(color);
+ immVertex3fv(pos, mvert[mface->v1].co);
+ immSkipAttrib(color);
+ immVertex3fv(pos, mvert[mface->v2].co);
+ immAttrib3fv(color, col);
+ immVertex3fv(pos, mvert[mface->v3].co);
+
+ if (mface->v4) {
+ /* this tess face is a quad, so draw the other triangle */
+ immSkipAttrib(color);
+ immVertex3fv(pos, mvert[mface->v1].co);
+ immSkipAttrib(color);
+ immVertex3fv(pos, mvert[mface->v3].co);
+ immAttrib3fv(color, col);
+ immVertex3fv(pos, mvert[mface->v4].co);
+ }
+ }
+ immEnd();
+ immUnbindProgram();
}
static void navmesh_DM_drawFacesSolid(
@@ -4056,7 +3627,6 @@ static DerivedMesh *navmesh_dm_createNavMeshForVisualization(DerivedMesh *dm)
recastData = (int *)CustomData_get_layer(&result->polyData, CD_RECAST);
/* note: This is not good design! - really should not be doing this */
- result->drawFacesTex = navmesh_DM_drawFacesTex;
result->drawFacesSolid = navmesh_DM_drawFacesSolid;
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 034248df8d5..acb2db8d7ad 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -55,7 +55,6 @@
#include "BKE_animsys.h"
#include "BKE_constraint.h"
#include "BKE_deform.h"
-#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
@@ -65,6 +64,8 @@
#include "BKE_main.h"
#include "BKE_object.h"
+#include "DEG_depsgraph_build.h"
+
#include "BIK_api.h"
#include "RNA_access.h"
@@ -587,6 +588,8 @@ void BKE_pose_copy_data_ex(bPose **dst, const bPose *src, const int flag, const
if (pchan->prop) {
pchan->prop = IDP_CopyProperty_ex(pchan->prop, flag);
}
+
+ pchan->draw_data = NULL; /* Drawing cache, no need to copy. */
}
/* for now, duplicate Bone Groups too when doing this */
@@ -780,6 +783,9 @@ void BKE_pose_channel_free_ex(bPoseChannel *pchan, bool do_id_user)
IDP_FreeProperty(pchan->prop);
MEM_freeN(pchan->prop);
}
+
+ /* Cached data, for new draw manager rendering code. */
+ MEM_SAFE_FREE(pchan->draw_data);
}
void BKE_pose_channel_free(bPoseChannel *pchan)
@@ -1428,7 +1434,7 @@ void BKE_pose_tag_recalc(Main *bmain, bPose *pose)
/* Depsgraph components depends on actual pose state,
* if pose was changed depsgraph is to be updated as well.
*/
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
/* For the calculation of the effects of an Action at the given frame on an object
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 2f65e71c6d2..62df97c6afa 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -43,8 +43,8 @@
#include "DNA_key_types.h"
#include "DNA_scene_types.h"
+#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_key.h"
#include "BKE_main.h"
@@ -54,6 +54,9 @@
#include "BKE_anim.h"
#include "BKE_report.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
// XXX bad level call...
/* --------------------- */
@@ -273,88 +276,23 @@ void animviz_get_object_motionpaths(Object *ob, ListBase *targets)
/* ........ */
-/* Note on evaluation optimizations:
- * Optimization's currently used here play tricks with the depsgraph in order to try and
- * evaluate as few objects as strictly necessary to get nicer performance under standard
- * production conditions. For those people who really need the accurate version,
- * disable the ifdef (i.e. 1 -> 0) and comment out the call to motionpaths_calc_optimise_depsgraph()
- */
-
-/* tweak the object ordering to trick depsgraph into making MotionPath calculations run faster */
-static void motionpaths_calc_optimise_depsgraph(Scene *scene, ListBase *targets)
-{
- Base *base, *baseNext;
- MPathTarget *mpt;
-
- /* make sure our temp-tag isn't already in use */
- for (base = scene->base.first; base; base = base->next)
- base->object->flag &= ~BA_TEMP_TAG;
-
- /* for each target, dump its object to the start of the list if it wasn't moved already */
- for (mpt = targets->first; mpt; mpt = mpt->next) {
- for (base = scene->base.first; base; base = baseNext) {
- baseNext = base->next;
-
- if ((base->object == mpt->ob) && !(mpt->ob->flag & BA_TEMP_TAG)) {
- BLI_remlink(&scene->base, base);
- BLI_addhead(&scene->base, base);
-
- mpt->ob->flag |= BA_TEMP_TAG;
-
- /* we really don't need to continue anymore once this happens, but this line might really 'break' */
- break;
- }
- }
- }
-
- /* "brew me a list that's sorted a bit faster now depsy" */
- DAG_scene_relations_rebuild(G.main, scene);
-}
-
/* update scene for current frame */
-static void motionpaths_calc_update_scene(Scene *scene)
+static void motionpaths_calc_update_scene(Main *bmain,
+ Scene *scene,
+ ViewLayer *view_layer,
+ struct Depsgraph *depsgraph)
{
-#if 1 // 'production' optimizations always on
- /* rigid body simulation needs complete update to work correctly for now */
- /* RB_TODO investigate if we could avoid updating everything */
- if (BKE_scene_check_rigidbody_active(scene)) {
- BKE_scene_update_for_newframe(G.main->eval_ctx, G.main, scene, scene->lay);
- }
- else { /* otherwise we can optimize by restricting updates */
- Base *base, *last = NULL;
-
- /* only stuff that moves or needs display still */
- DAG_scene_update_flags(G.main, scene, scene->lay, true, false);
-
- /* find the last object with the tag
- * - all those afterwards are assumed to not be relevant for our calculations
- */
- /* optimize further by moving out... */
- for (base = scene->base.first; base; base = base->next) {
- if (base->object->flag & BA_TEMP_TAG)
- last = base;
- }
-
- /* perform updates for tagged objects */
- /* XXX: this will break if rigs depend on scene or other data that
- * is animated but not attached to/updatable from objects */
- for (base = scene->base.first; base; base = base->next) {
- /* update this object */
- BKE_object_handle_update(G.main->eval_ctx, scene, base->object);
-
- /* if this is the last one we need to update, let's stop to save some time */
- if (base == last)
- break;
- }
- }
-#else // original, 'always correct' version
- /* do all updates
+ /* Do all updates
* - if this is too slow, resort to using a more efficient way
* that doesn't force complete update, but for now, this is the
* most accurate way!
+ *
+ * TODO(segey): Bring back partial updates, which became impossible
+ * with the new depsgraph due to unsorted nature of bases.
+ *
+ * TODO(sergey): Use evaluation context dedicated to motion paths.
*/
- BKE_scene_update_for_newframe(G.main->eval_ctx, G.main, scene, scene->lay); /* XXX this is the best way we can get anything moving */
-#endif
+ BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
}
/* ........ */
@@ -404,7 +342,7 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
* - recalc: whether we need to
*/
/* TODO: include reports pointer? */
-void animviz_calc_motionpaths(Scene *scene, ListBase *targets)
+ void animviz_calc_motionpaths(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, ListBase *targets)
{
MPathTarget *mpt;
int sfra, efra;
@@ -428,14 +366,10 @@ void animviz_calc_motionpaths(Scene *scene, ListBase *targets)
}
if (efra <= sfra) return;
- /* optimize the depsgraph for faster updates */
- /* TODO: whether this is used should depend on some setting for the level of optimizations used */
- motionpaths_calc_optimise_depsgraph(scene, targets);
-
/* calculate path over requested range */
for (CFRA = sfra; CFRA <= efra; CFRA++) {
/* update relevant data for new frame */
- motionpaths_calc_update_scene(scene);
+ motionpaths_calc_update_scene(bmain, scene, eval_ctx->view_layer, eval_ctx->depsgraph);
/* perform baking for targets */
motionpaths_calc_bake_targets(scene, targets);
@@ -443,7 +377,7 @@ void animviz_calc_motionpaths(Scene *scene, ListBase *targets)
/* reset original environment */
CFRA = cfra;
- motionpaths_calc_update_scene(scene);
+ motionpaths_calc_update_scene(bmain, scene, eval_ctx->view_layer, eval_ctx->depsgraph);
/* clear recalc flags from targets */
for (mpt = targets->first; mpt; mpt = mpt->next) {
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index 21fb29ff06d..58b476d3da5 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -60,7 +60,6 @@
#include "BKE_animsys.h"
#include "BKE_action.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_nla.h"
#include "BKE_global.h"
@@ -70,6 +69,8 @@
#include "BKE_report.h"
#include "BKE_texture.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "nla_private.h"
@@ -95,6 +96,7 @@ bool id_type_can_have_animdata(const short id_type)
case ID_MA: case ID_TE: case ID_NT:
case ID_LA: case ID_CA: case ID_WO:
case ID_LS:
+ case ID_LP:
case ID_SPK:
case ID_SCE:
case ID_MC:
@@ -1563,12 +1565,6 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val
/* caller must ensure this is animatable */
BLI_assert(RNA_property_animateable(ptr, prop) || ptr->id.data == NULL);
- /* set value for animatable numerical values only
- * HACK: some local F-Curves (e.g. those on NLA Strips) are evaluated
- * without an ID provided, which causes the animateable test to fail!
- */
- bool written = false;
-
switch (RNA_property_type(prop)) {
case PROP_BOOLEAN:
{
@@ -1576,13 +1572,11 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val
if (array_index != -1) {
if (RNA_property_boolean_get_index(ptr, prop, array_index) != value_coerce) {
RNA_property_boolean_set_index(ptr, prop, array_index, value_coerce);
- written = true;
}
}
else {
if (RNA_property_boolean_get(ptr, prop) != value_coerce) {
RNA_property_boolean_set(ptr, prop, value_coerce);
- written = true;
}
}
break;
@@ -1594,13 +1588,11 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val
if (array_index != -1) {
if (RNA_property_int_get_index(ptr, prop, array_index) != value_coerce) {
RNA_property_int_set_index(ptr, prop, array_index, value_coerce);
- written = true;
}
}
else {
if (RNA_property_int_get(ptr, prop) != value_coerce) {
RNA_property_int_set(ptr, prop, value_coerce);
- written = true;
}
}
break;
@@ -1612,13 +1604,11 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val
if (array_index != -1) {
if (RNA_property_float_get_index(ptr, prop, array_index) != value_coerce) {
RNA_property_float_set_index(ptr, prop, array_index, value_coerce);
- written = true;
}
}
else {
if (RNA_property_float_get(ptr, prop) != value_coerce) {
RNA_property_float_set(ptr, prop, value_coerce);
- written = true;
}
}
break;
@@ -1628,7 +1618,6 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val
const int value_coerce = (int)value;
if (RNA_property_enum_get(ptr, prop) != value_coerce) {
RNA_property_enum_set(ptr, prop, value_coerce);
- written = true;
}
break;
}
@@ -1657,23 +1646,6 @@ static bool animsys_write_rna_setting(PathResolvedRNA *anim_rna, const float val
}
#endif
- /* as long as we don't do property update, we still tag datablock
- * as having been updated. this flag does not cause any updates to
- * be run, it's for e.g. render engines to synchronize data */
- if (written && ptr->id.data) {
- ID *id = ptr->id.data;
-
- /* for cases like duplifarmes it's only a temporary so don't
- * notify anyone of updates */
- if (!(id->recalc & ID_RECALC_SKIP_ANIM_TAG)) {
- /* NOTE: This is a bit annoying to use atomic API here, but this
- * code is at it's EOL and removed already in 2.8 branch.
- */
- atomic_fetch_and_or_int32(&id->recalc, ID_RECALC);
- DAG_id_type_tag(G.main, GS(id->name));
- }
- }
-
/* successful */
return true;
}
@@ -2617,17 +2589,6 @@ static void animsys_evaluate_nla(ListBase *echannels, PointerRNA *ptr, AnimData
/* 3. free temporary evaluation data that's not used elsewhere */
BLI_freelistN(&estrips);
-
- /* Tag ID as updated so render engines will recognize changes in data
- * which is animated but doesn't have actions.
- */
- if (ptr->id.data != NULL) {
- ID *id = ptr->id.data;
- if (!(id->recalc & ID_RECALC_SKIP_ANIM_TAG)) {
- id->recalc |= ID_RECALC;
- DAG_id_type_tag(G.main, GS(id->name));
- }
- }
}
/* NLA Evaluation function (mostly for use through do_animdata)
@@ -2920,7 +2881,7 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime)
#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
-void BKE_animsys_eval_animdata(EvaluationContext *eval_ctx, ID *id)
+void BKE_animsys_eval_animdata(const EvaluationContext *eval_ctx, ID *id)
{
AnimData *adt = BKE_animdata_from_id(id);
Scene *scene = NULL; /* XXX: this is only needed for flushing RNA updates,
@@ -2930,7 +2891,7 @@ void BKE_animsys_eval_animdata(EvaluationContext *eval_ctx, ID *id)
BKE_animsys_evaluate_animdata(scene, id, adt, eval_ctx->ctime, ADT_RECALC_ANIM);
}
-void BKE_animsys_eval_driver(EvaluationContext *eval_ctx,
+void BKE_animsys_eval_driver(const EvaluationContext *eval_ctx,
ID *id,
FCurve *fcu)
{
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 2edbd088334..953fef067b4 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -60,7 +60,6 @@
#include "BKE_anim.h"
#include "BKE_constraint.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_deform.h"
#include "BKE_displist.h"
@@ -1464,13 +1463,13 @@ void BKE_armature_loc_pose_to_bone(bPoseChannel *pchan, const float inloc[3], fl
copy_v3_v3(outloc, nLocMat[3]);
}
-void BKE_armature_mat_pose_to_bone_ex(Object *ob, bPoseChannel *pchan, float inmat[4][4], float outmat[4][4])
+void BKE_armature_mat_pose_to_bone_ex(const struct EvaluationContext *eval_ctx, Object *ob, bPoseChannel *pchan, float inmat[4][4], float outmat[4][4])
{
bPoseChannel work_pchan = *pchan;
/* recalculate pose matrix with only parent transformations,
* bone loc/sca/rot is ignored, scene and frame are not used. */
- BKE_pose_where_is_bone(NULL, ob, &work_pchan, 0.0f, false);
+ BKE_pose_where_is_bone(eval_ctx, NULL, ob, &work_pchan, 0.0f, false);
/* find the matrix, need to remove the bone transforms first so this is
* calculated as a matrix to set rather then a difference ontop of whats
@@ -1953,7 +1952,7 @@ void BKE_pose_clear_pointers(bPose *pose)
/* only after leave editmode, duplicating, validating older files, library syncing */
/* NOTE: pose->flag is set for it */
-void BKE_pose_rebuild_ex(Object *ob, bArmature *arm, const bool sort_bones)
+void BKE_pose_rebuild(Object *ob, bArmature *arm)
{
Bone *bone;
bPose *pose;
@@ -1997,27 +1996,12 @@ void BKE_pose_rebuild_ex(Object *ob, bArmature *arm, const bool sort_bones)
BKE_pose_update_constraint_flags(ob->pose); /* for IK detection for example */
-#ifdef WITH_LEGACY_DEPSGRAPH
- /* the sorting */
- /* Sorting for new dependnecy graph is done on the scene graph level. */
- if (counter > 1 && sort_bones) {
- DAG_pose_sort(ob);
- }
-#else
- UNUSED_VARS(sort_bones);
-#endif
-
ob->pose->flag &= ~POSE_RECALC;
ob->pose->flag |= POSE_WAS_REBUILT;
BKE_pose_channels_hash_make(ob->pose);
}
-void BKE_pose_rebuild(Object *ob, bArmature *arm)
-{
- BKE_pose_rebuild_ex(ob, arm, true);
-}
-
/* ********************** THE POSE SOLVER ******************* */
/* loc/rot/size to given mat4 */
@@ -2128,7 +2112,7 @@ static void do_strip_modifiers(Scene *scene, Object *armob, Bone *bone, bPoseCha
if (STREQ(pchan->name, amod->channel)) {
float mat4[4][4], mat3[3][3];
- curve_deform_vector(scene, amod->ob, armob, bone->arm_mat[3], pchan->pose_mat[3], mat3, amod->no_rot_axis);
+ curve_deform_vector(amod->ob, armob, bone->arm_mat[3], pchan->pose_mat[3], mat3, amod->no_rot_axis);
copy_m4_m4(mat4, pchan->pose_mat);
mul_m4_m3m4(pchan->pose_mat, mat3, mat4);
@@ -2212,7 +2196,9 @@ void BKE_pose_where_is_bone_tail(bPoseChannel *pchan)
/* pchan is validated, as having bone and parent pointer
* 'do_extra': when zero skips loc/size/rot, constraints and strip modifiers.
*/
-void BKE_pose_where_is_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float ctime, bool do_extra)
+void BKE_pose_where_is_bone(
+ const struct EvaluationContext *eval_ctx, Scene *scene,
+ Object *ob, bPoseChannel *pchan, float ctime, bool do_extra)
{
/* This gives a chan_mat with actions (ipos) results. */
if (do_extra)
@@ -2251,7 +2237,7 @@ void BKE_pose_where_is_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float
cob = BKE_constraints_make_evalob(scene, ob, pchan, CONSTRAINT_OBTYPE_BONE);
/* Solve PoseChannel's Constraints */
- BKE_constraints_solve(&pchan->constraints, cob, ctime); /* ctime doesnt alter objects */
+ BKE_constraints_solve(eval_ctx, &pchan->constraints, cob, ctime); /* ctime doesnt alter objects */
/* cleanup after Constraint Solving
* - applies matrix back to pchan, and frees temporary struct used
@@ -2273,7 +2259,7 @@ void BKE_pose_where_is_bone(Scene *scene, Object *ob, bPoseChannel *pchan, float
/* This only reads anim data from channels, and writes to channels */
/* This is the only function adding poses */
-void BKE_pose_where_is(Scene *scene, Object *ob)
+void BKE_pose_where_is(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
bArmature *arm;
Bone *bone;
@@ -2312,7 +2298,7 @@ void BKE_pose_where_is(Scene *scene, Object *ob)
}
/* 2a. construct the IK tree (standard IK) */
- BIK_initialize_tree(scene, ob, ctime);
+ BIK_initialize_tree(eval_ctx, scene, ob, ctime);
/* 2b. construct the Spline IK trees
* - this is not integrated as an IK plugin, since it should be able
@@ -2324,15 +2310,15 @@ void BKE_pose_where_is(Scene *scene, Object *ob)
for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
/* 4a. if we find an IK root, we handle it separated */
if (pchan->flag & POSE_IKTREE) {
- BIK_execute_tree(scene, ob, pchan, ctime);
+ BIK_execute_tree(eval_ctx, scene, ob, pchan, ctime);
}
/* 4b. if we find a Spline IK root, we handle it separated too */
else if (pchan->flag & POSE_IKSPLINE) {
- BKE_splineik_execute_tree(scene, ob, pchan, ctime);
+ BKE_splineik_execute_tree(eval_ctx, scene, ob, pchan, ctime);
}
/* 5. otherwise just call the normal solver */
else if (!(pchan->flag & POSE_DONE)) {
- BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1);
+ BKE_pose_where_is_bone(eval_ctx, scene, ob, pchan, ctime, 1);
}
}
/* 6. release the IK tree */
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
index aac9cfdf792..1b8bf3feb10 100644
--- a/source/blender/blenkernel/intern/armature_update.c
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -41,7 +41,6 @@
#include "BKE_anim.h"
#include "BKE_armature.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_displist.h"
#include "BKE_fcurve.h"
#include "BKE_scene.h"
@@ -51,13 +50,7 @@
#include "BKE_global.h"
#include "BKE_main.h"
-#include "DEG_depsgraph.h"
-
-#ifdef WITH_LEGACY_DEPSGRAPH
-# define DEBUG_PRINT if (!DEG_depsgraph_use_legacy() && G.debug & G_DEBUG_DEPSGRAPH) printf
-#else
-# define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
-#endif
+#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
/* ********************** SPLINE IK SOLVER ******************* */
@@ -120,9 +113,11 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos
* currently for paths to work it needs to go through the bevlist/displist system (ton)
*/
+ /* TODO: Make sure this doesn't crash. */
+#if 0
/* only happens on reload file, but violates depsgraph still... fix! */
if (ELEM(NULL, ikData->tar->curve_cache, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) {
- BKE_displist_make_curveTypes(scene, ikData->tar, 0);
+ BKE_displist_make_curveTypes(eval_ctx, scene, ikData->tar, 0);
/* path building may fail in EditMode after removing verts [#33268]*/
if (ELEM(NULL, ikData->tar->curve_cache->path, ikData->tar->curve_cache->path->data)) {
@@ -130,6 +125,9 @@ static void splineik_init_tree_from_pchan(Scene *scene, Object *UNUSED(ob), bPos
return;
}
}
+#else
+ (void) scene;
+#endif
}
/* find the root bone and the chain of bones from the root to the tip
@@ -268,15 +266,16 @@ static void splineik_init_tree(Scene *scene, Object *ob, float UNUSED(ctime))
/* ----------- */
/* Evaluate spline IK for a given bone */
-static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *ob, bPoseChannel *pchan,
- int index, float ctime)
+static void splineik_evaluate_bone(
+ const struct EvaluationContext *eval_ctx, tSplineIK_Tree *tree, Scene *scene, Object *ob, bPoseChannel *pchan,
+ int index, float ctime)
{
bSplineIKConstraint *ikData = tree->ikData;
float poseHead[3], poseTail[3], poseMat[4][4];
float splineVec[3], scaleFac, radius = 1.0f;
/* firstly, calculate the bone matrix the standard way, since this is needed for roll control */
- BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1);
+ BKE_pose_where_is_bone(eval_ctx, scene, ob, pchan, ctime, 1);
copy_v3_v3(poseHead, pchan->pose_head);
copy_v3_v3(poseTail, pchan->pose_tail);
@@ -518,7 +517,7 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o
}
/* Evaluate the chain starting from the nominated bone */
-static void splineik_execute_tree(Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime)
+static void splineik_execute_tree(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime)
{
tSplineIK_Tree *tree;
@@ -532,7 +531,7 @@ static void splineik_execute_tree(Scene *scene, Object *ob, bPoseChannel *pchan_
*/
for (i = tree->chainlen - 1; i >= 0; i--) {
bPoseChannel *pchan = tree->chain[i];
- splineik_evaluate_bone(tree, scene, ob, pchan, i, ctime);
+ splineik_evaluate_bone(eval_ctx, tree, scene, ob, pchan, i, ctime);
}
/* free the tree info specific to SplineIK trees now */
@@ -551,14 +550,16 @@ void BKE_pose_splineik_init_tree(Scene *scene, Object *ob, float ctime)
splineik_init_tree(scene, ob, ctime);
}
-void BKE_splineik_execute_tree(Scene *scene, Object *ob, bPoseChannel *pchan_root, float ctime)
+void BKE_splineik_execute_tree(
+ const struct EvaluationContext *eval_ctx, Scene *scene,
+ Object *ob, bPoseChannel *pchan_root, float ctime)
{
- splineik_execute_tree(scene, ob, pchan_root, ctime);
+ splineik_execute_tree(eval_ctx, scene, ob, pchan_root, ctime);
}
/* *************** Depsgraph evaluation callbacks ************ */
-void BKE_pose_eval_init(EvaluationContext *UNUSED(eval_ctx),
+void BKE_pose_eval_init(const struct EvaluationContext *UNUSED(eval_ctx),
Scene *UNUSED(scene),
Object *ob,
bPose *pose)
@@ -582,7 +583,7 @@ void BKE_pose_eval_init(EvaluationContext *UNUSED(eval_ctx),
}
}
-void BKE_pose_eval_init_ik(EvaluationContext *UNUSED(eval_ctx),
+void BKE_pose_eval_init_ik(const struct EvaluationContext *eval_ctx,
Scene *scene,
Object *ob,
bPose *UNUSED(pose))
@@ -592,7 +593,7 @@ void BKE_pose_eval_init_ik(EvaluationContext *UNUSED(eval_ctx),
DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
/* 2a. construct the IK tree (standard IK) */
- BIK_initialize_tree(scene, ob, ctime);
+ BIK_initialize_tree(eval_ctx, scene, ob, ctime);
/* 2b. construct the Spline IK trees
* - this is not integrated as an IK plugin, since it should be able
@@ -601,7 +602,7 @@ void BKE_pose_eval_init_ik(EvaluationContext *UNUSED(eval_ctx),
BKE_pose_splineik_init_tree(scene, ob, ctime);
}
-void BKE_pose_eval_bone(EvaluationContext *UNUSED(eval_ctx),
+void BKE_pose_eval_bone(const struct EvaluationContext *eval_ctx,
Scene *scene,
Object *ob,
bPoseChannel *pchan)
@@ -629,14 +630,14 @@ void BKE_pose_eval_bone(EvaluationContext *UNUSED(eval_ctx),
if ((pchan->flag & POSE_DONE) == 0) {
/* TODO(sergey): Use time source node for time. */
float ctime = BKE_scene_frame_get(scene); /* not accurate... */
- BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1);
+ BKE_pose_where_is_bone(eval_ctx, scene, ob, pchan, ctime, 1);
}
}
}
}
}
-void BKE_pose_constraints_evaluate(EvaluationContext *UNUSED(eval_ctx),
+void BKE_pose_constraints_evaluate(const struct EvaluationContext *eval_ctx,
Scene *scene,
Object *ob,
bPoseChannel *pchan)
@@ -652,12 +653,12 @@ void BKE_pose_constraints_evaluate(EvaluationContext *UNUSED(eval_ctx),
else {
if ((pchan->flag & POSE_DONE) == 0) {
float ctime = BKE_scene_frame_get(scene); /* not accurate... */
- BKE_pose_where_is_bone(scene, ob, pchan, ctime, 1);
+ BKE_pose_where_is_bone(eval_ctx, scene, ob, pchan, ctime, 1);
}
}
}
-void BKE_pose_bone_done(EvaluationContext *UNUSED(eval_ctx),
+void BKE_pose_bone_done(const struct EvaluationContext *UNUSED(eval_ctx),
bPoseChannel *pchan)
{
float imat[4][4];
@@ -668,27 +669,27 @@ void BKE_pose_bone_done(EvaluationContext *UNUSED(eval_ctx),
}
}
-void BKE_pose_iktree_evaluate(EvaluationContext *UNUSED(eval_ctx),
+void BKE_pose_iktree_evaluate(const struct EvaluationContext *eval_ctx,
Scene *scene,
Object *ob,
bPoseChannel *rootchan)
{
float ctime = BKE_scene_frame_get(scene); /* not accurate... */
DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, rootchan->name);
- BIK_execute_tree(scene, ob, rootchan, ctime);
+ BIK_execute_tree(eval_ctx, scene, ob, rootchan, ctime);
}
-void BKE_pose_splineik_evaluate(EvaluationContext *UNUSED(eval_ctx),
+void BKE_pose_splineik_evaluate(const struct EvaluationContext *eval_ctx,
Scene *scene,
Object *ob,
bPoseChannel *rootchan)
{
float ctime = BKE_scene_frame_get(scene); /* not accurate... */
DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, rootchan->name);
- BKE_splineik_execute_tree(scene, ob, rootchan, ctime);
+ BKE_splineik_execute_tree(eval_ctx, scene, ob, rootchan, ctime);
}
-void BKE_pose_eval_flush(EvaluationContext *UNUSED(eval_ctx),
+void BKE_pose_eval_flush(const struct EvaluationContext *UNUSED(eval_ctx),
Scene *scene,
Object *ob,
bPose *UNUSED(pose))
@@ -699,11 +700,9 @@ void BKE_pose_eval_flush(EvaluationContext *UNUSED(eval_ctx),
/* 6. release the IK tree */
BIK_release_tree(scene, ob, ctime);
-
- ob->recalc &= ~OB_RECALC_ALL;
}
-void BKE_pose_eval_proxy_copy(EvaluationContext *UNUSED(eval_ctx), Object *ob)
+void BKE_pose_eval_proxy_copy(const struct EvaluationContext *UNUSED(eval_ctx), Object *ob)
{
BLI_assert(ID_IS_LINKED(ob) && ob->proxy_from != NULL);
DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
@@ -711,8 +710,4 @@ void BKE_pose_eval_proxy_copy(EvaluationContext *UNUSED(eval_ctx), Object *ob)
printf("Proxy copy error, lib Object: %s proxy Object: %s\n",
ob->id.name + 2, ob->proxy_from->id.name + 2);
}
- /* Rest of operations are NO-OP in depsgraph, so can clear
- * flag now.
- */
- ob->recalc &= ~OB_RECALC_ALL;
}
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index e8a3387c153..182b88c1c57 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -51,10 +51,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"
@@ -62,6 +62,8 @@
#include "BKE_screen.h"
#include "BKE_sequencer.h"
+#include "DEG_depsgraph.h"
+
#include "RE_pipeline.h"
#include "RE_render_ext.h"
@@ -87,7 +89,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();
@@ -96,6 +98,8 @@ void BKE_blender_free(void)
BKE_sequencer_cache_destruct();
IMB_moviecache_destruct();
+
+ BKE_layer_exit();
free_nodesystem();
}
@@ -280,11 +284,13 @@ void BKE_blender_userdef_app_template_data_swap(UserDef *userdef_a, UserDef *use
DATA_SWAP(font_path_ui_mono);
DATA_SWAP(keyconfigstr);
+ DATA_SWAP(manipulator_flag);
DATA_SWAP(app_flag);
/* We could add others. */
FLAG_SWAP(uiflag, int, USER_QUIT_PROMPT);
+#undef SWAP_TYPELESS
#undef DATA_SWAP
#undef LIST_SWAP
#undef FLAG_SWAP
diff --git a/source/blender/blenkernel/intern/blender_copybuffer.c b/source/blender/blenkernel/intern/blender_copybuffer.c
index e57524af546..b0c571bf159 100644
--- a/source/blender/blenkernel/intern/blender_copybuffer.c
+++ b/source/blender/blenkernel/intern/blender_copybuffer.c
@@ -44,12 +44,15 @@
#include "BKE_blender_copybuffer.h" /* own include */
#include "BKE_blendfile.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_scene.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "BLO_readfile.h"
#include "BLO_writefile.h"
@@ -117,7 +120,7 @@ bool BKE_copybuffer_paste(bContext *C, const char *libname, const short flag, Re
{
Main *bmain = CTX_data_main(C);
Scene *scene = CTX_data_scene(C);
- View3D *v3d = CTX_wm_view3d(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
Main *mainl = NULL;
Library *lib;
BlendHandle *bh;
@@ -129,7 +132,7 @@ bool BKE_copybuffer_paste(bContext *C, const char *libname, const short flag, Re
return false;
}
- BKE_scene_base_deselect_all(scene);
+ BKE_view_layer_base_deselect_all(view_layer);
/* tag everything, all untagged data can be made local
* its also generally useful to know what is new
@@ -142,7 +145,7 @@ bool BKE_copybuffer_paste(bContext *C, const char *libname, const short flag, Re
BLO_library_link_copypaste(mainl, bh);
- BLO_library_link_end(mainl, &bh, flag, scene, v3d);
+ BLO_library_link_end(mainl, &bh, flag, scene, view_layer);
/* mark all library linked objects to be updated */
BKE_main_lib_objects_recalc_all(bmain);
@@ -157,7 +160,11 @@ bool BKE_copybuffer_paste(bContext *C, const char *libname, const short flag, Re
BKE_main_id_tag_all(bmain, LIB_TAG_PRE_EXISTING, false);
/* recreate dependency graph to include new objects */
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
+
+ /* Tag update the scene to flush base collection settings, since the new object is added to a
+ * new (active) collection, not its original collection, thus need recalculation. */
+ DEG_id_tag_update(&scene->id, 0);
BLO_blendhandle_close(bh);
/* remove library... */
diff --git a/source/blender/blenkernel/intern/blender_undo.c b/source/blender/blenkernel/intern/blender_undo.c
index e3a5edb2049..b8f46756445 100644
--- a/source/blender/blenkernel/intern/blender_undo.c
+++ b/source/blender/blenkernel/intern/blender_undo.c
@@ -56,7 +56,6 @@
#include "BKE_appdir.h"
#include "BKE_brush.h"
#include "BKE_context.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_image.h"
#include "BKE_main.h"
@@ -66,6 +65,8 @@
#include "BLO_readfile.h"
#include "BLO_writefile.h"
+#include "DEG_depsgraph.h"
+
/* -------------------------------------------------------------------- */
/** \name Global Undo
@@ -118,7 +119,7 @@ static int read_undosave(bContext *C, UndoElem *uel)
if (success) {
/* important not to update time here, else non keyed tranforms are lost */
- DAG_on_visible_update(G.main, false);
+ DEG_on_visible_update(G.main, false);
}
return success;
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index cc992a4a520..8d61b6723c6 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -32,6 +32,7 @@
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
+#include "DNA_workspace_types.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
@@ -48,11 +49,13 @@
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_ipo.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
+#include "BKE_workspace.h"
#include "BLO_readfile.h"
#include "BLO_writefile.h"
@@ -93,7 +96,7 @@ static bool wm_scene_is_visible(wmWindowManager *wm, Scene *scene)
{
wmWindow *win;
for (win = wm->windows.first; win; win = win->next) {
- if (win->screen->scene == scene) {
+ if (win->scene == scene) {
return true;
}
}
@@ -163,17 +166,22 @@ static void setup_app_data(
* (otherwise we'd be undoing on an off-screen scene which isn't acceptable).
* see: T43424
*/
+ wmWindow *win;
bScreen *curscreen = NULL;
+ ViewLayer *cur_view_layer;
bool track_undo_scene;
/* comes from readfile.c */
SWAP(ListBase, G.main->wm, bfd->main->wm);
+ SWAP(ListBase, G.main->workspaces, bfd->main->workspaces);
SWAP(ListBase, G.main->screen, bfd->main->screen);
- /* we re-use current screen */
+ /* we re-use current window and screen */
+ win = CTX_wm_window(C);
curscreen = CTX_wm_screen(C);
- /* but use new Scene pointer */
+ /* but use Scene pointer from new file */
curscene = bfd->curscene;
+ cur_view_layer = bfd->cur_view_layer;
track_undo_scene = (mode == LOAD_UNDO && curscreen && curscene && bfd->main->wm.first);
@@ -184,34 +192,41 @@ static void setup_app_data(
if (curscene == NULL) {
curscene = BKE_scene_add(bfd->main, "Empty");
}
+ if (cur_view_layer == NULL) {
+ /* fallback to scene layer */
+ cur_view_layer = BKE_view_layer_from_scene_get(curscene);
+ }
if (track_undo_scene) {
/* keep the old (free'd) scene, let 'blo_lib_link_screen_restore'
* replace it with 'curscene' if its needed */
}
- else {
- /* and we enforce curscene to be in current screen */
- if (curscreen) {
- /* can run in bgmode */
- curscreen->scene = curscene;
- }
+ /* and we enforce curscene to be in current screen */
+ else if (win) { /* can run in bgmode */
+ win->scene = curscene;
}
/* BKE_blender_globals_clear will free G.main, here we can still restore pointers */
- blo_lib_link_screen_restore(bfd->main, curscreen, curscene);
- /* curscreen might not be set when loading without ui (see T44217) so only re-assign if available */
- if (curscreen) {
- curscene = curscreen->scene;
+ blo_lib_link_restore(bfd->main, CTX_wm_manager(C), curscene, cur_view_layer);
+ if (win) {
+ curscene = win->scene;
}
if (track_undo_scene) {
wmWindowManager *wm = bfd->main->wm.first;
if (wm_scene_is_visible(wm, bfd->curscene) == false) {
curscene = bfd->curscene;
- curscreen->scene = curscene;
- BKE_screen_view3d_scene_sync(curscreen);
+ win->scene = curscene;
+ BKE_screen_view3d_scene_sync(curscreen, curscene);
}
}
+
+ /* We need to tag this here because events may be handled immediately after.
+ * only the current screen is important because we wont have to handle
+ * events from multiple screens at once.*/
+ {
+ BKE_screen_manipulator_tag_refresh(curscreen);
+ }
}
/* free G.main Main database */
@@ -226,6 +241,7 @@ static void setup_app_data(
CTX_data_main_set(C, G.main);
if (bfd->user) {
+
/* only here free userdef themes... */
BKE_blender_userdef_data_set_and_free(bfd->user);
bfd->user = NULL;
@@ -261,12 +277,14 @@ static void setup_app_data(
/* this can happen when active scene was lib-linked, and doesn't exist anymore */
if (CTX_data_scene(C) == NULL) {
+ wmWindow *win = CTX_wm_window(C);
+
/* in case we don't even have a local scene, add one */
if (!G.main->scene.first)
BKE_scene_add(G.main, "Empty");
CTX_data_scene_set(C, G.main->scene.first);
- CTX_wm_screen(C)->scene = CTX_data_scene(C);
+ win->scene = CTX_data_scene(C);
curscene = CTX_data_scene(C);
}
@@ -315,20 +333,27 @@ static void setup_app_data(
wmWindowManager *wm = G.main->wm.first;
if (wm) {
- wmWindow *win;
-
- for (win = wm->windows.first; win; win = win->next) {
- if (win->screen && win->screen->scene) /* zealous check... */
- if (win->screen->scene != curscene)
- BKE_scene_set_background(G.main, win->screen->scene);
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ if (win->scene && win->scene != curscene) {
+ BKE_scene_set_background(G.main, win->scene);
+ }
}
}
}
+
+ /* Setting scene might require having a dependency graph, with copy on write
+ * we need to make sure we ensure scene has correct color management before
+ * constructing dependency graph.
+ */
+ if (mode != LOAD_UNDO) {
+ IMB_colormanagement_check_file_config(G.main);
+ }
+
BKE_scene_set_background(G.main, curscene);
if (mode != LOAD_UNDO) {
+ /* TODO(sergey): Can this be also move above? */
RE_FreeAllPersistentData();
- IMB_colormanagement_check_file_config(G.main);
}
MEM_freeN(bfd);
@@ -534,6 +559,48 @@ bool BKE_blendfile_userdef_write_app_template(const char *filepath, ReportList *
return ok;
}
+WorkspaceConfigFileData *BKE_blendfile_workspace_config_read(const char *filepath, ReportList *reports)
+{
+ BlendFileData *bfd;
+ WorkspaceConfigFileData *workspace_config = NULL;
+
+ bfd = BLO_read_from_file(filepath, reports, BLO_READ_SKIP_USERDEF);
+ if (bfd) {
+ workspace_config = MEM_mallocN(sizeof(*workspace_config), __func__);
+ workspace_config->main = bfd->main;
+ workspace_config->workspaces = bfd->main->workspaces;
+
+ MEM_freeN(bfd);
+ }
+
+ return workspace_config;
+}
+
+bool BKE_blendfile_workspace_config_write(Main *bmain, const char *filepath, ReportList *reports)
+{
+ int fileflags = G.fileflags & ~(G_FILE_NO_UI | G_FILE_AUTOPLAY | G_FILE_HISTORY);
+ bool retval = false;
+
+ BKE_blendfile_write_partial_begin(bmain);
+
+ for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
+ BKE_blendfile_write_partial_tag_ID(&workspace->id, true);
+ }
+
+ if (BKE_blendfile_write_partial(bmain, filepath, fileflags, reports)) {
+ retval = true;
+ }
+
+ BKE_blendfile_write_partial_end(bmain);
+
+ return retval;
+}
+
+void BKE_blendfile_workspace_config_data_free(WorkspaceConfigFileData *workspace_config)
+{
+ BKE_main_free(workspace_config->main);
+ MEM_freeN(workspace_config);
+}
/** \} */
diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c
index 7ca4e07076d..8c78787c259 100644
--- a/source/blender/blenkernel/intern/boids.c
+++ b/source/blender/blenkernel/intern/boids.c
@@ -132,6 +132,7 @@ static int rule_goal_avoid(BoidRule *rule, BoidBrainData *bbd, BoidValues *val,
if (eff == NULL && gabr->ob) {
memset(&temp_eff, 0, sizeof(EffectorCache));
temp_eff.ob = gabr->ob;
+ temp_eff.eval_ctx = bbd->sim->eval_ctx;
temp_eff.scene = bbd->sim->scene;
eff = &temp_eff;
get_effector_data(eff, &efd, &epoint, 0);
diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c
index e821a14da2e..f8215668034 100644
--- a/source/blender/blenkernel/intern/cachefile.c
+++ b/source/blender/blenkernel/intern/cachefile.c
@@ -176,7 +176,7 @@ void BKE_cachefile_update_frame(Main *bmain, Scene *scene, const float ctime, co
const float time = BKE_cachefile_time_offset(cache_file, ctime, fps);
if (BKE_cachefile_filepath_get(bmain, cache_file, time, filename)) {
- BKE_cachefile_clean(scene, cache_file);
+ BKE_cachefile_clean(bmain, cache_file);
#ifdef WITH_ALEMBIC
ABC_free_handle(cache_file->handle);
cache_file->handle = ABC_create_handle(filename, NULL);
@@ -217,11 +217,9 @@ float BKE_cachefile_time_offset(CacheFile *cache_file, const float time, const f
}
/* TODO(kevin): replace this with some depsgraph mechanism, or something similar. */
-void BKE_cachefile_clean(Scene *scene, CacheFile *cache_file)
+void BKE_cachefile_clean(struct Main *bmain, CacheFile *cache_file)
{
- for (Base *base = scene->base.first; base; base = base->next) {
- Object *ob = base->object;
-
+ for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache);
if (md) {
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index 719125b3317..4993caf14f1 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -40,6 +40,7 @@
#include "DNA_ID.h"
#include "BLI_math.h"
+#include "BLI_listbase.h"
#include "BLI_rect.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
@@ -48,6 +49,7 @@
#include "BKE_camera.h"
#include "BKE_object.h"
#include "BKE_global.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_library_remap.h"
@@ -55,6 +57,8 @@
#include "BKE_scene.h"
#include "BKE_screen.h"
+#include "MEM_guardedalloc.h"
+
#include "GPU_compositing.h"
/****************************** Camera Datablock *****************************/
@@ -101,9 +105,19 @@ void *BKE_camera_add(Main *bmain, const char *name)
*
* \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
*/
-void BKE_camera_copy_data(Main *UNUSED(bmain), Camera *UNUSED(cam_dst), const Camera *UNUSED(cam_src), const int UNUSED(flag))
+void BKE_camera_copy_data(Main *UNUSED(bmain), Camera *cam_dst, const Camera *cam_src, const int flag)
{
- /* Nothing to do! */
+ BLI_duplicatelist(&cam_dst->bg_images, &cam_src->bg_images);
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ for (CameraBGImage *bgpic = cam_dst->bg_images.first; bgpic; bgpic = bgpic->next) {
+ if (bgpic->source == CAM_BGIMG_SOURCE_IMAGE) {
+ id_us_plus((ID *)bgpic->ima);
+ }
+ else if (bgpic->source == CAM_BGIMG_SOURCE_MOVIE) {
+ id_us_plus((ID *)bgpic->clip);
+ }
+ }
+ }
}
Camera *BKE_camera_copy(Main *bmain, const Camera *cam)
@@ -121,6 +135,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);
}
@@ -642,7 +666,7 @@ static bool camera_frame_fit_calc_from_data(
/* don't move the camera, just yield the fit location */
/* r_scale only valid/useful for ortho cameras */
bool BKE_camera_view_frame_fit_to_scene(
- Scene *scene, struct View3D *v3d, Object *camera_ob, float r_co[3], float *r_scale)
+ Scene *scene, ViewLayer *view_layer, Object *camera_ob, float r_co[3], float *r_scale)
{
CameraParams params;
CameraViewFrameData data_cb;
@@ -653,7 +677,7 @@ bool BKE_camera_view_frame_fit_to_scene(
camera_frame_fit_data_init(scene, camera_ob, &params, &data_cb);
/* run callback on all visible points */
- BKE_scene_foreach_display_point(scene, v3d, BA_SELECT, camera_to_frame_view_cb, &data_cb);
+ BKE_scene_foreach_display_point(scene, view_layer, camera_to_frame_view_cb, &data_cb);
return camera_frame_fit_calc_from_data(&params, &data_cb, r_co, r_scale);
}
@@ -862,9 +886,9 @@ static Object *camera_multiview_advanced(Scene *scene, Object *camera, const cha
}
if (name[0] != '\0') {
- Base *base = BKE_scene_base_find_by_name(scene, name);
- if (base) {
- return base->object;
+ Object *ob = BKE_scene_object_find_by_name(scene, name);
+ if (ob != NULL) {
+ return ob;
}
}
@@ -961,3 +985,38 @@ void BKE_camera_to_gpu_dof(struct Object *camera, struct GPUFXSettings *r_fx_set
r_fx_settings->dof->focus_distance = BKE_camera_object_dof_distance(camera);
}
}
+
+CameraBGImage *BKE_camera_background_image_new(Camera *cam)
+{
+ CameraBGImage *bgpic = MEM_callocN(sizeof(CameraBGImage), "Background Image");
+
+ bgpic->scale = 1.0f;
+ bgpic->alpha = 0.5f;
+ bgpic->iuser.fie_ima = 2;
+ bgpic->iuser.ok = 1;
+ bgpic->flag |= CAM_BGIMG_FLAG_EXPANDED;
+
+ BLI_addtail(&cam->bg_images, bgpic);
+
+ return bgpic;
+}
+
+void BKE_camera_background_image_remove(Camera *cam, CameraBGImage *bgpic)
+{
+ BLI_remlink(&cam->bg_images, bgpic);
+
+ MEM_freeN(bgpic);
+}
+
+void BKE_camera_background_image_clear(Camera *cam)
+{
+ CameraBGImage *bgpic = cam->bg_images.first;
+
+ while (bgpic) {
+ CameraBGImage *next_bgpic = bgpic->next;
+
+ BKE_camera_background_image_remove(cam, bgpic);
+
+ bgpic = next_bgpic;
+ }
+}
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index d3b106835ef..ea54548ab09 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -60,6 +60,7 @@
#include "GPU_buffers.h"
#include "GPU_draw.h"
#include "GPU_glew.h"
+#include "GPU_immediate.h"
#include "GPU_shader.h"
#include "GPU_basic_shader.h"
@@ -376,40 +377,10 @@ static void cdDM_drawVerts(DerivedMesh *dm)
GPU_buffers_unbind();
}
-static void cdDM_drawUVEdges(DerivedMesh *dm)
+static void cdDM_drawEdges(DerivedMesh *dm, bool UNUSED(drawLooseEdges), bool UNUSED(drawAllEdges))
{
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
- const MPoly *mpoly = cddm->mpoly;
- int totpoly = dm->getNumPolys(dm);
- int prevstart = 0;
- bool prevdraw = true;
- int curpos = 0;
- int i;
-
- GPU_uvedge_setup(dm);
- for (i = 0; i < totpoly; i++, mpoly++) {
- const bool draw = (mpoly->flag & ME_HIDE) == 0;
-
- if (prevdraw != draw) {
- if (prevdraw && (curpos != prevstart)) {
- glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
- }
- prevstart = curpos;
- }
- curpos += 2 * mpoly->totloop;
- prevdraw = draw;
- }
- if (prevdraw && (curpos != prevstart)) {
- glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
- }
- GPU_buffers_unbind();
-}
-
-static void cdDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdges)
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
- GPUDrawObject *gdo;
if (cddm->pbvh && cddm->pbvh_draw &&
BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH)
{
@@ -417,22 +388,37 @@ static void cdDM_drawEdges(DerivedMesh *dm, bool drawLooseEdges, bool drawAllEdg
return;
}
-
- GPU_edge_setup(dm);
- gdo = dm->drawObject;
- if (gdo->edges && gdo->points) {
- if (drawAllEdges && drawLooseEdges) {
- GPU_buffer_draw_elements(gdo->edges, GL_LINES, 0, gdo->totedge * 2);
- }
- else if (drawAllEdges) {
- GPU_buffer_draw_elements(gdo->edges, GL_LINES, 0, gdo->loose_edge_offset * 2);
- }
- else {
- GPU_buffer_draw_elements(gdo->edges, GL_LINES, 0, gdo->tot_edge_drawn * 2);
- GPU_buffer_draw_elements(gdo->edges, GL_LINES, gdo->loose_edge_offset * 2, dm->drawObject->tot_loose_edge_drawn * 2);
+
+ MVert *vert = cddm->mvert;
+ MEdge *edge = cddm->medge;
+
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+
+ /* NOTE: This is active object color, which is not really perfect.
+ * But we can't query color set by glColor() :(
+ */
+ float color[4] = {1.0f, 0.667f, 0.251f, 1.0f};
+
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+ immUniformColor4fv(color);
+
+ const int chunk_size = 1024;
+ const int num_chunks = (dm->numEdgeData + chunk_size - 1) / chunk_size;
+
+ for (int chunk = 0; chunk < num_chunks; ++chunk) {
+ const int num_current_edges = (chunk < num_chunks - 1)
+ ? chunk_size
+ : dm->numEdgeData - chunk_size * (num_chunks - 1);
+ immBeginAtMost(GWN_PRIM_LINES, num_current_edges * 2);
+ for (int i = 0; i < num_current_edges; i++, edge++) {
+ immVertex3fv(pos, vert[edge->v1].co);
+ immVertex3fv(pos, vert[edge->v2].co);
}
+ immEnd();
}
- GPU_buffers_unbind();
+
+ immUnbindProgram();
}
static void cdDM_drawLooseEdges(DerivedMesh *dm)
@@ -455,8 +441,9 @@ static void cdDM_drawLooseEdges(DerivedMesh *dm)
static void cdDM_drawFacesSolid(
DerivedMesh *dm,
float (*partial_redraw_planes)[4],
- bool UNUSED(fast), DMSetMaterial setMaterial)
+ bool fast, DMSetMaterial setMaterial)
{
+ UNUSED_VARS(partial_redraw_planes, fast, setMaterial);
CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
int a;
@@ -469,177 +456,79 @@ static void cdDM_drawFacesSolid(
return;
}
}
-
- GPU_vertex_setup(dm);
- GPU_normal_setup(dm);
- GPU_triangle_setup(dm);
- for (a = 0; a < dm->drawObject->totmaterial; a++) {
- if (!setMaterial || setMaterial(dm->drawObject->materials[a].mat_nr + 1, NULL)) {
- GPU_buffer_draw_elements(
- dm->drawObject->triangles, GL_TRIANGLES,
- dm->drawObject->materials[a].start, dm->drawObject->materials[a].totelements);
- }
- }
- GPU_buffers_unbind();
-}
-static void cdDM_drawFacesTex_common(
- DerivedMesh *dm,
- DMSetDrawOptionsTex drawParams,
- DMSetDrawOptionsMappedTex drawParamsMapped,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag flag)
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *) dm;
+ const MVert *mvert = cddm->mvert;
+ const MLoop *mloop = cddm->mloop;
const MPoly *mpoly = cddm->mpoly;
- MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
- const MLoopCol *mloopcol = NULL;
- int i;
- int colType, start_element, tot_drawn;
- const bool use_hide = (flag & DM_DRAW_SKIP_HIDDEN) != 0;
- const bool use_tface = (flag & DM_DRAW_USE_ACTIVE_UV) != 0;
- const bool use_colors = (flag & DM_DRAW_USE_COLORS) != 0;
- int totpoly;
- int next_actualFace;
- int mat_index;
- int tot_element;
-
- /* double lookup */
- const int *index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
-
- /* TODO: not entirely correct, but currently dynamic topology will
- * destroy UVs anyway, so textured display wouldn't work anyway
- *
- * this will do more like solid view with lights set up for
- * textured view, but object itself will be displayed gray
- * (the same as it'll display without UV maps in textured view)
- */
- if (cddm->pbvh) {
- if (cddm->pbvh_draw &&
- BKE_pbvh_type(cddm->pbvh) == PBVH_BMESH &&
- BKE_pbvh_has_faces(cddm->pbvh))
- {
- GPU_set_tpage(NULL, false, false);
- BKE_pbvh_draw(cddm->pbvh, NULL, NULL, NULL, false, false);
- return;
- }
- else {
- cdDM_update_normals_from_pbvh(dm);
- }
- }
+ const int num_looptris = dm->getNumLoopTri(dm);
+ const MLoopTri *looptri = dm->getLoopTriArray(dm);
+ const float (*nors)[3] = dm->getPolyDataArray(dm, CD_NORMAL);
+ const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
- if (use_colors) {
- colType = CD_TEXTURE_MLOOPCOL;
- mloopcol = dm->getLoopDataArray(dm, colType);
- if (!mloopcol) {
- colType = CD_PREVIEW_MLOOPCOL;
- mloopcol = dm->getLoopDataArray(dm, colType);
- }
- if (!mloopcol) {
- colType = CD_MLOOPCOL;
- mloopcol = dm->getLoopDataArray(dm, colType);
- }
- }
+ Gwn_VertFormat *format = immVertexFormat();
+ unsigned int pos = GWN_vertformat_attr_add(format, "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ unsigned int nor = GWN_vertformat_attr_add(format, "nor", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
- GPU_vertex_setup(dm);
- GPU_normal_setup(dm);
- GPU_triangle_setup(dm);
- if (flag & DM_DRAW_USE_TEXPAINT_UV)
- GPU_texpaint_uv_setup(dm);
- else
- GPU_uv_setup(dm);
- if (mloopcol) {
- GPU_color_setup(dm, colType);
- }
+ float color[4] = {0.8f, 0.8f, 0.8f, 1.0f};
+ const float light_vec[3] = {0.0f, 0.0f, 1.0f};
- /* lastFlag = 0; */ /* UNUSED */
- for (mat_index = 0; mat_index < dm->drawObject->totmaterial; mat_index++) {
- GPUBufferMaterial *bufmat = dm->drawObject->materials + mat_index;
- next_actualFace = bufmat->polys[0];
- totpoly = bufmat->totpolys;
+ immBindBuiltinProgram(GPU_SHADER_SIMPLE_LIGHTING);
+ immUniformColor4fv(color);
+ immUniform3fv("light", light_vec);
- tot_element = 0;
- tot_drawn = 0;
- start_element = 0;
+ const int chunk_size = 1024;
+ const int num_chunks = (num_looptris + chunk_size - 1) / chunk_size;
- for (i = 0; i < totpoly; i++) {
- int actualFace = bufmat->polys[i];
- DMDrawOption draw_option = DM_DRAW_OPTION_NORMAL;
- int flush = 0;
- int tot_tri_verts;
+ for (int chunk = 0; chunk < num_chunks; ++chunk) {
+ const int num_current_looptris = (chunk < num_chunks - 1)
+ ? chunk_size
+ : num_looptris - chunk_size * (num_chunks - 1);
- if (i != totpoly - 1)
- next_actualFace = bufmat->polys[i + 1];
+ immBeginAtMost(GWN_PRIM_TRIS, num_current_looptris * 3);
- if (use_hide && (mpoly[actualFace].flag & ME_HIDE)) {
- draw_option = DM_DRAW_OPTION_SKIP;
- }
- else if (drawParams) {
- MTexPoly *tp = use_tface && mtexpoly ? &mtexpoly[actualFace] : NULL;
- draw_option = drawParams(tp, (mloopcol != NULL), mpoly[actualFace].mat_nr);
- }
- else {
- if (index_mp_to_orig) {
- const int orig = index_mp_to_orig[actualFace];
- if (orig == ORIGINDEX_NONE) {
- /* XXX, this is not really correct
- * it will draw the previous faces context for this one when we don't know its settings.
- * but better then skipping it altogether. - campbell */
- draw_option = DM_DRAW_OPTION_NORMAL;
- }
- else if (drawParamsMapped) {
- draw_option = drawParamsMapped(userData, orig, mpoly[actualFace].mat_nr);
- }
+ for (a = 0; a < num_current_looptris; a++, looptri++) {
+ const MPoly *mp = &mpoly[looptri->poly];
+ const bool smoothnormal = (lnors != NULL) || (mp->flag & ME_SMOOTH);
+ const unsigned int vtri[3] = {mloop[looptri->tri[0]].v,
+ mloop[looptri->tri[1]].v,
+ mloop[looptri->tri[2]].v};
+ const unsigned int *ltri = looptri->tri;
+ float normals[3][3];
+ if (!smoothnormal) {
+ if (nors != NULL) {
+ copy_v3_v3(normals[0], nors[looptri->poly]);
}
- else if (drawParamsMapped) {
- draw_option = drawParamsMapped(userData, actualFace, mpoly[actualFace].mat_nr);
+ else {
+ normal_tri_v3(normals[0],
+ mvert[vtri[0]].co,
+ mvert[vtri[1]].co,
+ mvert[vtri[2]].co);
}
+ copy_v3_v3(normals[1], normals[0]);
+ copy_v3_v3(normals[2], normals[0]);
}
-
- /* flush buffer if current triangle isn't drawable or it's last triangle */
- flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == totpoly - 1);
-
- if (!flush && compareDrawOptions) {
- /* also compare draw options and flush buffer if they're different
- * need for face selection highlight in edit mode */
- flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
- }
-
- tot_tri_verts = ME_POLY_TRI_TOT(&mpoly[actualFace]) * 3;
- tot_element += tot_tri_verts;
-
- if (flush) {
- if (draw_option != DM_DRAW_OPTION_SKIP)
- tot_drawn += tot_tri_verts;
-
- if (tot_drawn) {
- if (mloopcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
- GPU_color_switch(1);
- else
- GPU_color_switch(0);
-
- GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, bufmat->start + start_element, tot_drawn);
- tot_drawn = 0;
- }
- start_element = tot_element;
+ else if (lnors != NULL) {
+ copy_v3_v3(normals[0], lnors[ltri[0]]);
+ copy_v3_v3(normals[1], lnors[ltri[1]]);
+ copy_v3_v3(normals[2], lnors[ltri[2]]);
}
else {
- tot_drawn += tot_tri_verts;
+ normal_short_to_float_v3(normals[0], mvert[vtri[0]].no);
+ normal_short_to_float_v3(normals[1], mvert[vtri[1]].no);
+ normal_short_to_float_v3(normals[2], mvert[vtri[2]].no);
}
+
+ immAttrib3fv(nor, normals[0]);
+ immVertex3fv(pos, mvert[vtri[0]].co);
+ immAttrib3fv(nor, normals[1]);
+ immVertex3fv(pos, mvert[vtri[1]].co);
+ immAttrib3fv(nor, normals[2]);
+ immVertex3fv(pos, mvert[vtri[2]].co);
}
+ immEnd();
}
- GPU_buffers_unbind();
-
-}
-
-static void cdDM_drawFacesTex(
- DerivedMesh *dm,
- DMSetDrawOptionsTex setDrawOptions,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag flag)
-{
- cdDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData, flag);
+ immUnbindProgram();
}
static void cdDM_drawMappedFaces(
@@ -851,15 +740,6 @@ static void cdDM_drawMappedFaces(
}
-static void cdDM_drawMappedFacesTex(
- DerivedMesh *dm,
- DMSetDrawOptionsMappedTex setDrawOptions,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag flag)
-{
- cdDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag);
-}
-
static void cddm_draw_attrib_vertex(
DMVertexAttribs *attribs, const MVert *mvert, int a, int index, int loop, int vert,
const float *lnor, const bool smoothnormal)
@@ -1913,7 +1793,7 @@ void CDDM_recalc_tessellation_ex(DerivedMesh *dm, const bool do_face_nor_cpy)
/* Tessellation recreated faceData, and the active layer indices need to get re-propagated
* from loops and polys to faces */
- CustomData_bmesh_update_active_layers(&dm->faceData, &dm->polyData, &dm->loopData);
+ CustomData_bmesh_update_active_layers(&dm->faceData, &dm->loopData);
}
void CDDM_recalc_tessellation(DerivedMesh *dm)
@@ -2007,16 +1887,13 @@ static CDDerivedMesh *cdDM_create(const char *desc)
dm->drawVerts = cdDM_drawVerts;
- dm->drawUVEdges = cdDM_drawUVEdges;
dm->drawEdges = cdDM_drawEdges;
dm->drawLooseEdges = cdDM_drawLooseEdges;
dm->drawMappedEdges = cdDM_drawMappedEdges;
dm->drawFacesSolid = cdDM_drawFacesSolid;
- dm->drawFacesTex = cdDM_drawFacesTex;
dm->drawFacesGLSL = cdDM_drawFacesGLSL;
dm->drawMappedFaces = cdDM_drawMappedFaces;
- dm->drawMappedFacesTex = cdDM_drawMappedFacesTex;
dm->drawMappedFacesGLSL = cdDM_drawMappedFacesGLSL;
dm->drawMappedFacesMat = cdDM_drawMappedFacesMat;
@@ -2153,7 +2030,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 +2044,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 +2109,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 +2139,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 +2211,7 @@ static DerivedMesh *cddm_from_bmesh_ex(
/* map mfaces to polygons in the same cddm intentionally */
*index++ = BM_elem_index_get(efa);
- loops_to_customdata_corners(bm, &dm->faceData, i, l, numCol, numTex);
+ loops_to_customdata_corners(bm, &dm->faceData, i, l, numCol, numUV);
test_index_face(mf, &dm->faceData, i, 3);
}
}
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index dd93606a67c..09b793629f7 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -345,7 +345,7 @@ static int do_init_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
return 1;
}
-static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *result, int framenr)
+static int do_step_cloth(const struct EvaluationContext *eval_ctx, Object *ob, ClothModifierData *clmd, DerivedMesh *result, int framenr)
{
ClothVertex *verts = NULL;
Cloth *cloth;
@@ -370,7 +370,7 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
mul_m4_v3(ob->obmat, verts->xconst);
}
- effectors = pdInitEffectors(clmd->scene, ob, NULL, clmd->sim_parms->effector_weights, true);
+ effectors = pdInitEffectors(eval_ctx, clmd->scene, ob, NULL, clmd->sim_parms->effector_weights, true);
if (clmd->sim_parms->flags & CLOTH_SIMSETTINGS_FLAG_DYNAMIC_BASEMESH )
cloth_update_verts ( ob, clmd, result );
@@ -400,7 +400,7 @@ static int do_step_cloth(Object *ob, ClothModifierData *clmd, DerivedMesh *resul
/************************************************
* clothModifier_do - main simulation function
************************************************/
-void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, DerivedMesh *dm, float (*vertexCos)[3])
+void clothModifier_do(ClothModifierData *clmd, const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, DerivedMesh *dm, float (*vertexCos)[3])
{
PointCache *cache;
PTCacheID pid;
@@ -478,7 +478,6 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived
return;
}
- if (!can_simulate)
return;
/* if on second frame, write cache for first frame */
@@ -490,7 +489,7 @@ void clothModifier_do(ClothModifierData *clmd, Scene *scene, Object *ob, Derived
/* do simulation */
BKE_ptcache_validate(cache, framenr);
- if (!do_step_cloth(ob, clmd, dm, framenr)) {
+ if (!do_step_cloth(eval_ctx, ob, clmd, dm, framenr)) {
BKE_ptcache_invalidate(cache);
}
else
@@ -922,7 +921,7 @@ static void cloth_from_mesh ( ClothModifierData *clmd, DerivedMesh *dm )
}
/***************************************************************************************
- * SPRING NETWORK BUILDING IMPLEMENTATION BEGIN
+ * SPRING NETWORK GWN_BATCH_BUILDING IMPLEMENTATION BEGIN
***************************************************************************************/
BLI_INLINE void spring_verts_ordered_set(ClothSpring *spring, int v0, int v1)
@@ -1504,6 +1503,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..6846683fe13
--- /dev/null
+++ b/source/blender/blenkernel/intern/collection.c
@@ -0,0 +1,848 @@
+/*
+ * ***** 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 "BLT_translation.h"
+#include "BLI_string_utils.h"
+
+#include "BKE_collection.h"
+#include "BKE_group.h"
+#include "BKE_idprop.h"
+#include "BKE_layer.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+
+#include "DNA_group_types.h"
+#include "DNA_ID.h"
+#include "DNA_layer_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "MEM_guardedalloc.h"
+
+/* Prototypes. */
+static SceneCollection *find_collection_parent(const struct SceneCollection *sc_child, struct SceneCollection *sc_parent);
+static bool is_collection_in_tree(const struct SceneCollection *sc_reference, struct SceneCollection *sc_parent);
+
+static SceneCollection *collection_master_from_id(const ID *owner_id)
+{
+ switch (GS(owner_id->name)) {
+ case ID_SCE:
+ return ((Scene *)owner_id)->collection;
+ case ID_GR:
+ return ((Group *)owner_id)->collection;
+ default:
+ BLI_assert(!"ID doesn't support collections");
+ return NULL;
+ }
+}
+
+/**
+ * Add a 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)
+{
+ SceneCollection *sc_master = collection_master_from_id(owner_id);
+ SceneCollection *sc = MEM_callocN(sizeof(SceneCollection), "New Collection");
+ sc->type = type;
+ const char *name = name_custom;
+
+ if (!sc_parent) {
+ sc_parent = sc_master;
+ }
+
+ if (!name) {
+ if (sc_parent == sc_master) {
+ name = BLI_sprintfN("Collection %d", BLI_listbase_count(&sc_master->scene_collections) + 1);
+ }
+ else {
+ name = BLI_sprintfN("%s %d", sc_parent->name, BLI_listbase_count(&sc_parent->scene_collections) + 1);
+ }
+ }
+
+ BLI_addtail(&sc_parent->scene_collections, sc);
+ BKE_collection_rename((Scene *)owner_id, sc, name);
+
+ BKE_layer_sync_new_scene_collection(owner_id, sc_parent, sc);
+
+ if (name != name_custom) {
+ MEM_freeN((char *)name);
+ }
+
+ return sc;
+}
+
+/**
+ * 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);
+ }
+ for (LinkData *link = sc->filter_objects.first; link; link = link->next) {
+ id_us_min(link->data);
+ }
+ }
+
+ BLI_freelistN(&sc->objects);
+ BLI_freelistN(&sc->filter_objects);
+
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+ collection_free(nsc, do_id_user);
+ }
+ BLI_freelistN(&sc->scene_collections);
+}
+
+/**
+ * Unlink the collection recursively
+ * \return true if unlinked.
+ */
+static bool collection_remlink(SceneCollection *sc_parent, SceneCollection *sc_gone)
+{
+ for (SceneCollection *sc = sc_parent->scene_collections.first; sc; sc = sc->next) {
+ if (sc == sc_gone) {
+ BLI_remlink(&sc_parent->scene_collections, sc_gone);
+ return true;
+ }
+
+ if (collection_remlink(sc, sc_gone)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Recursively remove any instance of this SceneCollection
+ */
+static void layer_collection_remove(ViewLayer *view_layer, ListBase *lb, const SceneCollection *sc)
+{
+ LayerCollection *lc = lb->first;
+ while (lc) {
+ if (lc->scene_collection == sc) {
+ BKE_layer_collection_free(view_layer, lc);
+ BLI_remlink(lb, lc);
+
+ LayerCollection *lc_next = lc->next;
+ MEM_freeN(lc);
+ lc = lc_next;
+
+ /* only the "top-level" layer collections may have the
+ * same SceneCollection in a sibling tree.
+ */
+ if (lb != &view_layer->layer_collections) {
+ return;
+ }
+ }
+
+ else {
+ layer_collection_remove(view_layer, &lc->layer_collections, sc);
+ lc = lc->next;
+ }
+ }
+}
+
+/**
+ * Remove a collection from the scene, and syncronize all render layers
+ *
+ * If an object is in any other collection, link the object to the master collection.
+ */
+bool BKE_collection_remove(ID *owner_id, SceneCollection *sc)
+{
+ SceneCollection *sc_master = collection_master_from_id(owner_id);
+
+ /* The master collection cannot be removed. */
+ if (sc == sc_master) {
+ return false;
+ }
+
+ /* We need to do bottom up removal, otherwise we get a crash when we remove a collection that
+ * has one of its nested collections linked to a view layer. */
+ SceneCollection *scene_collection_nested = sc->scene_collections.first;
+ while (scene_collection_nested != NULL) {
+ SceneCollection *scene_collection_next = scene_collection_nested->next;
+ BKE_collection_remove(owner_id, scene_collection_nested);
+ scene_collection_nested = scene_collection_next;
+ }
+
+ /* Unlink from the respective collection tree. */
+ if (!collection_remlink(sc_master, sc)) {
+ BLI_assert(false);
+ }
+
+ /* If an object is no longer in any collection, we add it to the master collection. */
+ ListBase collection_objects;
+ BLI_duplicatelist(&collection_objects, &sc->objects);
+
+ FOREACH_SCENE_COLLECTION(owner_id, scene_collection_iter)
+ {
+ if (scene_collection_iter == sc) {
+ continue;
+ }
+
+ LinkData *link_next, *link = collection_objects.first;
+ while (link) {
+ link_next = link->next;
+
+ if (BLI_findptr(&scene_collection_iter->objects, link->data, offsetof(LinkData, data))) {
+ BLI_remlink(&collection_objects, link);
+ MEM_freeN(link);
+ }
+
+ link = link_next;
+ }
+ }
+ FOREACH_SCENE_COLLECTION_END
+
+ for (LinkData *link = collection_objects.first; link; link = link->next) {
+ BKE_collection_object_add(owner_id, sc_master, link->data);
+ }
+
+ BLI_freelistN(&collection_objects);
+
+ /* Clear the collection items. */
+ collection_free(sc, true);
+
+ /* check all layers that use this collection and clear them */
+ for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
+ layer_collection_remove(view_layer, &view_layer->layer_collections, sc);
+ view_layer->active_collection = 0;
+ }
+
+ MEM_freeN(sc);
+ return true;
+}
+
+/**
+ * Copy SceneCollection tree but keep pointing to the same objects
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_collection_copy_data(SceneCollection *sc_dst, SceneCollection *sc_src, const int flag)
+{
+ BLI_duplicatelist(&sc_dst->objects, &sc_src->objects);
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ for (LinkData *link = sc_dst->objects.first; link; link = link->next) {
+ id_us_plus(link->data);
+ }
+ }
+
+ BLI_duplicatelist(&sc_dst->filter_objects, &sc_src->filter_objects);
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ for (LinkData *link = sc_dst->filter_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);
+ }
+}
+
+static SceneCollection *master_collection_from_id(const ID *owner_id)
+{
+ switch (GS(owner_id->name)) {
+ case ID_SCE:
+ return ((const Scene *)owner_id)->collection;
+ case ID_GR:
+ return ((const Group *)owner_id)->collection;
+ default:
+ BLI_assert(!"ID doesn't support scene collection");
+ return NULL;
+ }
+}
+
+/**
+ * Returns the master collection of the scene or group
+ */
+SceneCollection *BKE_collection_master(const ID *owner_id)
+{
+ return master_collection_from_id(owner_id);
+}
+
+static void collection_rename(const ID *owner_id, SceneCollection *sc, const char *name)
+{
+ SceneCollection *sc_parent = find_collection_parent(sc, collection_master_from_id(owner_id));
+ BLI_strncpy(sc->name, name, sizeof(sc->name));
+ BLI_uniquename(&sc_parent->scene_collections, sc, DATA_("Collection"), '.', offsetof(SceneCollection, name), sizeof(sc->name));
+}
+
+void BKE_collection_rename(const Scene *scene, SceneCollection *sc, const char *name)
+{
+ collection_rename(&scene->id, sc, name);
+}
+
+/**
+ * Free (or release) any data used by the master collection (does not free the master collection itself).
+ * Used only to clear the entire scene or group data since it's not doing re-syncing of the LayerCollection tree
+ */
+void BKE_collection_master_free(ID *owner_id, const bool do_id_user)
+{
+ collection_free(BKE_collection_master(owner_id), do_id_user);
+}
+
+static void collection_object_add(const ID *owner_id, SceneCollection *sc, Object *ob)
+{
+ BLI_addtail(&sc->objects, BLI_genericNodeN(ob));
+
+ if (GS(owner_id->name) == ID_SCE) {
+ id_us_plus((ID *)ob);
+ }
+ else {
+ BLI_assert(GS(owner_id->name) == ID_GR);
+ if ((ob->flag & OB_FROMGROUP) == 0) {
+ ob->flag |= OB_FROMGROUP;
+ }
+ }
+
+ BKE_layer_sync_object_link(owner_id, sc, ob);
+}
+
+/**
+ * Add object to collection
+ */
+bool BKE_collection_object_add(const ID *owner_id, SceneCollection *sc, Object *ob)
+{
+ if (BLI_findptr(&sc->objects, ob, offsetof(LinkData, data))) {
+ /* don't add the same object twice */
+ return false;
+ }
+
+ collection_object_add(owner_id, sc, ob);
+ return true;
+}
+
+/**
+ * Add object to all collections that reference objects is in
+ * (used to copy objects)
+ */
+void BKE_collection_object_add_from(Scene *scene, Object *ob_src, Object *ob_dst)
+{
+ FOREACH_SCENE_COLLECTION(scene, sc)
+ {
+ if (BLI_findptr(&sc->objects, ob_src, offsetof(LinkData, data))) {
+ collection_object_add(&scene->id, sc, ob_dst);
+ }
+ }
+ FOREACH_SCENE_COLLECTION_END
+
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ Base *base_src = BKE_view_layer_base_find(view_layer, ob_src);
+ if (base_src != NULL) {
+ if (base_src->collection_properties == NULL) {
+ continue;
+ }
+ Base *base_dst = BKE_view_layer_base_find(view_layer, ob_dst);
+ IDP_MergeGroup(base_dst->collection_properties, base_src->collection_properties, true);
+ }
+ }
+}
+
+/**
+ * Remove object from collection.
+ * \param bmain: Can be NULL if free_us is false.
+ */
+bool BKE_collection_object_remove(Main *bmain, ID *owner_id, SceneCollection *sc, Object *ob, const bool free_us)
+{
+ LinkData *link = BLI_findptr(&sc->objects, ob, offsetof(LinkData, data));
+
+ if (link == NULL) {
+ return false;
+ }
+
+ BLI_remlink(&sc->objects, link);
+ MEM_freeN(link);
+
+ TODO_LAYER_SYNC_FILTER; /* need to remove all instances of ob in scene collections -> filter_objects */
+ BKE_layer_sync_object_unlink(owner_id, sc, ob);
+
+ if (GS(owner_id->name) == ID_SCE) {
+ if (free_us) {
+ BKE_libblock_free_us(bmain, ob);
+ }
+ else {
+ id_us_min(&ob->id);
+ }
+ }
+ else {
+ BLI_assert(GS(owner_id->name) == ID_GR);
+ }
+
+ return true;
+}
+
+/**
+ * Move object from a collection into another
+ */
+void BKE_collection_object_move(ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src, Object *ob)
+{
+ if (BKE_collection_object_add(owner_id, sc_dst, ob)) {
+ BKE_collection_object_remove(NULL, owner_id, sc_src, ob, false);
+ }
+}
+
+/**
+ * Remove object from all collections of scene
+ */
+bool BKE_collections_object_remove(Main *bmain, ID *owner_id, Object *ob, const bool free_us)
+{
+ bool removed = false;
+ if (GS(owner_id->name) == ID_SCE) {
+ BKE_scene_remove_rigidbody_object((Scene *)owner_id, ob);
+ }
+ else {
+ BLI_assert(GS(owner_id->name) == ID_GR);
+ }
+
+ FOREACH_SCENE_COLLECTION(owner_id, sc)
+ {
+ removed |= BKE_collection_object_remove(bmain, owner_id, sc, ob, free_us);
+ }
+ FOREACH_SCENE_COLLECTION_END
+ return removed;
+}
+
+static void layer_collection_sync(LayerCollection *lc_dst, LayerCollection *lc_src)
+{
+ lc_dst->flag = lc_src->flag;
+
+ /* Pending: sync overrides. */
+ IDP_MergeGroup(lc_dst->properties, lc_src->properties, true);
+
+ /* Continue recursively. */
+ LayerCollection *lc_dst_nested, *lc_src_nested;
+ lc_src_nested = lc_src->layer_collections.first;
+ for (lc_dst_nested = lc_dst->layer_collections.first;
+ lc_dst_nested && lc_src_nested;
+ lc_dst_nested = lc_dst_nested->next, lc_src_nested = lc_src_nested->next)
+ {
+ layer_collection_sync(lc_dst_nested, lc_src_nested);
+ }
+}
+
+/**
+ * Leave only the master collection in, remove everything else.
+ * @param group
+ */
+static void collection_group_cleanup(Group *group)
+{
+ /* Unlink all the LayerCollections. */
+ while (group->view_layer->layer_collections.last != NULL) {
+ BKE_collection_unlink(group->view_layer, group->view_layer->layer_collections.last);
+ }
+
+ /* Remove all the SceneCollections but the master. */
+ collection_free(group->collection, false);
+}
+
+/**
+ * Create a group from a collection
+ *
+ * Any ViewLayer that may have this the related SceneCollection linked is converted
+ * to a Group Collection.
+ */
+Group *BKE_collection_group_create(Main *bmain, Scene *scene, LayerCollection *lc_src)
+{
+ SceneCollection *sc_dst, *sc_src = lc_src->scene_collection;
+ LayerCollection *lc_dst;
+
+ /* The master collection can't be converted. */
+ if (sc_src == BKE_collection_master(&scene->id)) {
+ return NULL;
+ }
+
+ /* If a sub-collection of sc_dst is directly linked into a ViewLayer we can't convert. */
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (LayerCollection *lc_child = view_layer->layer_collections.first; lc_child; lc_child = lc_child->next) {
+ if (is_collection_in_tree(lc_child->scene_collection, sc_src)) {
+ return NULL;
+ }
+ }
+ }
+
+ /* Create new group with the same data as the original collection. */
+ Group *group = BKE_group_add(bmain, sc_src->name);
+ collection_group_cleanup(group);
+
+ sc_dst = BKE_collection_add(&group->id, NULL, COLLECTION_TYPE_GROUP_INTERNAL, sc_src->name);
+ BKE_collection_copy_data(sc_dst, sc_src, 0);
+ FOREACH_SCENE_COLLECTION(&group->id, sc_group)
+ {
+ sc_group->type = COLLECTION_TYPE_GROUP_INTERNAL;
+ }
+ FOREACH_SCENE_COLLECTION_END
+
+ lc_dst = BKE_collection_link(group->view_layer, sc_dst);
+ layer_collection_sync(lc_dst, lc_src);
+
+ return group;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Outliner drag and drop */
+
+/**
+ * Find and return the SceneCollection that has \a sc_child as one of its directly
+ * nested SceneCollection.
+ *
+ * \param sc_parent Initial SceneCollection to look into recursively, usually the master collection
+ */
+static SceneCollection *find_collection_parent(const SceneCollection *sc_child, SceneCollection *sc_parent)
+{
+ for (SceneCollection *sc_nested = sc_parent->scene_collections.first; sc_nested; sc_nested = sc_nested->next) {
+ if (sc_nested == sc_child) {
+ return sc_parent;
+ }
+
+ SceneCollection *found = find_collection_parent(sc_child, sc_nested);
+ if (found) {
+ return found;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Check if \a sc_reference is nested to \a sc_parent SceneCollection
+ */
+static bool is_collection_in_tree(const SceneCollection *sc_reference, SceneCollection *sc_parent)
+{
+ return find_collection_parent(sc_reference, sc_parent) != NULL;
+}
+
+bool BKE_collection_move_above(const ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src)
+{
+ /* Find the SceneCollection the sc_src belongs to */
+ SceneCollection *sc_master = master_collection_from_id(owner_id);
+
+ /* Master Layer can't be moved around*/
+ if (ELEM(sc_master, sc_src, sc_dst)) {
+ return false;
+ }
+
+ /* collection is already where we wanted it to be */
+ if (sc_dst->prev == sc_src) {
+ return false;
+ }
+
+ /* We can't move a collection fs the destiny collection
+ * is nested to the source collection */
+ if (is_collection_in_tree(sc_dst, sc_src)) {
+ return false;
+ }
+
+ SceneCollection *sc_src_parent = find_collection_parent(sc_src, sc_master);
+ SceneCollection *sc_dst_parent = find_collection_parent(sc_dst, sc_master);
+ BLI_assert(sc_src_parent);
+ BLI_assert(sc_dst_parent);
+
+ /* Remove sc_src from its parent */
+ BLI_remlink(&sc_src_parent->scene_collections, sc_src);
+
+ /* Re-insert it where it belongs */
+ BLI_insertlinkbefore(&sc_dst_parent->scene_collections, sc_dst, sc_src);
+
+ /* Update the tree */
+ BKE_layer_collection_resync(owner_id, sc_src_parent);
+ BKE_layer_collection_resync(owner_id, sc_dst_parent);
+
+ 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);
+
+ 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);
+
+ 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 21e28f5180c..2f80fbbec46 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -47,6 +47,8 @@
#include "BKE_cloth.h"
#include "BKE_effect.h"
+#include "BKE_group.h"
+#include "BKE_layer.h"
#include "BKE_modifier.h"
#include "BKE_scene.h"
@@ -501,22 +503,22 @@ static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned
/* objects in dupli groups, one level only for now */
if (ob->dup_group && level == 0) {
- GroupObject *go;
Group *group= ob->dup_group;
/* add objects */
- for (go= group->gobject.first; go; go= go->next)
- add_collision_object(objs, numobj, maxobj, go->ob, self, level+1, modifier_type);
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ add_collision_object(objs, numobj, maxobj, object, self, level+1, modifier_type);
+ }
+ FOREACH_GROUP_OBJECT_END
}
}
// return all collision objects in scene
// collision object will exclude self
-Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, int layer, unsigned int *numcollobj, unsigned int modifier_type, bool dupli)
+Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, unsigned int *numcollobj, unsigned int modifier_type, bool dupli)
{
- Base *base;
Object **objs;
- GroupObject *go;
unsigned int numobj= 0, maxobj= 100;
int level = dupli ? 0 : 1;
@@ -525,16 +527,20 @@ Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, int
/* gather all collision objects */
if (group) {
/* use specified group */
- for (go= group->gobject.first; go; go= go->next)
- add_collision_object(&objs, &numobj, &maxobj, go->ob, self, level, modifier_type);
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ add_collision_object(&objs, &numobj, &maxobj, object, self, level, modifier_type);
+ }
+ FOREACH_GROUP_OBJECT_END
}
else {
Scene *sce_iter;
+ Base *base;
/* add objects in same layer in scene */
for (SETLOOPER(scene, sce_iter, base)) {
- if ( base->lay & layer )
+ if ((base->flag & BASE_VISIBLED) != 0) {
add_collision_object(&objs, &numobj, &maxobj, base->object, self, level, modifier_type);
-
+ }
}
}
@@ -547,7 +553,7 @@ Object **get_collisionobjects(Scene *scene, Object *self, Group *group, unsigned
{
/* Need to check for active layers, too.
Otherwise this check fails if the objects are not on the same layer - DG */
- return get_collisionobjects_ext(scene, self, group, self->lay | scene->lay, numcollobj, modifier_type, true);
+ return get_collisionobjects_ext(scene, self, group, numcollobj, modifier_type, true);
}
static void add_collider_cache_object(ListBase **objs, Object *ob, Object *self, int level)
@@ -575,24 +581,28 @@ static void add_collider_cache_object(ListBase **objs, Object *ob, Object *self,
/* objects in dupli groups, one level only for now */
if (ob->dup_group && level == 0) {
- GroupObject *go;
Group *group= ob->dup_group;
/* add objects */
- for (go= group->gobject.first; go; go= go->next)
- add_collider_cache_object(objs, go->ob, self, level+1);
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ add_collider_cache_object(objs, object, self, level+1);
+ }
+ FOREACH_GROUP_OBJECT_END
}
}
ListBase *get_collider_cache(Scene *scene, Object *self, Group *group)
{
- GroupObject *go;
ListBase *objs= NULL;
/* add object in same layer in scene */
if (group) {
- for (go= group->gobject.first; go; go= go->next)
- add_collider_cache_object(&objs, go->ob, self, 0);
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ add_collider_cache_object(&objs, object, self, 0);
+ }
+ FOREACH_GROUP_OBJECT_END
}
else {
Scene *sce_iter;
@@ -600,7 +610,7 @@ ListBase *get_collider_cache(Scene *scene, Object *self, Group *group)
/* add objects in same layer in scene */
for (SETLOOPER(scene, sce_iter, base)) {
- if (!self || (base->lay & self->lay))
+ if (!self || ((base->flag & BASE_VISIBLED) != 0))
add_collider_cache_object(&objs, base->object, self, 0);
}
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index c77cac7bcbd..b8dc7944a75 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -98,11 +98,6 @@
/* Constraint Target Macros */
#define VALID_CONS_TARGET(ct) ((ct) && (ct->tar))
-/* Workaround for cyclic depenndnecy with curves.
- * In such case curve_cache might not be ready yet,
- */
-#define CYCLIC_DEPENDENCY_WORKAROUND
-
/* ************************ Constraints - General Utilities *************************** */
/* These functions here don't act on any specific constraints, and are therefore should/will
* not require any of the special function-pointers afforded by the relevant constraint
@@ -689,7 +684,7 @@ static bConstraintTypeInfo CTI_CONSTRNAME = {
/* This function should be used for the get_target_matrix member of all
* constraints that are not picky about what happens to their target matrix.
*/
-static void default_get_tarmat(bConstraint *con, bConstraintOb *UNUSED(cob), bConstraintTarget *ct, float UNUSED(ctime))
+static void default_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx), bConstraint *con, bConstraintOb *UNUSED(cob), bConstraintTarget *ct, float UNUSED(ctime))
{
if (VALID_CONS_TARGET(ct))
constraint_target_to_mat4(ct->tar, ct->subtarget, ct->matrix, CONSTRAINT_SPACE_WORLD, ct->space, con->flag, con->headtail);
@@ -1158,7 +1153,7 @@ static void kinematic_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
}
}
-static void kinematic_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
+static void kinematic_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx), bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
{
bKinematicConstraint *data = con->data;
@@ -1245,7 +1240,9 @@ static void followpath_flush_tars(bConstraint *con, ListBase *list, bool no_copy
}
}
-static void followpath_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
+static void followpath_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx),
+ bConstraint *con, bConstraintOb *UNUSED(cob),
+ bConstraintTarget *ct, float UNUSED(ctime))
{
bFollowPathConstraint *data = con->data;
@@ -1260,13 +1257,7 @@ static void followpath_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra
* currently for paths to work it needs to go through the bevlist/displist system (ton)
*/
-#ifdef CYCLIC_DEPENDENCY_WORKAROUND
- if (ct->tar->curve_cache == NULL) {
- BKE_displist_make_curveTypes(cob->scene, ct->tar, false);
- }
-#endif
-
- if (ct->tar->curve_cache->path && ct->tar->curve_cache->path->data) {
+ if (ct->tar->curve_cache && ct->tar->curve_cache->path && ct->tar->curve_cache->path->data) {
float quat[4];
if ((data->followflag & FOLLOWPATH_STATIC) == 0) {
/* animated position along curve depending on time */
@@ -2027,21 +2018,19 @@ static void pycon_id_looper(bConstraint *con, ConstraintIDFunc func, void *userd
}
/* Whether this approach is maintained remains to be seen (aligorith) */
-static void pycon_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
+static void pycon_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx),
+ bConstraint *con, bConstraintOb *UNUSED(cob),
+ bConstraintTarget *ct, float UNUSED(ctime))
{
#ifdef WITH_PYTHON
bPythonConstraint *data = con->data;
#endif
if (VALID_CONS_TARGET(ct)) {
-#ifdef CYCLIC_DEPENDENCY_WORKAROUND
- /* special exception for curves - depsgraph issues */
- if (ct->tar->type == OB_CURVE) {
- if (ct->tar->curve_cache == NULL) {
- BKE_displist_make_curveTypes(cob->scene, ct->tar, false);
- }
+ if (ct->tar->type == OB_CURVE && ct->tar->curve_cache == NULL) {
+ unit_m4(ct->matrix);
+ return;
}
-#endif
/* firstly calculate the matrix the normal way, then let the py-function override
* this matrix if it needs to do so
@@ -2145,7 +2134,7 @@ static void actcon_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
}
}
-static void actcon_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
+static void actcon_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx), bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
{
bActionConstraint *data = con->data;
@@ -3134,16 +3123,10 @@ static void clampto_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
}
}
-static void clampto_get_tarmat(bConstraint *UNUSED(con), bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
+static void clampto_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx),
+ bConstraint *UNUSED(con), bConstraintOb *UNUSED(cob),
+ bConstraintTarget *ct, float UNUSED(ctime))
{
-#ifdef CYCLIC_DEPENDENCY_WORKAROUND
- if (VALID_CONS_TARGET(ct)) {
- if (ct->tar->curve_cache == NULL) {
- BKE_displist_make_curveTypes(cob->scene, ct->tar, false);
- }
- }
-#endif
-
/* technically, this isn't really needed for evaluation, but we don't know what else
* might end up calling this...
*/
@@ -3477,7 +3460,7 @@ static void shrinkwrap_flush_tars(bConstraint *con, ListBase *list, bool no_copy
}
-static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
+static void shrinkwrap_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx), bConstraint *con, bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
{
bShrinkwrapConstraint *scon = (bShrinkwrapConstraint *) con->data;
@@ -3809,16 +3792,10 @@ static void splineik_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
}
}
-static void splineik_get_tarmat(bConstraint *UNUSED(con), bConstraintOb *cob, bConstraintTarget *ct, float UNUSED(ctime))
+static void splineik_get_tarmat(const struct EvaluationContext *UNUSED(eval_ctx),
+ bConstraint *UNUSED(con), bConstraintOb *UNUSED(cob),
+ bConstraintTarget *ct, float UNUSED(ctime))
{
-#ifdef CYCLIC_DEPENDENCY_WORKAROUND
- if (VALID_CONS_TARGET(ct)) {
- if (ct->tar->curve_cache == NULL) {
- BKE_displist_make_curveTypes(cob->scene, ct->tar, false);
- }
- }
-#endif
-
/* technically, this isn't really needed for evaluation, but we don't know what else
* might end up calling this...
*/
@@ -4867,7 +4844,7 @@ bool BKE_constraints_proxylocked_owner(Object *ob, bPoseChannel *pchan)
* None of the actual calculations of the matrices should be done here! Also, this function is
* not to be used by any new constraints, particularly any that have multiple targets.
*/
-void BKE_constraint_target_matrix_get(Scene *scene, bConstraint *con, int index, short ownertype, void *ownerdata, float mat[4][4], float ctime)
+void BKE_constraint_target_matrix_get(const struct EvaluationContext *eval_ctx, Scene *scene, bConstraint *con, int index, short ownertype, void *ownerdata, float mat[4][4], float ctime)
{
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
ListBase targets = {NULL, NULL};
@@ -4918,7 +4895,7 @@ void BKE_constraint_target_matrix_get(Scene *scene, bConstraint *con, int index,
if (ct) {
if (cti->get_target_matrix)
- cti->get_target_matrix(con, cob, ct, ctime);
+ cti->get_target_matrix(eval_ctx, con, cob, ct, ctime);
copy_m4_m4(mat, ct->matrix);
}
@@ -4934,7 +4911,7 @@ void BKE_constraint_target_matrix_get(Scene *scene, bConstraint *con, int index,
}
/* Get the list of targets required for solving a constraint */
-void BKE_constraint_targets_for_solving_get(bConstraint *con, bConstraintOb *cob, ListBase *targets, float ctime)
+void BKE_constraint_targets_for_solving_get(const struct EvaluationContext *eval_ctx, bConstraint *con, bConstraintOb *cob, ListBase *targets, float ctime)
{
const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
@@ -4952,7 +4929,7 @@ void BKE_constraint_targets_for_solving_get(bConstraint *con, bConstraintOb *cob
*/
if (cti->get_target_matrix) {
for (ct = targets->first; ct; ct = ct->next)
- cti->get_target_matrix(con, cob, ct, ctime);
+ cti->get_target_matrix(eval_ctx, con, cob, ct, ctime);
}
else {
for (ct = targets->first; ct; ct = ct->next)
@@ -4969,7 +4946,7 @@ void BKE_constraint_targets_for_solving_get(bConstraint *con, bConstraintOb *cob
* BKE_constraints_make_evalob and BKE_constraints_clear_evalob should be called before and
* after running this function, to sort out cob
*/
-void BKE_constraints_solve(ListBase *conlist, bConstraintOb *cob, float ctime)
+void BKE_constraints_solve(const struct EvaluationContext *eval_ctx, ListBase *conlist, bConstraintOb *cob, float ctime)
{
bConstraint *con;
float oldmat[4][4];
@@ -5004,7 +4981,7 @@ void BKE_constraints_solve(ListBase *conlist, bConstraintOb *cob, float ctime)
BKE_constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace, false);
/* prepare targets for constraint solving */
- BKE_constraint_targets_for_solving_get(con, cob, &targets, ctime);
+ BKE_constraint_targets_for_solving_get(eval_ctx, con, cob, &targets, ctime);
/* Solve the constraint and put result in cob->matrix */
cti->evaluate_constraint(con, cob, &targets);
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 4c01bfd35f2..7d4cbd16331 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -38,6 +38,9 @@
#include "DNA_object_types.h"
#include "DNA_linestyle_types.h"
#include "DNA_gpencil_types.h"
+#include "DNA_workspace_types.h"
+
+#include "DEG_depsgraph.h"
#include "BLI_listbase.h"
#include "BLI_string.h"
@@ -47,9 +50,14 @@
#include "BLT_translation.h"
#include "BKE_context.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
+#include "BKE_scene.h"
#include "BKE_screen.h"
#include "BKE_sound.h"
+#include "BKE_workspace.h"
+
+#include "RE_engine.h"
#include "RNA_access.h"
@@ -66,10 +74,12 @@ struct bContext {
struct {
struct wmWindowManager *manager;
struct wmWindow *window;
+ struct WorkSpace *workspace;
struct bScreen *screen;
struct ScrArea *area;
struct ARegion *region;
struct ARegion *menu;
+ struct wmManipulatorGroup *manipulator_group;
struct bContextStore *store;
const char *operator_poll_msg; /* reason for poll failing */
} wm;
@@ -627,6 +637,11 @@ wmWindow *CTX_wm_window(const bContext *C)
return ctx_wm_python_context_get(C, "window", &RNA_Window, C->wm.window);
}
+WorkSpace *CTX_wm_workspace(const bContext *C)
+{
+ return ctx_wm_python_context_get(C, "workspace", &RNA_WorkSpace, C->wm.workspace);
+}
+
bScreen *CTX_wm_screen(const bContext *C)
{
return ctx_wm_python_context_get(C, "screen", &RNA_Screen, C->wm.screen);
@@ -659,6 +674,16 @@ struct ARegion *CTX_wm_menu(const bContext *C)
return C->wm.menu;
}
+struct wmManipulatorGroup *CTX_wm_manipulator_group(const bContext *C)
+{
+ return C->wm.manipulator_group;
+}
+
+struct wmMsgBus *CTX_wm_message_bus(const bContext *C)
+{
+ return C->wm.manager ? C->wm.manager->message_bus : NULL;
+}
+
struct ReportList *CTX_wm_reports(const bContext *C)
{
if (C->wm.manager)
@@ -826,9 +851,11 @@ void CTX_wm_manager_set(bContext *C, wmWindowManager *wm)
void CTX_wm_window_set(bContext *C, wmWindow *win)
{
C->wm.window = win;
- C->wm.screen = (win) ? win->screen : NULL;
- if (C->wm.screen)
- C->data.scene = C->wm.screen->scene;
+ if (win) {
+ C->data.scene = win->scene;
+ }
+ C->wm.workspace = (win) ? BKE_workspace_active_get(win->workspace_hook) : NULL;
+ C->wm.screen = (win) ? BKE_workspace_active_screen_get(win->workspace_hook) : NULL;
C->wm.area = NULL;
C->wm.region = NULL;
}
@@ -836,8 +863,6 @@ void CTX_wm_window_set(bContext *C, wmWindow *win)
void CTX_wm_screen_set(bContext *C, bScreen *screen)
{
C->wm.screen = screen;
- if (C->wm.screen)
- C->data.scene = C->wm.screen->scene;
C->wm.area = NULL;
C->wm.region = NULL;
}
@@ -858,6 +883,11 @@ void CTX_wm_menu_set(bContext *C, ARegion *menu)
C->wm.menu = menu;
}
+void CTX_wm_manipulator_group_set(bContext *C, struct wmManipulatorGroup *mgroup)
+{
+ C->wm.manipulator_group = mgroup;
+}
+
void CTX_wm_operator_poll_msg_set(bContext *C, const char *msg)
{
C->wm.operator_poll_msg = msg;
@@ -896,10 +926,80 @@ Scene *CTX_data_scene(const bContext *C)
return C->data.scene;
}
-int CTX_data_mode_enum(const bContext *C)
+ViewLayer *CTX_data_view_layer(const bContext *C)
{
- Object *obedit = CTX_data_edit_object(C);
+ ViewLayer *view_layer;
+
+ if (ctx_data_pointer_verify(C, "view_layer", (void *)&view_layer)) {
+ return view_layer;
+ }
+ else {
+ return BKE_view_layer_from_workspace_get(CTX_data_scene(C), CTX_wm_workspace(C));
+ }
+}
+
+ViewRender *CTX_data_view_render(const bContext *C)
+{
+ ViewRender *view_render;
+
+ if (ctx_data_pointer_verify(C, "view_render", (void *)&view_render)) {
+ return view_render;
+ }
+ else {
+ Scene *scene = CTX_data_scene(C);
+ WorkSpace *workspace = CTX_wm_workspace(C);
+ return BKE_viewrender_get(scene, workspace);
+ }
+}
+
+RenderEngineType *CTX_data_engine_type(const bContext *C)
+{
+ ViewRender *view_render = CTX_data_view_render(C);
+ return RE_engines_find(view_render->engine_id);
+}
+/**
+ * This is tricky. Sometimes the user overrides the render_layer
+ * but not the scene_collection. In this case what to do?
+ *
+ * If the scene_collection is linked to the ViewLayer we use it.
+ * Otherwise we fallback to the active one of the ViewLayer.
+ */
+LayerCollection *CTX_data_layer_collection(const bContext *C)
+{
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ LayerCollection *layer_collection;
+
+ if (ctx_data_pointer_verify(C, "layer_collection", (void *)&layer_collection)) {
+ if (BKE_view_layer_has_collection(view_layer, layer_collection->scene_collection)) {
+ return layer_collection;
+ }
+ }
+
+ /* fallback */
+ return BKE_layer_collection_get_active(view_layer);
+}
+
+SceneCollection *CTX_data_scene_collection(const bContext *C)
+{
+ SceneCollection *scene_collection;
+ if (ctx_data_pointer_verify(C, "scene_collection", (void *)&scene_collection)) {
+ return scene_collection;
+ }
+
+ LayerCollection *layer_collection = CTX_data_layer_collection(C);
+ if (layer_collection) {
+ return layer_collection->scene_collection;
+ }
+
+ /* fallback */
+ Scene *scene = CTX_data_scene(C);
+ return BKE_collection_master(&scene->id);
+}
+
+int CTX_data_mode_enum_ex(const Object *obedit, const Object *ob)
+{
+ // Object *obedit = CTX_data_edit_object(C);
if (obedit) {
switch (obedit->type) {
case OB_MESH:
@@ -919,8 +1019,7 @@ 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;
@@ -934,6 +1033,12 @@ int CTX_data_mode_enum(const bContext *C)
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);
+}
/* would prefer if we can use the enum version below over this one - Campbell */
/* must be aligned with above enum */
@@ -954,6 +1059,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 +1260,21 @@ int CTX_data_editable_gpencil_strokes(const bContext *C, ListBase *list)
return ctx_data_collection_get(C, "editable_gpencil_strokes", list);
}
+Depsgraph *CTX_data_depsgraph(const bContext *C)
+{
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ return BKE_scene_get_depsgraph(scene, view_layer, true);
+}
+
+void CTX_data_eval_ctx(const bContext *C, EvaluationContext *eval_ctx)
+{
+ BLI_assert(C != NULL);
+
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ RenderEngineType *engine_type = CTX_data_engine_type(C);
+ DEG_evaluation_context_init_from_scene(eval_ctx,
+ scene, view_layer, engine_type,
+ DAG_EVAL_VIEWPORT);
+}
diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c
index 56df8e51eba..d2ffbbcf27b 100644
--- a/source/blender/blenkernel/intern/crazyspace.c
+++ b/source/blender/blenkernel/intern/crazyspace.c
@@ -99,7 +99,8 @@ static int modifiers_disable_subsurf_temporary(Object *ob)
}
/* disable subsurf temporal, get mapped cos, and enable it */
-float (*BKE_crazyspace_get_mapped_editverts(Scene *scene, Object *obedit))[3]
+float (*BKE_crazyspace_get_mapped_editverts(
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *obedit))[3]
{
Mesh *me = obedit->data;
DerivedMesh *dm;
@@ -109,13 +110,13 @@ float (*BKE_crazyspace_get_mapped_editverts(Scene *scene, Object *obedit))[3]
/* disable subsurf temporal, get mapped cos, and enable it */
if (modifiers_disable_subsurf_temporary(obedit)) {
/* need to make new derivemesh */
- makeDerivedMesh(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH, false);
+ makeDerivedMesh(eval_ctx, scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH, false);
}
/* now get the cage */
vertexcos = MEM_mallocN(sizeof(*vertexcos) * nverts, "vertexcos map");
- dm = editbmesh_get_derived_cage(scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH);
+ dm = editbmesh_get_derived_cage(eval_ctx, scene, obedit, me->edit_btmesh, CD_MASK_BAREMESH);
mesh_get_mapped_verts_coords(dm, vertexcos, nverts);
@@ -250,8 +251,9 @@ void BKE_crazyspace_set_quats_mesh(Mesh *me, float (*origcos)[3], float (*mapped
/** returns an array of deform matrices for crazyspace correction, and the
* number of modifiers left */
-int BKE_crazyspace_get_first_deform_matrices_editbmesh(Scene *scene, Object *ob, BMEditMesh *em,
- float (**deformmats)[3][3], float (**deformcos)[3])
+int BKE_crazyspace_get_first_deform_matrices_editbmesh(
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, BMEditMesh *em,
+ float (**deformmats)[3][3], float (**deformcos)[3])
{
ModifierData *md;
DerivedMesh *dm;
@@ -290,7 +292,7 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(Scene *scene, Object *ob,
unit_m3(defmats[a]);
}
- mti->deformMatricesEM(md, ob, em, dm, deformedVerts, defmats,
+ mti->deformMatricesEM(md, eval_ctx, ob, em, dm, deformedVerts, defmats,
numVerts);
}
else
@@ -310,7 +312,9 @@ int BKE_crazyspace_get_first_deform_matrices_editbmesh(Scene *scene, Object *ob,
return numleft;
}
-int BKE_sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**deformmats)[3][3], float (**deformcos)[3])
+int BKE_sculpt_get_first_deform_matrices(
+ const struct EvaluationContext *eval_ctx, Scene *scene,
+ Object *ob, float (**deformmats)[3][3], float (**deformcos)[3])
{
ModifierData *md;
DerivedMesh *dm;
@@ -346,7 +350,7 @@ int BKE_sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**defo
unit_m3(defmats[a]);
}
- if (mti->deformMatrices) mti->deformMatrices(md, ob, dm, deformedVerts, defmats, numVerts);
+ if (mti->deformMatrices) mti->deformMatrices(md, eval_ctx, ob, dm, deformedVerts, defmats, numVerts);
else break;
}
}
@@ -369,9 +373,9 @@ int BKE_sculpt_get_first_deform_matrices(Scene *scene, Object *ob, float (**defo
return numleft;
}
-void BKE_crazyspace_build_sculpt(Scene *scene, Object *ob, float (**deformmats)[3][3], float (**deformcos)[3])
+void BKE_crazyspace_build_sculpt(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float (**deformmats)[3][3], float (**deformcos)[3])
{
- int totleft = BKE_sculpt_get_first_deform_matrices(scene, ob, deformmats, deformcos);
+ int totleft = BKE_sculpt_get_first_deform_matrices(eval_ctx, scene, ob, deformmats, deformcos);
if (totleft) {
/* there are deformation modifier which doesn't support deformation matrices
@@ -396,7 +400,7 @@ void BKE_crazyspace_build_sculpt(Scene *scene, Object *ob, float (**deformmats)[
if (mti->deformMatrices && !deformed)
continue;
- mti->deformVerts(md, ob, NULL, deformedVerts, me->totvert, 0);
+ mti->deformVerts(md, eval_ctx, ob, NULL, deformedVerts, me->totvert, 0);
deformed = 1;
}
}
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 1a744ddaf03..380ab6fcc1e 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -53,7 +53,6 @@
#include "BKE_animsys.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_displist.h"
#include "BKE_font.h"
#include "BKE_global.h"
@@ -65,6 +64,8 @@
#include "BKE_object.h"
#include "BKE_material.h"
+#include "DEG_depsgraph.h"
+
/* globals */
/* local */
@@ -127,6 +128,8 @@ void BKE_curve_free(Curve *cu)
{
BKE_animdata_free((ID *)cu, false);
+ BKE_curve_batch_cache_free(cu);
+
BKE_nurbList_free(&cu->nurb);
BKE_curve_editfont_free(cu);
@@ -207,6 +210,7 @@ void BKE_curve_copy_data(Main *bmain, Curve *cu_dst, const Curve *cu_src, const
cu_dst->strinfo = MEM_dupallocN(cu_src->strinfo);
cu_dst->tb = MEM_dupallocN(cu_src->tb);
cu_dst->bb = MEM_dupallocN(cu_src->bb);
+ cu_dst->batch_cache = NULL;
if (cu_src->key) {
BKE_id_copy_ex(bmain, &cu_src->key->id, (ID **)&cu_dst->key, flag, false);
@@ -1620,7 +1624,7 @@ float *BKE_curve_surf_make_orco(Object *ob)
/* NOTE: This routine is tied to the order of vertex
* built by displist and as passed to the renderer.
*/
-float *BKE_curve_make_orco(Scene *scene, Object *ob, int *r_numVerts)
+float *BKE_curve_make_orco(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, int *r_numVerts)
{
Curve *cu = ob->data;
DispList *dl;
@@ -1628,7 +1632,7 @@ float *BKE_curve_make_orco(Scene *scene, Object *ob, int *r_numVerts)
float *fp, *coord_array;
ListBase disp = {NULL, NULL};
- BKE_displist_make_curveTypes_forOrco(scene, ob, &disp);
+ BKE_displist_make_curveTypes_forOrco(eval_ctx, scene, ob, &disp);
numVerts = 0;
for (dl = disp.first; dl; dl = dl->next) {
@@ -1719,8 +1723,9 @@ float *BKE_curve_make_orco(Scene *scene, Object *ob, int *r_numVerts)
/* ***************** BEVEL ****************** */
-void BKE_curve_bevel_make(Scene *scene, Object *ob, ListBase *disp,
- const bool for_render, const bool use_render_resolution)
+void BKE_curve_bevel_make(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *disp,
+ const bool for_render, const bool use_render_resolution)
{
DispList *dl, *dlnew;
Curve *bevcu, *cu;
@@ -1744,7 +1749,7 @@ void BKE_curve_bevel_make(Scene *scene, Object *ob, ListBase *disp,
facy = cu->bevobj->size[1];
if (for_render) {
- BKE_displist_make_curveTypes_forRender(scene, cu->bevobj, &bevdisp, NULL, false, use_render_resolution);
+ BKE_displist_make_curveTypes_forRender(eval_ctx, scene, cu->bevobj, &bevdisp, NULL, false, use_render_resolution);
dl = bevdisp.first;
}
else if (cu->bevobj->curve_cache) {
@@ -5180,7 +5185,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 {
@@ -5247,7 +5252,7 @@ void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *t
/* **** Depsgraph evaluation **** */
-void BKE_curve_eval_geometry(EvaluationContext *UNUSED(eval_ctx),
+void BKE_curve_eval_geometry(const EvaluationContext *UNUSED(eval_ctx),
Curve *curve)
{
if (G.debug & G_DEBUG_DEPSGRAPH) {
@@ -5257,3 +5262,20 @@ void BKE_curve_eval_geometry(EvaluationContext *UNUSED(eval_ctx),
BKE_curve_texspace_calc(curve);
}
}
+
+/* Draw Engine */
+void (*BKE_curve_batch_cache_dirty_cb)(Curve *cu, int mode) = NULL;
+void (*BKE_curve_batch_cache_free_cb)(Curve *cu) = NULL;
+
+void BKE_curve_batch_cache_dirty(Curve *cu, int mode)
+{
+ if (cu->batch_cache) {
+ BKE_curve_batch_cache_dirty_cb(cu, mode);
+ }
+}
+void BKE_curve_batch_cache_free(Curve *cu)
+{
+ if (cu->batch_cache) {
+ BKE_curve_batch_cache_free_cb(cu);
+ }
+}
diff --git a/source/blender/blenkernel/intern/customdata.c b/source/blender/blenkernel/intern/customdata.c
index cf86963cf60..9c0ace2f654 100644
--- a/source/blender/blenkernel/intern/customdata.c
+++ b/source/blender/blenkernel/intern/customdata.c
@@ -390,37 +390,19 @@ static void layerSwap_tface(void *data, const int *corner_indices)
{
MTFace *tf = data;
float uv[4][2];
- static const short pin_flags[4] = { TF_PIN1, TF_PIN2, TF_PIN3, TF_PIN4 };
- static const char sel_flags[4] = { TF_SEL1, TF_SEL2, TF_SEL3, TF_SEL4 };
- short unwrap = tf->unwrap & ~(TF_PIN1 | TF_PIN2 | TF_PIN3 | TF_PIN4);
- char flag = tf->flag & ~(TF_SEL1 | TF_SEL2 | TF_SEL3 | TF_SEL4);
int j;
for (j = 0; j < 4; ++j) {
const int source_index = corner_indices[j];
-
copy_v2_v2(uv[j], tf->uv[source_index]);
-
- /* swap pinning flags around */
- if (tf->unwrap & pin_flags[source_index]) {
- unwrap |= pin_flags[j];
- }
-
- /* swap selection flags around */
- if (tf->flag & sel_flags[source_index]) {
- flag |= sel_flags[j];
- }
}
memcpy(tf->uv, uv, sizeof(tf->uv));
- tf->unwrap = unwrap;
- tf->flag = flag;
}
static void layerDefault_tface(void *data, int count)
{
- static MTFace default_tf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}, NULL,
- 0, 0, TF_DYNAMIC | TF_CONVERTED, 0, 0};
+ static MTFace default_tf = {{{0, 0}, {1, 0}, {1, 1}, {0, 1}}};
MTFace *tf = (MTFace *)data;
int i;
@@ -1190,6 +1172,15 @@ static void layerSwap_flnor(void *data, const int *corner_indices)
memcpy(flnors, nors, sizeof(nors));
}
+static void layerDefault_fmap(void *data, int count)
+{
+ int *fmap_num = (int *)data;
+ int i;
+ for (i = 0; i < count; i++) {
+ *fmap_num = -1;
+ }
+}
+
static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 0: CD_MVERT */
{sizeof(MVert), "MVert", 1, NULL, NULL, NULL, NULL, NULL, NULL},
@@ -1215,8 +1206,8 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
/* 3 floats per normal vector */
{sizeof(float) * 3, "vec3f", 1, NULL, NULL, NULL, layerInterp_normal, NULL, NULL,
NULL, NULL, NULL, NULL, NULL, layerCopyValue_normal},
- /* 9: CD_POLYINDEX */ /* DEPRECATED */
- {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
+ /* 9: CD_FACEMAP */
+ {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, layerDefault_fmap, NULL},
/* 10: CD_PROP_FLT */
{sizeof(MFloatProperty), "MFloatProperty", 1, N_("Float"), layerCopy_propFloat, NULL, NULL, NULL},
/* 11: CD_PROP_INT */
@@ -1228,10 +1219,9 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
layerInterp_origspace_face, layerSwap_origspace_face, layerDefault_origspace_face},
/* 14: CD_ORCO */
{sizeof(float) * 3, "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
- /* 15: CD_MTEXPOLY */
+ /* 15: CD_MTEXPOLY */ /* DEPRECATED */
/* note, when we expose the UV Map / TexFace split to the user, change this back to face Texture */
- {sizeof(MTexPoly), "MTexPoly", 1, N_("UVMap") /* "Face Texture" */, NULL, NULL, NULL, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, layerMaxNum_tface},
+ {sizeof(int), "", 0, NULL, NULL, NULL, NULL, NULL, NULL},
/* 16: CD_MLOOPUV */
{sizeof(MLoopUV), "MLoopUV", 1, N_("UVMap"), NULL, NULL, layerInterp_mloopuv, NULL, NULL,
layerEqual_mloopuv, layerMultiply_mloopuv, layerInitMinMax_mloopuv,
@@ -1310,7 +1300,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
/* 0-4 */ "CDMVert", "CDMSticky", "CDMDeformVert", "CDMEdge", "CDMFace",
- /* 5-9 */ "CDMTFace", "CDMCol", "CDOrigIndex", "CDNormal", "CDFlags",
+ /* 5-9 */ "CDMTFace", "CDMCol", "CDOrigIndex", "CDNormal", "CDFaceMap",
/* 10-14 */ "CDMFloatProperty", "CDMIntProperty", "CDMStringProperty", "CDOrigSpace", "CDOrco",
/* 15-19 */ "CDMTexPoly", "CDMLoopUV", "CDMloopCol", "CDTangent", "CDMDisps",
/* 20-24 */ "CDPreviewMCol", "CDIDMCol", "CDTextureMCol", "CDClothOrco", "CDMRecast",
@@ -1325,41 +1315,41 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
const CustomDataMask CD_MASK_BAREMESH =
- CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MLOOP | CD_MASK_MPOLY | CD_MASK_BWEIGHT;
+ CD_MASK_MVERT | CD_MASK_MEDGE | CD_MASK_MLOOP | CD_MASK_MPOLY | CD_MASK_BWEIGHT | CD_MASK_FACEMAP;
const CustomDataMask CD_MASK_MESH =
CD_MASK_MVERT | CD_MASK_MEDGE |
CD_MASK_MDEFORMVERT |
CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_MDISPS |
CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MPOLY | CD_MASK_MLOOP |
- CD_MASK_MTEXPOLY | CD_MASK_RECAST | CD_MASK_PAINT_MASK |
+ CD_MASK_RECAST | CD_MASK_PAINT_MASK |
CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE |
- CD_MASK_CUSTOMLOOPNORMAL;
+ CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_FACEMAP;
const CustomDataMask CD_MASK_EDITMESH =
CD_MASK_MDEFORMVERT | CD_MASK_MLOOPUV |
- CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_SHAPE_KEYINDEX |
+ CD_MASK_MLOOPCOL | CD_MASK_SHAPE_KEYINDEX |
CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_PROP_STR |
CD_MASK_MDISPS | CD_MASK_SHAPEKEY | CD_MASK_RECAST | CD_MASK_PAINT_MASK |
- CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_CUSTOMLOOPNORMAL;
+ CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_FACEMAP;
const CustomDataMask CD_MASK_DERIVEDMESH =
CD_MASK_MDEFORMVERT |
CD_MASK_PROP_FLT | CD_MASK_PROP_INT | CD_MASK_CLOTH_ORCO |
- CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY | CD_MASK_PREVIEW_MLOOPCOL |
+ CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_PREVIEW_MLOOPCOL |
CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORIGSPACE_MLOOP | CD_MASK_ORCO | CD_MASK_TANGENT |
CD_MASK_PREVIEW_MCOL | CD_MASK_SHAPEKEY | CD_MASK_RECAST |
CD_MASK_ORIGINDEX | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE |
- CD_MASK_CUSTOMLOOPNORMAL;
+ CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_FACEMAP;
const CustomDataMask CD_MASK_BMESH =
- CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL | CD_MASK_MTEXPOLY |
+ CD_MASK_MLOOPUV | CD_MASK_MLOOPCOL |
CD_MASK_MDEFORMVERT | CD_MASK_PROP_FLT | CD_MASK_PROP_INT |
CD_MASK_PROP_STR | CD_MASK_SHAPEKEY | CD_MASK_SHAPE_KEYINDEX | CD_MASK_MDISPS |
CD_MASK_CREASE | CD_MASK_BWEIGHT | CD_MASK_RECAST | CD_MASK_PAINT_MASK |
CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN | CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE |
- CD_MASK_CUSTOMLOOPNORMAL;
+ CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_FACEMAP;
/**
* cover values copied by #BKE_mesh_loops_to_tessdata
*/
const CustomDataMask CD_MASK_FACECORNERS =
- CD_MASK_MTFACE | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV |
+ CD_MASK_MTFACE | CD_MASK_MLOOPUV |
CD_MASK_MCOL | CD_MASK_MLOOPCOL |
CD_MASK_PREVIEW_MCOL | CD_MASK_PREVIEW_MLOOPCOL |
CD_MASK_ORIGSPACE | CD_MASK_ORIGSPACE_MLOOP |
@@ -1368,7 +1358,7 @@ const CustomDataMask CD_MASK_FACECORNERS =
const CustomDataMask CD_MASK_EVERYTHING =
CD_MASK_MVERT | CD_MASK_MDEFORMVERT | CD_MASK_MEDGE | CD_MASK_MFACE |
CD_MASK_MTFACE | CD_MASK_MCOL | CD_MASK_ORIGINDEX | CD_MASK_NORMAL /* | CD_MASK_POLYINDEX */ | CD_MASK_PROP_FLT |
- CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV |
+ CD_MASK_PROP_INT | CD_MASK_PROP_STR | CD_MASK_ORIGSPACE | CD_MASK_ORCO | CD_MASK_MLOOPUV |
CD_MASK_MLOOPCOL | CD_MASK_TANGENT | CD_MASK_MDISPS | CD_MASK_PREVIEW_MCOL | CD_MASK_CLOTH_ORCO | CD_MASK_RECAST |
/* BMESH ONLY START */
CD_MASK_MPOLY | CD_MASK_MLOOP | CD_MASK_SHAPE_KEYINDEX | CD_MASK_SHAPEKEY | CD_MASK_BWEIGHT | CD_MASK_CREASE |
@@ -1376,7 +1366,7 @@ const CustomDataMask CD_MASK_EVERYTHING =
/* BMESH ONLY END */
CD_MASK_PAINT_MASK | CD_MASK_GRID_PAINT_MASK | CD_MASK_MVERT_SKIN |
CD_MASK_FREESTYLE_EDGE | CD_MASK_FREESTYLE_FACE |
- CD_MASK_MLOOPTANGENT | CD_MASK_TESSLOOPNORMAL | CD_MASK_CUSTOMLOOPNORMAL;
+ CD_MASK_MLOOPTANGENT | CD_MASK_TESSLOOPNORMAL | CD_MASK_CUSTOMLOOPNORMAL | CD_MASK_FACEMAP;
static const LayerTypeInfo *layerType_getInfo(int type)
{
@@ -2501,13 +2491,10 @@ void CustomData_set(const CustomData *data, int index, int type, const void *sou
/* BMesh functions */
/* needed to convert to/from different face reps */
-void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata,
- int totloop, int totpoly)
+void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *ldata, int totloop)
{
- int i;
- for (i = 0; i < fdata->totlayer; i++) {
+ for (int i = 0; i < fdata->totlayer; i++) {
if (fdata->layers[i].type == CD_MTFACE) {
- CustomData_add_layer_named(pdata, CD_MTEXPOLY, CD_CALLOC, NULL, totpoly, fdata->layers[i].name);
CustomData_add_layer_named(ldata, CD_MLOOPUV, CD_CALLOC, NULL, totloop, fdata->layers[i].name);
}
else if (fdata->layers[i].type == CD_MCOL) {
@@ -2522,19 +2509,18 @@ void CustomData_to_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *l
}
}
-void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData *ldata, int total)
+void CustomData_from_bmeshpoly(
+ CustomData *fdata, CustomData *ldata, int total)
{
int i;
/* avoid accumulating extra layers */
- BLI_assert(!CustomData_from_bmeshpoly_test(fdata, pdata, ldata, false));
+ BLI_assert(!CustomData_from_bmeshpoly_test(fdata, ldata, false));
- for (i = 0; i < pdata->totlayer; i++) {
- if (pdata->layers[i].type == CD_MTEXPOLY) {
- CustomData_add_layer_named(fdata, CD_MTFACE, CD_CALLOC, NULL, total, pdata->layers[i].name);
- }
- }
for (i = 0; i < ldata->totlayer; i++) {
+ if (ldata->layers[i].type == CD_MLOOPUV) {
+ CustomData_add_layer_named(fdata, CD_MTFACE, CD_CALLOC, NULL, total, ldata->layers[i].name);
+ }
if (ldata->layers[i].type == CD_MLOOPCOL) {
CustomData_add_layer_named(fdata, CD_MCOL, CD_CALLOC, NULL, total, ldata->layers[i].name);
}
@@ -2552,7 +2538,7 @@ void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData
}
}
- CustomData_bmesh_update_active_layers(fdata, pdata, ldata);
+ CustomData_bmesh_update_active_layers(fdata, ldata);
}
#ifndef NDEBUG
@@ -2562,13 +2548,13 @@ void CustomData_from_bmeshpoly(CustomData *fdata, CustomData *pdata, CustomData
* \param fallback: Use when there are no layers to handle,
* since callers may expect success or failure.
*/
-bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *pdata, CustomData *ldata, bool fallback)
+bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *ldata, bool fallback)
{
int a_num = 0, b_num = 0;
#define LAYER_CMP(l_a, t_a, l_b, t_b) \
((a_num += CustomData_number_of_layers(l_a, t_a)) == (b_num += CustomData_number_of_layers(l_b, t_b)))
- if (!LAYER_CMP(pdata, CD_MTEXPOLY, fdata, CD_MTFACE))
+ if (!LAYER_CMP(ldata, CD_MLOOPUV, fdata, CD_MTFACE))
return false;
if (!LAYER_CMP(ldata, CD_MLOOPCOL, fdata, CD_MCOL))
return false;
@@ -2590,25 +2576,21 @@ bool CustomData_from_bmeshpoly_test(CustomData *fdata, CustomData *pdata, Custom
#endif
-void CustomData_bmesh_update_active_layers(CustomData *fdata, CustomData *pdata, CustomData *ldata)
+void CustomData_bmesh_update_active_layers(CustomData *fdata, CustomData *ldata)
{
int act;
- if (CustomData_has_layer(pdata, CD_MTEXPOLY)) {
- act = CustomData_get_active_layer(pdata, CD_MTEXPOLY);
- CustomData_set_layer_active(ldata, CD_MLOOPUV, act);
+ if (CustomData_has_layer(ldata, CD_MLOOPUV)) {
+ act = CustomData_get_active_layer(ldata, CD_MLOOPUV);
CustomData_set_layer_active(fdata, CD_MTFACE, act);
- act = CustomData_get_render_layer(pdata, CD_MTEXPOLY);
- CustomData_set_layer_render(ldata, CD_MLOOPUV, act);
+ act = CustomData_get_render_layer(ldata, CD_MLOOPUV);
CustomData_set_layer_render(fdata, CD_MTFACE, act);
- act = CustomData_get_clone_layer(pdata, CD_MTEXPOLY);
- CustomData_set_layer_clone(ldata, CD_MLOOPUV, act);
+ act = CustomData_get_clone_layer(ldata, CD_MLOOPUV);
CustomData_set_layer_clone(fdata, CD_MTFACE, act);
- act = CustomData_get_stencil_layer(pdata, CD_MTEXPOLY);
- CustomData_set_layer_stencil(ldata, CD_MLOOPUV, act);
+ act = CustomData_get_stencil_layer(ldata, CD_MLOOPUV);
CustomData_set_layer_stencil(fdata, CD_MTFACE, act);
}
@@ -2632,25 +2614,21 @@ void CustomData_bmesh_update_active_layers(CustomData *fdata, CustomData *pdata,
* used by do_versions in readfile.c when creating pdata and ldata for pre-bmesh
* meshes and needed to preserve active/render/clone/stencil flags set in pre-bmesh files
*/
-void CustomData_bmesh_do_versions_update_active_layers(CustomData *fdata, CustomData *pdata, CustomData *ldata)
+void CustomData_bmesh_do_versions_update_active_layers(CustomData *fdata, CustomData *ldata)
{
int act;
if (CustomData_has_layer(fdata, CD_MTFACE)) {
act = CustomData_get_active_layer(fdata, CD_MTFACE);
- CustomData_set_layer_active(pdata, CD_MTEXPOLY, act);
CustomData_set_layer_active(ldata, CD_MLOOPUV, act);
act = CustomData_get_render_layer(fdata, CD_MTFACE);
- CustomData_set_layer_render(pdata, CD_MTEXPOLY, act);
CustomData_set_layer_render(ldata, CD_MLOOPUV, act);
act = CustomData_get_clone_layer(fdata, CD_MTFACE);
- CustomData_set_layer_clone(pdata, CD_MTEXPOLY, act);
CustomData_set_layer_clone(ldata, CD_MLOOPUV, act);
act = CustomData_get_stencil_layer(fdata, CD_MTFACE);
- CustomData_set_layer_stencil(pdata, CD_MTEXPOLY, act);
CustomData_set_layer_stencil(ldata, CD_MLOOPUV, act);
}
diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c
index 3bc09c0173b..00b8063110d 100644
--- a/source/blender/blenkernel/intern/data_transfer.c
+++ b/source/blender/blenkernel/intern/data_transfer.c
@@ -79,7 +79,7 @@ CustomDataMask BKE_object_data_transfer_dttypes_to_cdmask(const int dtdata_types
cddata_mask |= CD_MASK_MDEFORMVERT; /* Exception for vgroups :/ */
}
else if (cddata_type == CD_FAKE_UV) {
- cddata_mask |= CD_MASK_MTEXPOLY | CD_MASK_MLOOPUV;
+ cddata_mask |= CD_MASK_MLOOPUV;
}
else if (cddata_type == CD_FAKE_LNOR) {
cddata_mask |= CD_MASK_NORMAL | CD_MASK_CUSTOMLOOPNORMAL;
@@ -962,7 +962,7 @@ static bool data_transfer_layersmapping_generate(
}
else if (elem_type == ME_POLY) {
if (cddata_type == CD_FAKE_UV) {
- cddata_type = CD_MTEXPOLY;
+ cddata_type = CD_MLOOPUV;
}
if (!(cddata_type & CD_FAKE)) {
@@ -1010,7 +1010,8 @@ static bool data_transfer_layersmapping_generate(
* to get (as much as possible) exact copy of source data layout.
*/
void BKE_object_data_transfer_layout(
- Scene *scene, Object *ob_src, Object *ob_dst, const int data_types, const bool use_delete,
+ const struct EvaluationContext *eval_ctx, Scene *scene,
+ Object *ob_src, Object *ob_dst, const int data_types, const bool use_delete,
const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX])
{
DerivedMesh *dm_src;
@@ -1027,7 +1028,7 @@ void BKE_object_data_transfer_layout(
/* Get source DM.*/
dm_src_mask |= BKE_object_data_transfer_dttypes_to_cdmask(data_types);
- dm_src = mesh_get_derived_final(scene, ob_src, dm_src_mask);
+ dm_src = mesh_get_derived_final(eval_ctx, scene, ob_src, dm_src_mask);
if (!dm_src) {
return;
}
@@ -1085,9 +1086,9 @@ void BKE_object_data_transfer_layout(
}
bool BKE_object_data_transfer_dm(
- Scene *scene, Object *ob_src, Object *ob_dst, DerivedMesh *dm_dst, const int data_types, bool use_create,
- const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode,
- SpaceTransform *space_transform, const bool auto_transform,
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob_src, Object *ob_dst, DerivedMesh *dm_dst,
+ const int data_types, bool use_create, const int map_vert_mode, const int map_edge_mode,
+ const int map_loop_mode, const int map_poly_mode, SpaceTransform *space_transform, const bool auto_transform,
const float max_distance, const float ray_radius, const float islands_handling_precision,
const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX],
const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup,
@@ -1149,7 +1150,7 @@ bool BKE_object_data_transfer_dm(
* Also, we need to make a local copy of dm_src, otherwise we may end with concurrent creation
* of data in it (multi-threaded evaluation of the modifier stack, see T46672).
*/
- dm_src = dm_dst ? ob_src->derivedFinal : mesh_get_derived_final(scene, ob_src, dm_src_mask);
+ dm_src = dm_dst ? ob_src->derivedFinal : mesh_get_derived_final(eval_ctx, scene, ob_src, dm_src_mask);
if (!dm_src) {
return changed;
}
@@ -1457,16 +1458,16 @@ bool BKE_object_data_transfer_dm(
}
bool BKE_object_data_transfer_mesh(
- Scene *scene, Object *ob_src, Object *ob_dst, const int data_types, const bool use_create,
- const int map_vert_mode, const int map_edge_mode, const int map_loop_mode, const int map_poly_mode,
- SpaceTransform *space_transform, const bool auto_transform,
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob_src, Object *ob_dst, const int data_types,
+ const bool use_create, const int map_vert_mode, const int map_edge_mode, const int map_loop_mode,
+ const int map_poly_mode, SpaceTransform *space_transform, const bool auto_transform,
const float max_distance, const float ray_radius, const float islands_handling_precision,
const int fromlayers_select[DT_MULTILAYER_INDEX_MAX], const int tolayers_select[DT_MULTILAYER_INDEX_MAX],
const int mix_mode, const float mix_factor, const char *vgroup_name, const bool invert_vgroup,
ReportList *reports)
{
return BKE_object_data_transfer_dm(
- scene, ob_src, ob_dst, NULL, data_types, use_create,
+ eval_ctx, scene, ob_src, ob_dst, NULL, data_types, use_create,
map_vert_mode, map_edge_mode, map_loop_mode, map_poly_mode,
space_transform, auto_transform,
max_distance, ray_radius, islands_handling_precision,
diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c
index 22ff8bf4bb7..d4ff9bd5c0c 100644
--- a/source/blender/blenkernel/intern/deform.c
+++ b/source/blender/blenkernel/intern/deform.c
@@ -54,6 +54,7 @@
#include "BKE_customdata.h"
#include "BKE_data_transfer.h"
#include "BKE_deform.h" /* own include */
+#include "BKE_mesh.h"
#include "BKE_mesh_mapping.h"
#include "BKE_object_deform.h"
@@ -73,6 +74,8 @@ bDeformGroup *BKE_defgroup_new(Object *ob, const char *name)
BLI_addtail(&ob->defbase, defgroup);
defgroup_unique_name(defgroup, ob);
+ BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+
return defgroup;
}
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
deleted file mode 100644
index 149158b9f5d..00000000000
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ /dev/null
@@ -1,3739 +0,0 @@
-/*
- * ***** BEGIN GPL LICENSE BLOCK *****
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * The Original Code is Copyright (C) 2004 Blender Foundation.
- * All rights reserved.
- *
- * Contributor(s): none yet.
- *
- * ***** END GPL LICENSE BLOCK *****
- */
-
-/** \file blender/blenkernel/intern/depsgraph.c
- * \ingroup bke
- */
-
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-
-#include "MEM_guardedalloc.h"
-
-#ifdef WIN32
-# include "BLI_winstuff.h"
-#endif
-
-#include "BLI_utildefines.h"
-#include "BLI_listbase.h"
-#include "BLI_ghash.h"
-#include "BLI_threads.h"
-
-#include "DNA_anim_types.h"
-#include "DNA_camera_types.h"
-#include "DNA_cachefile_types.h"
-#include "DNA_group_types.h"
-#include "DNA_lamp_types.h"
-#include "DNA_lattice_types.h"
-#include "DNA_key_types.h"
-#include "DNA_material_types.h"
-#include "DNA_mesh_types.h"
-#include "DNA_node_types.h"
-#include "DNA_scene_types.h"
-#include "DNA_screen_types.h"
-#include "DNA_windowmanager_types.h"
-#include "DNA_movieclip_types.h"
-#include "DNA_mask_types.h"
-#include "DNA_modifier_types.h"
-#include "DNA_rigidbody_types.h"
-
-#include "BKE_anim.h"
-#include "BKE_animsys.h"
-#include "BKE_action.h"
-#include "BKE_DerivedMesh.h"
-#include "BKE_collision.h"
-#include "BKE_curve.h"
-#include "BKE_effect.h"
-#include "BKE_fcurve.h"
-#include "BKE_global.h"
-#include "BKE_idcode.h"
-#include "BKE_image.h"
-#include "BKE_key.h"
-#include "BKE_library.h"
-#include "BKE_main.h"
-#include "BKE_node.h"
-#include "BKE_material.h"
-#include "BKE_mball.h"
-#include "BKE_modifier.h"
-#include "BKE_object.h"
-#include "BKE_paint.h"
-#include "BKE_particle.h"
-#include "BKE_pointcache.h"
-#include "BKE_scene.h"
-#include "BKE_screen.h"
-#include "BKE_tracking.h"
-
-#include "GPU_buffers.h"
-
-#include "atomic_ops.h"
-
-#include "depsgraph_private.h"
-
-#include "DEG_depsgraph.h"
-#include "DEG_depsgraph_build.h"
-#include "DEG_depsgraph_debug.h"
-#include "DEG_depsgraph_query.h"
-
-#ifdef WITH_LEGACY_DEPSGRAPH
-
-static SpinLock threaded_update_lock;
-
-void DAG_init(void)
-{
- BLI_spin_init(&threaded_update_lock);
- DEG_register_node_types();
-}
-
-void DAG_exit(void)
-{
- BLI_spin_end(&threaded_update_lock);
- DEG_free_node_types();
-}
-
-/* Queue and stack operations for dag traversal
- *
- * the queue store a list of freenodes to avoid successive alloc/dealloc
- */
-
-DagNodeQueue *queue_create(int slots)
-{
- DagNodeQueue *queue;
- DagNodeQueueElem *elem;
- int i;
-
- queue = MEM_mallocN(sizeof(DagNodeQueue), "DAG queue");
- queue->freenodes = MEM_mallocN(sizeof(DagNodeQueue), "DAG queue");
- queue->count = 0;
- queue->maxlevel = 0;
- queue->first = queue->last = NULL;
- elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem3");
- elem->node = NULL;
- elem->next = NULL;
- queue->freenodes->first = queue->freenodes->last = elem;
-
- for (i = 1; i < slots; i++) {
- elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem4");
- elem->node = NULL;
- elem->next = NULL;
- queue->freenodes->last->next = elem;
- queue->freenodes->last = elem;
- }
- queue->freenodes->count = slots;
- return queue;
-}
-
-void queue_raz(DagNodeQueue *queue)
-{
- DagNodeQueueElem *elem;
-
- elem = queue->first;
- if (queue->freenodes->last)
- queue->freenodes->last->next = elem;
- else
- queue->freenodes->first = queue->freenodes->last = elem;
-
- elem->node = NULL;
- queue->freenodes->count++;
- while (elem->next) {
- elem = elem->next;
- elem->node = NULL;
- queue->freenodes->count++;
- }
- queue->freenodes->last = elem;
- queue->count = 0;
-}
-
-void queue_delete(DagNodeQueue *queue)
-{
- DagNodeQueueElem *elem;
- DagNodeQueueElem *temp;
-
- elem = queue->first;
- while (elem) {
- temp = elem;
- elem = elem->next;
- MEM_freeN(temp);
- }
-
- elem = queue->freenodes->first;
- while (elem) {
- temp = elem;
- elem = elem->next;
- MEM_freeN(temp);
- }
-
- MEM_freeN(queue->freenodes);
- MEM_freeN(queue);
-}
-
-/* insert in queue, remove in front */
-void push_queue(DagNodeQueue *queue, DagNode *node)
-{
- DagNodeQueueElem *elem;
- int i;
-
- if (node == NULL) {
- fprintf(stderr, "pushing null node\n");
- return;
- }
- /*fprintf(stderr, "BFS push : %s %d\n", ((ID *) node->ob)->name, queue->count);*/
-
- elem = queue->freenodes->first;
- if (elem != NULL) {
- queue->freenodes->first = elem->next;
- if (queue->freenodes->last == elem) {
- queue->freenodes->last = NULL;
- queue->freenodes->first = NULL;
- }
- queue->freenodes->count--;
- }
- else { /* alllocating more */
- elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem1");
- elem->node = NULL;
- elem->next = NULL;
- queue->freenodes->first = queue->freenodes->last = elem;
-
- for (i = 1; i < DAGQUEUEALLOC; i++) {
- elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem2");
- elem->node = NULL;
- elem->next = NULL;
- queue->freenodes->last->next = elem;
- queue->freenodes->last = elem;
- }
- queue->freenodes->count = DAGQUEUEALLOC;
-
- elem = queue->freenodes->first;
- queue->freenodes->first = elem->next;
- }
- elem->next = NULL;
- elem->node = node;
- if (queue->last != NULL)
- queue->last->next = elem;
- queue->last = elem;
- if (queue->first == NULL) {
- queue->first = elem;
- }
- queue->count++;
-}
-
-
-/* insert in front, remove in front */
-void push_stack(DagNodeQueue *queue, DagNode *node)
-{
- DagNodeQueueElem *elem;
- int i;
-
- elem = queue->freenodes->first;
- if (elem != NULL) {
- queue->freenodes->first = elem->next;
- if (queue->freenodes->last == elem) {
- queue->freenodes->last = NULL;
- queue->freenodes->first = NULL;
- }
- queue->freenodes->count--;
- }
- else { /* alllocating more */
- elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem1");
- elem->node = NULL;
- elem->next = NULL;
- queue->freenodes->first = queue->freenodes->last = elem;
-
- for (i = 1; i < DAGQUEUEALLOC; i++) {
- elem = MEM_mallocN(sizeof(DagNodeQueueElem), "DAG queue elem2");
- elem->node = NULL;
- elem->next = NULL;
- queue->freenodes->last->next = elem;
- queue->freenodes->last = elem;
- }
- queue->freenodes->count = DAGQUEUEALLOC;
-
- elem = queue->freenodes->first;
- queue->freenodes->first = elem->next;
- }
- elem->next = queue->first;
- elem->node = node;
- queue->first = elem;
- if (queue->last == NULL)
- queue->last = elem;
- queue->count++;
-}
-
-
-DagNode *pop_queue(DagNodeQueue *queue)
-{
- DagNodeQueueElem *elem;
- DagNode *node;
-
- elem = queue->first;
- if (elem) {
- queue->first = elem->next;
- if (queue->last == elem) {
- queue->last = NULL;
- queue->first = NULL;
- }
- queue->count--;
- if (queue->freenodes->last)
- queue->freenodes->last->next = elem;
- queue->freenodes->last = elem;
- if (queue->freenodes->first == NULL)
- queue->freenodes->first = elem;
- node = elem->node;
- elem->node = NULL;
- elem->next = NULL;
- queue->freenodes->count++;
- return node;
- }
- else {
- fprintf(stderr, "return null\n");
- return NULL;
- }
-}
-
-DagNode *get_top_node_queue(DagNodeQueue *queue)
-{
- return queue->first->node;
-}
-
-DagForest *dag_init(void)
-{
- DagForest *forest;
- /* use callocN to init all zero */
- forest = MEM_callocN(sizeof(DagForest), "DAG root");
- forest->ugly_hack_sorry = true;
- return forest;
-}
-
-/* isdata = object data... */
-/* XXX this needs to be extended to be more flexible (so that not only objects are evaluated via depsgraph)... */
-static void dag_add_driver_relation(AnimData *adt, DagForest *dag, DagNode *node, int isdata)
-{
- FCurve *fcu;
- DagNode *node1;
-
- for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
- ChannelDriver *driver = fcu->driver;
- DriverVar *dvar;
- int isdata_fcu = (isdata) || (fcu->rna_path && strstr(fcu->rna_path, "modifiers["));
-
- /* loop over variables to get the target relationships */
- for (dvar = driver->variables.first; dvar; dvar = dvar->next) {
- /* only used targets */
- DRIVER_TARGETS_USED_LOOPER(dvar)
- {
- if (dtar->id) {
- /* FIXME: other data types need to be added here so that they can work! */
- if (GS(dtar->id->name) == ID_OB) {
- Object *ob = (Object *)dtar->id;
-
- /* normal channel-drives-channel */
- node1 = dag_get_node(dag, dtar->id);
-
- /* check if bone... */
- if ((ob->type == OB_ARMATURE) &&
- ( ((dtar->rna_path) && strstr(dtar->rna_path, "pose.bones[")) ||
- ((dtar->flag & DTAR_FLAG_STRUCT_REF) && (dtar->pchan_name[0])) ))
- {
- dag_add_relation(dag, node1, node, isdata_fcu ? DAG_RL_DATA_DATA : DAG_RL_DATA_OB, "Driver");
- }
- /* check if ob data */
- else if (dtar->rna_path && strstr(dtar->rna_path, "data."))
- dag_add_relation(dag, node1, node, isdata_fcu ? DAG_RL_DATA_DATA : DAG_RL_DATA_OB, "Driver");
- /* normal */
- else
- dag_add_relation(dag, node1, node, isdata_fcu ? DAG_RL_OB_DATA : DAG_RL_OB_OB, "Driver");
- }
- }
- }
- DRIVER_TARGETS_LOOPER_END
- }
- }
-}
-
-/* XXX: forward def for material driver handling... */
-static void dag_add_material_driver_relations(DagForest *dag, DagNode *node, Material *ma);
-
-/* recursive handling for shader nodetree drivers */
-static void dag_add_shader_nodetree_driver_relations(DagForest *dag, DagNode *node, bNodeTree *ntree)
-{
- bNode *n;
-
- /* nodetree itself */
- if (ntree->adt) {
- dag_add_driver_relation(ntree->adt, dag, node, 1);
- }
-
- /* nodetree's nodes... */
- for (n = ntree->nodes.first; n; n = n->next) {
- if (n->id) {
- if (GS(n->id->name) == ID_MA) {
- dag_add_material_driver_relations(dag, node, (Material *)n->id);
- }
- else if (n->type == NODE_GROUP) {
- dag_add_shader_nodetree_driver_relations(dag, node, (bNodeTree *)n->id);
- }
- }
- }
-}
-
-/* recursive handling for material drivers */
-static void dag_add_material_driver_relations(DagForest *dag, DagNode *node, Material *ma)
-{
- /* Prevent infinite recursion by checking (and tagging the material) as having been visited
- * already (see build_dag()). This assumes ma->id.tag & LIB_TAG_DOIT isn't set by anything else
- * in the meantime... [#32017]
- */
- if (ma->id.tag & LIB_TAG_DOIT)
- return;
-
- ma->id.tag |= LIB_TAG_DOIT;
-
- /* material itself */
- if (ma->adt)
- dag_add_driver_relation(ma->adt, dag, node, 1);
-
- /* textures */
- // TODO...
- //dag_add_texture_driver_relations(DagForest *dag, DagNode *node, ID *id);
-
- /* material's nodetree */
- if (ma->nodetree)
- dag_add_shader_nodetree_driver_relations(dag, node, ma->nodetree);
-
- ma->id.tag &= ~LIB_TAG_DOIT;
-}
-
-/* recursive handling for lamp drivers */
-static void dag_add_lamp_driver_relations(DagForest *dag, DagNode *node, Lamp *la)
-{
- /* Prevent infinite recursion by checking (and tagging the lamp) as having been visited
- * already (see build_dag()). This assumes la->id.tag & LIB_TAG_DOIT isn't set by anything else
- * in the meantime... [#32017]
- */
- if (la->id.tag & LIB_TAG_DOIT)
- return;
-
- la->id.tag |= LIB_TAG_DOIT;
-
- /* lamp itself */
- if (la->adt)
- dag_add_driver_relation(la->adt, dag, node, 1);
-
- /* textures */
- // TODO...
- //dag_add_texture_driver_relations(DagForest *dag, DagNode *node, ID *id);
-
- /* lamp's nodetree */
- if (la->nodetree)
- dag_add_shader_nodetree_driver_relations(dag, node, la->nodetree);
-
- la->id.tag &= ~LIB_TAG_DOIT;
-}
-
-static void create_collision_relation(DagForest *dag, DagNode *node, Object *ob1, const char *name)
-{
- DagNode *node2 = dag_get_node(dag, ob1);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, name);
-}
-
-void dag_add_collision_relations(DagForest *dag, Scene *scene, Object *ob, DagNode *node, Group *group, int layer, unsigned int modifier_type, DagCollobjFilterFunction fn, bool dupli, const char *name)
-{
- unsigned int numcollobj;
- Object **collobjs = get_collisionobjects_ext(scene, ob, group, layer, &numcollobj, modifier_type, dupli);
-
- for (unsigned int i = 0; i < numcollobj; i++) {
- Object *ob1 = collobjs[i];
-
- if (!fn || fn(ob1, modifiers_findByType(ob1, modifier_type))) {
- create_collision_relation(dag, node, ob1, name);
- }
- }
-
- if (collobjs)
- MEM_freeN(collobjs);
-}
-
-void dag_add_forcefield_relations(DagForest *dag, Scene *scene, Object *ob, DagNode *node, EffectorWeights *effector_weights, bool add_absorption, int skip_forcefield, const char *name)
-{
- ListBase *effectors = pdInitEffectors(scene, ob, NULL, effector_weights, false);
-
- if (effectors) {
- for (EffectorCache *eff = effectors->first; eff; eff = eff->next) {
- if (eff->ob != ob && eff->pd->forcefield != skip_forcefield) {
- create_collision_relation(dag, node, eff->ob, name);
-
- if (eff->pd->forcefield == PFIELD_SMOKEFLOW && eff->pd->f_source) {
- create_collision_relation(dag, node, eff->pd->f_source, "Smoke Force Domain");
- }
-
- if (add_absorption && (eff->pd->flag & PFIELD_VISIBILITY)) {
- /* Actual code uses get_collider_cache */
- dag_add_collision_relations(dag, scene, ob, node, NULL, eff->ob->lay, eModifierType_Collision, NULL, true, "Force Absorption");
- }
- }
- }
- }
-
- pdEndEffectors(&effectors);
-}
-
-static bool build_deg_tracking_constraints(DagForest *dag,
- Scene *scene,
- DagNode *scenenode,
- bConstraint *con,
- const bConstraintTypeInfo *cti,
- DagNode *node,
- bool is_data)
-{
- if (!ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK,
- CONSTRAINT_TYPE_CAMERASOLVER,
- CONSTRAINT_TYPE_OBJECTSOLVER))
- {
- return false;
- }
- bool depends_on_camera = false;
- if (cti->type == CONSTRAINT_TYPE_FOLLOWTRACK) {
- bFollowTrackConstraint *data = (bFollowTrackConstraint *)con->data;
- if ((data->clip || data->flag & FOLLOWTRACK_ACTIVECLIP) && data->track[0]) {
- depends_on_camera = true;
- }
- if (data->depth_ob != NULL) {
- DagNode *node2 = dag_get_node(dag, data->depth_ob);
- dag_add_relation(dag,
- node2, node,
- (is_data) ? (DAG_RL_DATA_DATA | DAG_RL_OB_DATA)
- : (DAG_RL_DATA_OB | DAG_RL_OB_OB),
- cti->name);
- }
- }
- else if (cti->type == CONSTRAINT_TYPE_OBJECTSOLVER) {
- depends_on_camera = true;
- }
- if (depends_on_camera && scene->camera != NULL) {
- DagNode *node2 = dag_get_node(dag, scene->camera);
- dag_add_relation(dag,
- node2, node,
- (is_data) ? (DAG_RL_DATA_DATA | DAG_RL_OB_DATA)
- : (DAG_RL_DATA_OB | DAG_RL_OB_OB),
- cti->name);
- }
- dag_add_relation(dag, scenenode, node, DAG_RL_SCENE, "Scene Relation");
- return true;
-}
-
-static void build_dag_object(DagForest *dag, DagNode *scenenode, Main *bmain, Scene *scene, Object *ob, int mask)
-{
- bConstraint *con;
- DagNode *node;
- DagNode *node2;
- DagNode *node3;
- Key *key;
- ParticleSystem *psys;
- int addtoroot = 1;
-
- node = dag_get_node(dag, ob);
-
- if ((ob->data) && (mask & DAG_RL_DATA)) {
- node2 = dag_get_node(dag, ob->data);
- dag_add_relation(dag, node, node2, DAG_RL_DATA, "Object-Data Relation");
- node2->first_ancestor = ob;
- node2->ancestor_count += 1;
- }
-
- /* also build a custom data mask for dependencies that need certain layers */
-
- if (ob->type == OB_ARMATURE) {
- if (ob->pose) {
- bPoseChannel *pchan;
-
- for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
- for (con = pchan->constraints.first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- if (!cti) {
- continue;
- }
-
- if (build_deg_tracking_constraints(dag, scene, scenenode, con, cti, node, true)) {
- /* pass */
- }
- else if (cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- if (ct->tar && ct->tar != ob) {
- // fprintf(stderr, "armature %s target :%s\n", ob->id.name, target->id.name);
- node3 = dag_get_node(dag, ct->tar);
-
- if (ct->subtarget[0]) {
- dag_add_relation(dag, node3, node, DAG_RL_OB_DATA | DAG_RL_DATA_DATA, cti->name);
- if (ct->tar->type == OB_MESH)
- node3->customdata_mask |= CD_MASK_MDEFORMVERT;
- }
- else if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH,
- CONSTRAINT_TYPE_CLAMPTO,
- CONSTRAINT_TYPE_SPLINEIK,
- CONSTRAINT_TYPE_SHRINKWRAP))
- {
- dag_add_relation(dag, node3, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, cti->name);
- }
- else {
- dag_add_relation(dag, node3, node, DAG_RL_OB_DATA, cti->name);
- }
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 1);
- }
-
- }
- }
- }
- }
-
- /* driver dependencies, nla modifiers */
-#if 0 // XXX old animation system
- if (ob->nlastrips.first) {
- bActionStrip *strip;
- bActionChannel *chan;
- for (strip = ob->nlastrips.first; strip; strip = strip->next) {
- if (strip->modifiers.first) {
- bActionModifier *amod;
- for (amod = strip->modifiers.first; amod; amod = amod->next) {
- if (amod->ob) {
- node2 = dag_get_node(dag, amod->ob);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "NLA Strip Modifier");
- }
- }
- }
- }
- }
-#endif // XXX old animation system
- if (ob->adt)
- dag_add_driver_relation(ob->adt, dag, node, (ob->type == OB_ARMATURE)); // XXX isdata arg here doesn't give an accurate picture of situation
-
- key = BKE_key_from_object(ob);
- if (key && key->adt)
- dag_add_driver_relation(key->adt, dag, node, 1);
-
- if (ob->modifiers.first) {
- ModifierData *md;
-
- for (md = ob->modifiers.first; md; md = md->next) {
- const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
-
- if (mti->updateDepgraph) mti->updateDepgraph(md, dag, bmain, scene, ob, node);
- }
- }
- if (ob->parent) {
- node2 = dag_get_node(dag, ob->parent);
-
- switch (ob->partype) {
- case PARSKEL:
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_OB, "Parent");
- break;
- case PARVERT1: case PARVERT3:
- dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, "Vertex Parent");
- node2->customdata_mask |= CD_MASK_ORIGINDEX;
- break;
- case PARBONE:
- dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, "Bone Parent");
- break;
- default:
- if (ob->parent->type == OB_LATTICE)
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_OB, "Lattice Parent");
- else if (ob->parent->type == OB_CURVE) {
- Curve *cu = ob->parent->data;
- if (cu->flag & CU_PATH)
- dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, "Curve Parent");
- else
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Curve Parent");
- }
- else
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Parent");
- break;
- }
- /* exception case: parent is duplivert */
- if (ob->type == OB_MBALL && (ob->parent->transflag & OB_DUPLIVERTS)) {
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_OB, "Duplivert");
- }
-
- addtoroot = 0;
- }
- if (ob->proxy) {
- node2 = dag_get_node(dag, ob->proxy);
- dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA | DAG_RL_OB_OB, "Proxy");
- /* inverted relation, so addtoroot shouldn't be set to zero */
- }
-
- if (ob->transflag & OB_DUPLI) {
- if ((ob->transflag & OB_DUPLIGROUP) && ob->dup_group) {
- GroupObject *go;
- for (go = ob->dup_group->gobject.first; go; go = go->next) {
- if (go->ob) {
- node2 = dag_get_node(dag, go->ob);
- /* node2 changes node1, this keeps animations updated in groups?? not logical? */
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Dupligroup");
- }
- }
- }
- }
-
- /* rigidbody force fields */
- if ((ob->type == OB_MESH) || (ob->type == OB_CURVE) || (ob->type == OB_LATTICE)) {
- if (ob->rigidbody_object && scene->rigidbody_world) {
- dag_add_forcefield_relations(dag, scene, ob, node, scene->rigidbody_world->effector_weights, true, 0, "Force Field");
- }
- }
-
- /* object data drivers */
- if (ob->data) {
- AnimData *adt = BKE_animdata_from_id((ID *)ob->data);
- if (adt)
- dag_add_driver_relation(adt, dag, node, 1);
- }
-
- /* object type/data relationships */
- switch (ob->type) {
- case OB_CAMERA:
- {
- Camera *cam = (Camera *)ob->data;
-
- if (cam->dof_ob) {
- node2 = dag_get_node(dag, cam->dof_ob);
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Camera DoF");
- }
- break;
- }
- case OB_MBALL:
- {
- Object *mom = BKE_mball_basis_find(scene, ob);
-
- if (mom != ob) {
- node2 = dag_get_node(dag, mom);
- dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Metaball"); /* mom depends on children! */
- }
- break;
- }
- case OB_CURVE:
- case OB_FONT:
- {
- Curve *cu = ob->data;
-
- if (cu->bevobj) {
- node2 = dag_get_node(dag, cu->bevobj);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Curve Bevel");
- }
- if (cu->taperobj) {
- node2 = dag_get_node(dag, cu->taperobj);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Curve Taper");
- }
- if (ob->type == OB_FONT) {
- /* Really rather dirty hack. needs to support font family to work
- * reliably on render export.
- *
- * This totally mimics behavior of regular verts duplication with
- * parenting. The only tricky thing here is to get list of objects
- * used for the custom "font".
- *
- * This shouldn't harm so much because this code only runs on DAG
- * rebuild and this feature is not that commonly used.
- *
- * - sergey -
- */
- if (cu->family[0] != '\n') {
- ListBase *duplilist;
- DupliObject *dob;
- duplilist = object_duplilist(G.main->eval_ctx, scene, ob);
- for (dob = duplilist->first; dob; dob = dob->next) {
- node2 = dag_get_node(dag, dob->ob);
- dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Object Font");
- }
- free_object_duplilist(duplilist);
- }
-
- if (cu->textoncurve) {
- node2 = dag_get_node(dag, cu->textoncurve);
- /* Text on curve requires path to be evaluated for the target curve. */
- node2->eval_flags |= DAG_EVAL_NEED_CURVE_PATH;
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Texture On Curve");
- }
- }
- break;
- }
- }
-
- /* material drivers */
- if (ob->totcol) {
- int a;
-
- for (a = 1; a <= ob->totcol; a++) {
- Material *ma = give_current_material(ob, a);
-
- if (ma) {
- /* recursively figure out if there are drivers, and hook these up to this object */
- dag_add_material_driver_relations(dag, node, ma);
- }
- }
- }
- else if (ob->type == OB_LAMP) {
- dag_add_lamp_driver_relations(dag, node, ob->data);
- }
-
- /* particles */
- psys = ob->particlesystem.first;
- if (psys) {
- GroupObject *go;
-
- for (; psys; psys = psys->next) {
- BoidRule *rule = NULL;
- BoidState *state = NULL;
- ParticleSettings *part = psys->part;
-
- if (part->adt) {
- dag_add_driver_relation(part->adt, dag, node, 1);
- }
-
- dag_add_relation(dag, node, node, DAG_RL_OB_DATA, "Particle-Object Relation");
-
- if (!psys_check_enabled(ob, psys, G.is_rendering))
- continue;
-
- if (ELEM(part->phystype, PART_PHYS_KEYED, PART_PHYS_BOIDS)) {
- ParticleTarget *pt = psys->targets.first;
-
- for (; pt; pt = pt->next) {
- if (pt->ob && BLI_findlink(&pt->ob->particlesystem, pt->psys - 1)) {
- node2 = dag_get_node(dag, pt->ob);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, "Particle Targets");
- }
- }
- }
-
- if (part->ren_as == PART_DRAW_OB && part->dup_ob) {
- node2 = dag_get_node(dag, part->dup_ob);
- /* note that this relation actually runs in the wrong direction, the problem
- * is that dupli system all have this (due to parenting), and the render
- * engine instancing assumes particular ordering of objects in list */
- dag_add_relation(dag, node, node2, DAG_RL_OB_OB, "Particle Object Visualization");
- if (part->dup_ob->type == OB_MBALL)
- dag_add_relation(dag, node, node2, DAG_RL_DATA_DATA, "Particle Object Visualization");
- }
-
- if (part->ren_as == PART_DRAW_GR && part->dup_group) {
- for (go = part->dup_group->gobject.first; go; go = go->next) {
- node2 = dag_get_node(dag, go->ob);
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, "Particle Group Visualization");
- }
- }
-
- if (part->type != PART_HAIR) {
- /* Actual code uses get_collider_cache */
- dag_add_collision_relations(dag, scene, ob, node, part->collision_group, ob->lay, eModifierType_Collision, NULL, true, "Particle Collision");
- }
- else if ((psys->flag & PSYS_HAIR_DYNAMICS) && psys->clmd && psys->clmd->coll_parms) {
- /* Hair uses cloth simulation, i.e. get_collision_objects */
- dag_add_collision_relations(dag, scene, ob, node, psys->clmd->coll_parms->group, ob->lay | scene->lay, eModifierType_Collision, NULL, true, "Hair Collision");
- }
-
- dag_add_forcefield_relations(dag, scene, ob, node, part->effector_weights, part->type == PART_HAIR, 0, "Particle Force Field");
-
- if (part->boids) {
- for (state = part->boids->states.first; state; state = state->next) {
- for (rule = state->rules.first; rule; rule = rule->next) {
- Object *ruleob = NULL;
- if (rule->type == eBoidRuleType_Avoid)
- ruleob = ((BoidRuleGoalAvoid *)rule)->ob;
- else if (rule->type == eBoidRuleType_FollowLeader)
- ruleob = ((BoidRuleFollowLeader *)rule)->ob;
-
- if (ruleob) {
- node2 = dag_get_node(dag, ruleob);
- dag_add_relation(dag, node2, node, DAG_RL_OB_DATA, "Boid Rule");
- }
- }
- }
- }
- }
- }
-
- /* object constraints */
- for (con = ob->constraints.first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- if (!cti)
- continue;
-
- /* special case for camera tracking -- it doesn't use targets to define relations */
- if (build_deg_tracking_constraints(dag, scene, scenenode, con, cti, node, false)) {
- addtoroot = 0;
- }
- else if (cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- Object *obt;
-
- if (ct->tar)
- obt = ct->tar;
- else
- continue;
-
- node2 = dag_get_node(dag, obt);
- if (ELEM(con->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO))
- dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, cti->name);
- else {
- if (ELEM(obt->type, OB_ARMATURE, OB_MESH, OB_LATTICE) && (ct->subtarget[0])) {
- dag_add_relation(dag, node2, node, DAG_RL_DATA_OB | DAG_RL_OB_OB, cti->name);
- if (obt->type == OB_MESH)
- node2->customdata_mask |= CD_MASK_MDEFORMVERT;
- }
- else if (cti->type == CONSTRAINT_TYPE_SHRINKWRAP) {
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA | DAG_RL_OB_DATA, cti->name);
- }
- else {
- dag_add_relation(dag, node2, node, DAG_RL_OB_OB, cti->name);
- }
- }
- addtoroot = 0;
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 1);
- }
- }
-
- if (addtoroot == 1)
- dag_add_relation(dag, scenenode, node, DAG_RL_SCENE, "Scene Relation");
-}
-
-static void build_dag_group(DagForest *dag, DagNode *scenenode, Main *bmain, Scene *scene, Group *group, short mask)
-{
- GroupObject *go;
-
- if (group->id.tag & LIB_TAG_DOIT)
- return;
-
- group->id.tag |= LIB_TAG_DOIT;
-
- for (go = group->gobject.first; go; go = go->next) {
- build_dag_object(dag, scenenode, bmain, scene, go->ob, mask);
- if (go->ob->dup_group)
- build_dag_group(dag, scenenode, bmain, scene, go->ob->dup_group, mask);
- }
-}
-
-DagForest *build_dag(Main *bmain, Scene *sce, short mask)
-{
- Base *base;
- Object *ob;
- DagNode *node;
- DagNode *scenenode;
- DagForest *dag;
- DagAdjList *itA;
-
- dag = sce->theDag;
- if (dag)
- free_forest(dag);
- else {
- dag = dag_init();
- sce->theDag = dag;
- }
- dag->need_update = false;
-
- BKE_main_id_tag_idcode(bmain, ID_OB, LIB_TAG_DOIT, false);
-
- /* clear "LIB_TAG_DOIT" flag from all materials, to prevent infinite recursion problems later [#32017] */
- BKE_main_id_tag_idcode(bmain, ID_MA, LIB_TAG_DOIT, false);
- BKE_main_id_tag_idcode(bmain, ID_LA, LIB_TAG_DOIT, false);
- BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false);
-
- /* add base node for scene. scene is always the first node in DAG */
- scenenode = dag_add_node(dag, sce);
-
- /* add current scene objects */
- for (base = sce->base.first; base; base = base->next) {
- ob = base->object;
- ob->id.tag |= LIB_TAG_DOIT;
- build_dag_object(dag, scenenode, bmain, sce, ob, mask);
- if (ob->proxy)
- build_dag_object(dag, scenenode, bmain, sce, ob->proxy, mask);
- if (ob->dup_group)
- build_dag_group(dag, scenenode, bmain, sce, ob->dup_group, mask);
- }
-
- /* There might be situations when object from current scene depends on
- * objects form other scene AND objects from other scene has own
- * dependencies on objects from other scene.
- *
- * This is really important to include such indirect dependencies in order
- * to keep threaded update safe but since we don't really know if object is
- * coming from current scene or another scene we do rather stupid tag-based
- * check here: all the objects for which build_dag_object() was called are
- * getting tagged with LIB_TAG_DOIT. This way if some node has untagged
- * object we know it's an object from other scene.
- *
- * It should be enough to to it once, because if there's longer chain of
- * indirect dependencies, all the new nodes will be added to the end of the
- * list, meaning we'll keep covering them in this for loop.
- */
- for (node = sce->theDag->DagNode.first; node != NULL; node = node->next) {
- if (node->type == ID_OB) {
- ob = node->ob;
- if ((ob->id.tag & LIB_TAG_DOIT) == 0) {
- ob->id.tag |= LIB_TAG_DOIT;
- build_dag_object(dag, scenenode, bmain, sce, ob, mask);
- if (ob->proxy)
- build_dag_object(dag, scenenode, bmain, sce, ob->proxy, mask);
- if (ob->dup_group)
- build_dag_group(dag, scenenode, bmain, sce, ob->dup_group, mask);
- }
- }
- }
-
- BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false);
-
- /* Now all relations were built, but we need to solve 1 exceptional case;
- * When objects have multiple "parents" (for example parent + constraint working on same object)
- * the relation type has to be synced. One of the parents can change, and should give same event to child */
-
- /* nodes were callocced, so we can use node->color for temporal storage */
- for (node = sce->theDag->DagNode.first; node; node = node->next) {
- if (node->type == ID_OB) {
- for (itA = node->child; itA; itA = itA->next) {
- if (itA->node->type == ID_OB) {
- itA->node->color |= itA->type;
- }
- }
-
- /* also flush custom data mask */
- ((Object *)node->ob)->customdata_mask = node->customdata_mask;
-
- if (node->parent == NULL) {
- dag_add_relation(dag, scenenode, node, DAG_RL_SCENE, "Scene Relation");
- }
- }
- }
- /* now set relations equal, so that when only one parent changes, the correct recalcs are found */
- for (node = sce->theDag->DagNode.first; node; node = node->next) {
- if (node->type == ID_OB) {
- for (itA = node->child; itA; itA = itA->next) {
- if (itA->node->type == ID_OB) {
- itA->type |= itA->node->color;
- }
- }
- }
- }
-
- /* cycle detection and solving */
- // solve_cycles(dag);
-
- return dag;
-}
-
-
-void free_forest(DagForest *Dag)
-{ /* remove all nodes and deps */
- DagNode *tempN;
- DagAdjList *tempA;
- DagAdjList *itA;
- DagNode *itN = Dag->DagNode.first;
-
- while (itN) {
- itA = itN->child;
- while (itA) {
- tempA = itA;
- itA = itA->next;
- MEM_freeN(tempA);
- }
-
- itA = itN->parent;
- while (itA) {
- tempA = itA;
- itA = itA->next;
- MEM_freeN(tempA);
- }
-
- tempN = itN;
- itN = itN->next;
- MEM_freeN(tempN);
- }
-
- BLI_ghash_free(Dag->nodeHash, NULL, NULL);
- Dag->nodeHash = NULL;
- Dag->DagNode.first = NULL;
- Dag->DagNode.last = NULL;
- Dag->numNodes = 0;
-
-}
-
-DagNode *dag_find_node(DagForest *forest, void *fob)
-{
- if (forest->nodeHash)
- return BLI_ghash_lookup(forest->nodeHash, fob);
-
- return NULL;
-}
-
-static int dag_print_dependencies = 0; /* debugging */
-
-/* no checking of existence, use dag_find_node first or dag_get_node */
-DagNode *dag_add_node(DagForest *forest, void *fob)
-{
- DagNode *node;
-
- node = MEM_callocN(sizeof(DagNode), "DAG node");
- if (node) {
- node->ob = fob;
- node->color = DAG_WHITE;
-
- if (forest->ugly_hack_sorry) node->type = GS(((ID *) fob)->name); /* sorry, done for pose sorting */
- if (forest->numNodes) {
- ((DagNode *) forest->DagNode.last)->next = node;
- forest->DagNode.last = node;
- forest->numNodes++;
- }
- else {
- forest->DagNode.last = node;
- forest->DagNode.first = node;
- forest->numNodes = 1;
- }
-
- if (!forest->nodeHash)
- forest->nodeHash = BLI_ghash_ptr_new("dag_add_node gh");
- BLI_ghash_insert(forest->nodeHash, fob, node);
- }
-
- return node;
-}
-
-DagNode *dag_get_node(DagForest *forest, void *fob)
-{
- DagNode *node;
-
- node = dag_find_node(forest, fob);
- if (!node)
- node = dag_add_node(forest, fob);
- return node;
-}
-
-
-
-DagNode *dag_get_sub_node(DagForest *forest, void *fob)
-{
- DagNode *node;
- DagAdjList *mainchild, *prev = NULL;
-
- mainchild = ((DagNode *) forest->DagNode.first)->child;
- /* remove from first node (scene) adj list if present */
- while (mainchild) {
- if (mainchild->node == fob) {
- if (prev) {
- prev->next = mainchild->next;
- MEM_freeN(mainchild);
- break;
- }
- else {
- ((DagNode *) forest->DagNode.first)->child = mainchild->next;
- MEM_freeN(mainchild);
- break;
- }
- }
- prev = mainchild;
- mainchild = mainchild->next;
- }
- node = dag_find_node(forest, fob);
- if (!node)
- node = dag_add_node(forest, fob);
- return node;
-}
-
-static void dag_add_parent_relation(DagForest *UNUSED(forest), DagNode *fob1, DagNode *fob2, short rel, const char *name)
-{
- DagAdjList *itA = fob2->parent;
-
- while (itA) { /* search if relation exist already */
- if (itA->node == fob1) {
- itA->type |= rel;
- itA->count += 1;
- return;
- }
- itA = itA->next;
- }
- /* create new relation and insert at head. MALLOC alert! */
- itA = MEM_mallocN(sizeof(DagAdjList), "DAG adj list");
- itA->node = fob1;
- itA->type = rel;
- itA->count = 1;
- itA->next = fob2->parent;
- itA->name = name;
- fob2->parent = itA;
-}
-
-void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, const char *name)
-{
- DagAdjList *itA = fob1->child;
-
- /* parent relation is for cycle checking */
- dag_add_parent_relation(forest, fob1, fob2, rel, name);
-
- /* TODO(sergey): Find a better place for this. */
-#ifdef WITH_OPENSUBDIV
- if ((rel & (DAG_RL_DATA_DATA | DAG_RL_DATA_OB)) != 0) {
- if (fob1->type == ID_OB) {
- if ((fob1->eval_flags & DAG_EVAL_NEED_CPU) == 0) {
- Object *ob2 = fob2->ob;
- if (ob2->recalc & OB_RECALC_ALL) {
- /* Make sure object has all the data on CPU. */
- Object *ob1 = fob1->ob;
- ob1->recalc |= OB_RECALC_DATA;
- }
- fob1->eval_flags |= DAG_EVAL_NEED_CPU;
- }
- }
- }
-#endif
-
- while (itA) { /* search if relation exist already */
- if (itA->node == fob2) {
- itA->type |= rel;
- itA->count += 1;
- return;
- }
- itA = itA->next;
- }
- /* create new relation and insert at head. MALLOC alert! */
- itA = MEM_mallocN(sizeof(DagAdjList), "DAG adj list");
- itA->node = fob2;
- itA->type = rel;
- itA->count = 1;
- itA->next = fob1->child;
- itA->name = name;
- fob1->child = itA;
-}
-
-static const char *dag_node_name(DagForest *dag, DagNode *node)
-{
- if (node->ob == NULL)
- return "null";
- else if (dag->ugly_hack_sorry)
- return ((ID *)(node->ob))->name + 2;
- else
- return ((bPoseChannel *)(node->ob))->name;
-}
-
-static void dag_node_print_dependencies(DagForest *dag, DagNode *node)
-{
- DagAdjList *itA;
-
- printf("%s depends on:\n", dag_node_name(dag, node));
-
- for (itA = node->parent; itA; itA = itA->next)
- printf(" %s through %s\n", dag_node_name(dag, itA->node), itA->name);
- printf("\n");
-}
-
-static int dag_node_print_dependency_recurs(DagForest *dag, DagNode *node, DagNode *endnode)
-{
- DagAdjList *itA;
-
- if (node->color == DAG_BLACK)
- return 0;
-
- node->color = DAG_BLACK;
-
- if (node == endnode)
- return 1;
-
- for (itA = node->parent; itA; itA = itA->next) {
- if (dag_node_print_dependency_recurs(dag, itA->node, endnode)) {
- printf(" %s depends on %s through %s.\n", dag_node_name(dag, node), dag_node_name(dag, itA->node), itA->name);
- return 1;
- }
- }
-
- return 0;
-}
-
-static void dag_node_print_dependency_cycle(DagForest *dag, DagNode *startnode, DagNode *endnode, const char *name)
-{
- DagNode *node;
-
- for (node = dag->DagNode.first; node; node = node->next)
- node->color = DAG_WHITE;
-
- printf(" %s depends on %s through %s.\n", dag_node_name(dag, endnode), dag_node_name(dag, startnode), name);
- dag_node_print_dependency_recurs(dag, startnode, endnode);
- printf("\n");
-}
-
-static int dag_node_recurs_level(DagNode *node, int level)
-{
- DagAdjList *itA;
- int newlevel;
-
- node->color = DAG_BLACK; /* done */
- newlevel = ++level;
-
- for (itA = node->parent; itA; itA = itA->next) {
- if (itA->node->color == DAG_WHITE) {
- itA->node->ancestor_count = dag_node_recurs_level(itA->node, level);
- newlevel = MAX2(newlevel, level + itA->node->ancestor_count);
- }
- else
- newlevel = MAX2(newlevel, level + itA->node->ancestor_count);
- }
-
- return newlevel;
-}
-
-static void dag_check_cycle(DagForest *dag)
-{
- DagNode *node;
- DagAdjList *itA;
-
- dag->is_acyclic = true;
-
- /* debugging print */
- if (dag_print_dependencies)
- for (node = dag->DagNode.first; node; node = node->next)
- dag_node_print_dependencies(dag, node);
-
- /* tag nodes unchecked */
- for (node = dag->DagNode.first; node; node = node->next)
- node->color = DAG_WHITE;
-
- for (node = dag->DagNode.first; node; node = node->next) {
- if (node->color == DAG_WHITE) {
- node->ancestor_count = dag_node_recurs_level(node, 0);
- }
- }
-
- /* check relations, and print errors */
- for (node = dag->DagNode.first; node; node = node->next) {
- for (itA = node->parent; itA; itA = itA->next) {
- if (itA->node->ancestor_count > node->ancestor_count) {
- if (node->ob && itA->node->ob) {
- dag->is_acyclic = false;
- printf("Dependency cycle detected:\n");
- dag_node_print_dependency_cycle(dag, itA->node, node, itA->name);
- }
- }
- }
- }
-
- /* parent relations are only needed for cycle checking, so free now */
- for (node = dag->DagNode.first; node; node = node->next) {
- while (node->parent) {
- itA = node->parent->next;
- MEM_freeN(node->parent);
- node->parent = itA;
- }
- }
-}
-
-/* debug test functions */
-
-void graph_print_queue(DagNodeQueue *nqueue)
-{
- DagNodeQueueElem *queueElem;
-
- queueElem = nqueue->first;
- while (queueElem) {
- fprintf(stderr, "** %s %i %i-%i ", ((ID *) queueElem->node->ob)->name, queueElem->node->color, queueElem->node->DFS_dvtm, queueElem->node->DFS_fntm);
- queueElem = queueElem->next;
- }
- fprintf(stderr, "\n");
-}
-
-void graph_print_queue_dist(DagNodeQueue *nqueue)
-{
- DagNodeQueueElem *queueElem;
- int count;
-
- queueElem = nqueue->first;
- count = 0;
- while (queueElem) {
- fprintf(stderr, "** %25s %2.2i-%2.2i ", ((ID *) queueElem->node->ob)->name, queueElem->node->DFS_dvtm, queueElem->node->DFS_fntm);
- while (count < queueElem->node->DFS_dvtm - 1) { fputc(' ', stderr); count++; }
- fputc('|', stderr);
- while (count < queueElem->node->DFS_fntm - 2) { fputc('-', stderr); count++; }
- fputc('|', stderr);
- fputc('\n', stderr);
- count = 0;
- queueElem = queueElem->next;
- }
- fprintf(stderr, "\n");
-}
-
-void graph_print_adj_list(DagForest *dag)
-{
- DagNode *node;
- DagAdjList *itA;
-
- node = dag->DagNode.first;
- while (node) {
- fprintf(stderr, "node : %s col: %i", ((ID *) node->ob)->name, node->color);
- itA = node->child;
- while (itA) {
- fprintf(stderr, "-- %s ", ((ID *) itA->node->ob)->name);
-
- itA = itA->next;
- }
- fprintf(stderr, "\n");
- node = node->next;
- }
-}
-
-/* ************************ API *********************** */
-
-/* mechanism to allow editors to be informed of depsgraph updates,
- * to do their own updates based on changes... */
-static void (*EditorsUpdateIDCb)(Main *bmain, ID *id) = NULL;
-static void (*EditorsUpdateSceneCb)(Main *bmain, Scene *scene, int updated) = NULL;
-static void (*EditorsUpdateScenePreCb)(Main *bmain, Scene *scene, bool time) = NULL;
-
-void DAG_editors_update_cb(void (*id_func)(Main *bmain, ID *id),
- void (*scene_func)(Main *bmain, Scene *scene, int updated),
- void (*scene_pre_func)(Main *bmain, Scene *scene, bool time))
-{
- if (DEG_depsgraph_use_legacy()) {
- EditorsUpdateIDCb = id_func;
- EditorsUpdateSceneCb = scene_func;
- EditorsUpdateScenePreCb = scene_pre_func;
- }
- else {
- /* New dependency graph. */
- DEG_editors_set_update_cb(id_func, scene_func, scene_pre_func);
- }
-}
-
-void DAG_editors_update_pre(Main *bmain, Scene *scene, bool time)
-{
- if (DEG_depsgraph_use_legacy()) {
- if (EditorsUpdateScenePreCb != NULL) {
- EditorsUpdateScenePreCb(bmain, scene, time);
- }
- }
- else {
- DEG_editors_update_pre(bmain, scene, time);
- }
-}
-
-static void dag_editors_id_update(Main *bmain, ID *id)
-{
- if (EditorsUpdateIDCb)
- EditorsUpdateIDCb(bmain, id);
-}
-
-static void dag_editors_scene_update(Main *bmain, Scene *scene, int updated)
-{
- if (EditorsUpdateSceneCb)
- EditorsUpdateSceneCb(bmain, scene, updated);
-}
-
-/* groups with objects in this scene need to be put in the right order as well */
-static void scene_sort_groups(Main *bmain, Scene *sce)
-{
- Base *base;
- Group *group;
- GroupObject *go;
- Object *ob;
-
- /* test; are group objects all in this scene? */
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
- ob->id.tag &= ~LIB_TAG_DOIT;
- }
- for (base = sce->base.first; base; base = base->next)
- base->object->id.tag |= LIB_TAG_DOIT;
-
- for (group = bmain->group.first; group; group = group->id.next) {
- for (go = group->gobject.first; go; go = go->next) {
- if ((go->ob->id.tag & LIB_TAG_DOIT) == 0)
- break;
- }
- /* this group is entirely in this scene */
- if (go == NULL) {
- ListBase listb = {NULL, NULL};
-
- for (go = group->gobject.first; go; go = go->next)
- go->ob->id.newid = (ID *)go;
-
- /* in order of sorted bases we reinsert group objects */
- for (base = sce->base.first; base; base = base->next) {
-
- if (base->object->id.newid) {
- go = (GroupObject *)base->object->id.newid;
- base->object->id.newid = NULL;
- BLI_remlink(&group->gobject, go);
- BLI_addtail(&listb, go);
- }
- }
- /* copy the newly sorted listbase */
- group->gobject = listb;
- }
- }
-
- /* newid abused for GroupObject, cleanup. */
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
- ob->id.newid = NULL;
- }
-}
-
-static void dag_scene_tag_rebuild(Scene *sce)
-{
- if (sce->theDag) {
- sce->theDag->need_update = true;
- }
-}
-
-/* free the depency graph */
-static void dag_scene_free(Scene *sce)
-{
- if (sce->theDag) {
- free_forest(sce->theDag);
- MEM_freeN(sce->theDag);
- sce->theDag = NULL;
- }
-}
-
-/* Check whether object data needs to be evaluated before it
- * might be used by others.
- *
- * Means that mesh object needs to have proper derivedFinal,
- * curves-typed objects are to have proper curve cache.
- *
- * Other objects or objects which are tagged for data update are
- * not considered to be in need of evaluation.
- */
-static bool check_object_needs_evaluation(Object *object)
-{
- if (object->recalc & OB_RECALC_ALL) {
- /* Object is tagged for update anyway, no need to re-tag it. */
- return false;
- }
-
- if (object->type == OB_MESH) {
- return object->derivedFinal == NULL;
- }
- else if (ELEM(object->type, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
- return object->curve_cache == NULL;
- }
-
- return false;
-}
-
-/* Check whether object data is tagged for update. */
-static bool check_object_tagged_for_update(Object *object)
-{
- if (object->recalc & OB_RECALC_ALL) {
- return true;
- }
-
- if (ELEM(object->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
- ID *data_id = object->data;
- return (data_id->recalc & ID_RECALC_ALL) != 0;
- }
-
- return false;
-}
-
-/* Flush changes from tagged objects in the scene to their
- * dependencies which are not evaluated yet.
- *
- * This is needed to ensure all the dependencies are met
- * before objects gets handled by object_handle_update(),
- *
- * This is needed when visible layers are changed or changing
- * scene graph layout which involved usage of objects which
- * aren't in the scene or weren't visible yet.
- */
-static void dag_invisible_dependencies_flush(Scene *scene)
-{
- DagNode *root_node = scene->theDag->DagNode.first, *node;
- DagNodeQueue *queue;
-
- for (node = root_node; node != NULL; node = node->next) {
- node->color = DAG_WHITE;
- }
-
- queue = queue_create(DAGQUEUEALLOC);
-
- for (node = root_node; node != NULL; node = node->next) {
- if (node->color == DAG_WHITE) {
- push_stack(queue, node);
- node->color = DAG_GRAY;
-
- while (queue->count) {
- DagNode *current_node = get_top_node_queue(queue);
- DagAdjList *itA;
- bool skip = false;
-
- for (itA = current_node->child; itA; itA = itA->next) {
- if (itA->node->color == DAG_WHITE) {
- itA->node->color = DAG_GRAY;
- push_stack(queue, itA->node);
- skip = true;
- break;
- }
- }
-
- if (!skip) {
- current_node = pop_queue(queue);
-
- if (current_node->type == ID_OB) {
- Object *current_object = current_node->ob;
- if (check_object_needs_evaluation(current_object)) {
- for (itA = current_node->child; itA; itA = itA->next) {
- if (itA->node->type == ID_OB) {
- Object *object = itA->node->ob;
- if (check_object_tagged_for_update(object)) {
- current_object->recalc |= OB_RECALC_OB | OB_RECALC_DATA;
- }
- }
- }
- }
- }
- node->color = DAG_BLACK;
- }
- }
- }
- }
-
- queue_delete(queue);
-}
-
-static void dag_invisible_dependencies_check_flush(Main *bmain, Scene *scene)
-{
- if (DAG_id_type_tagged(bmain, ID_OB) ||
- DAG_id_type_tagged(bmain, ID_ME) || /* Mesh */
- DAG_id_type_tagged(bmain, ID_CU) || /* Curve */
- DAG_id_type_tagged(bmain, ID_MB) || /* MetaBall */
- DAG_id_type_tagged(bmain, ID_LT)) /* Lattice */
- {
- dag_invisible_dependencies_flush(scene);
- }
-}
-
-/* sort the base list on dependency order */
-static void dag_scene_build(Main *bmain, Scene *sce)
-{
- DagNode *node, *rootnode;
- DagNodeQueue *nqueue;
- DagAdjList *itA;
- int time;
- int skip = 0;
- ListBase tempbase;
- Base *base;
-
- BLI_listbase_clear(&tempbase);
-
- build_dag(bmain, sce, DAG_RL_ALL_BUT_DATA);
-
- dag_check_cycle(sce->theDag);
-
- nqueue = queue_create(DAGQUEUEALLOC);
-
- for (node = sce->theDag->DagNode.first; node; node = node->next) {
- node->color = DAG_WHITE;
- }
-
- time = 1;
-
- rootnode = sce->theDag->DagNode.first;
- rootnode->color = DAG_GRAY;
- time++;
- push_stack(nqueue, rootnode);
-
- while (nqueue->count) {
-
- skip = 0;
- node = get_top_node_queue(nqueue);
-
- itA = node->child;
- while (itA != NULL) {
- if (itA->node->color == DAG_WHITE) {
- itA->node->DFS_dvtm = time;
- itA->node->color = DAG_GRAY;
-
- time++;
- push_stack(nqueue, itA->node);
- skip = 1;
- break;
- }
- itA = itA->next;
- }
-
- if (!skip) {
- if (node) {
- node = pop_queue(nqueue);
- if (node->ob == sce) /* we are done */
- break;
- node->color = DAG_BLACK;
-
- time++;
- base = sce->base.first;
- while (base && base->object != node->ob)
- base = base->next;
- if (base) {
- BLI_remlink(&sce->base, base);
- BLI_addhead(&tempbase, base);
- }
- }
- }
- }
-
- /* temporal correction for circular dependencies */
- base = sce->base.first;
- while (base) {
- BLI_remlink(&sce->base, base);
- BLI_addhead(&tempbase, base);
- //if (G.debug & G_DEBUG)
- printf("cyclic %s\n", base->object->id.name);
- base = sce->base.first;
- }
-
- sce->base = tempbase;
- queue_delete(nqueue);
-
- /* all groups with objects in this scene gets resorted too */
- scene_sort_groups(bmain, sce);
-
- if (G.debug & G_DEBUG) {
- printf("\nordered\n");
- for (base = sce->base.first; base; base = base->next) {
- printf(" %s\n", base->object->id.name);
- }
- }
-
- /* Make sure that new dependencies which came from invisible layers
- * are tagged for update (if they're needed for objects which were
- * tagged for update).
- */
- dag_invisible_dependencies_check_flush(bmain, sce);
-}
-
-/* clear all dependency graphs */
-void DAG_relations_tag_update(Main *bmain)
-{
- if (DEG_depsgraph_use_legacy()) {
- Scene *sce;
- for (sce = bmain->scene.first; sce; sce = sce->id.next) {
- dag_scene_tag_rebuild(sce);
- }
- }
- else {
- /* New dependency graph. */
- DEG_relations_tag_update(bmain);
- }
-}
-
-/* rebuild dependency graph only for a given scene */
-void DAG_scene_relations_rebuild(Main *bmain, Scene *sce)
-{
- if (DEG_depsgraph_use_legacy()) {
- dag_scene_free(sce);
- DAG_scene_relations_update(bmain, sce);
- }
- else {
- /* New dependency graph. */
- DEG_scene_relations_rebuild(bmain, sce);
- }
-}
-
-/* create dependency graph if it was cleared or didn't exist yet */
-void DAG_scene_relations_update(Main *bmain, Scene *sce)
-{
- if (DEG_depsgraph_use_legacy()) {
- if (!sce->theDag || sce->theDag->need_update)
- dag_scene_build(bmain, sce);
- }
- else {
- /* New dependency graph. */
- DEG_scene_relations_update(bmain, sce);
- }
-}
-
-void DAG_scene_relations_validate(Main *bmain, Scene *sce)
-{
- if (!DEG_depsgraph_use_legacy()) {
- DEG_debug_scene_relations_validate(bmain, sce);
- }
-}
-
-void DAG_scene_free(Scene *sce)
-{
- if (DEG_depsgraph_use_legacy()) {
- if (sce->theDag) {
- free_forest(sce->theDag);
- MEM_freeN(sce->theDag);
- sce->theDag = NULL;
- }
- }
- else {
- if (sce->depsgraph) {
- DEG_graph_free(sce->depsgraph);
- sce->depsgraph = NULL;
- }
- }
-}
-
-static void lib_id_recalc_tag(Main *bmain, ID *id)
-{
- id->recalc |= ID_RECALC;
- DAG_id_type_tag(bmain, GS(id->name));
-}
-
-static void lib_id_recalc_data_tag(Main *bmain, ID *id)
-{
- id->recalc |= ID_RECALC_DATA;
- DAG_id_type_tag(bmain, GS(id->name));
-}
-
-/* node was checked to have lasttime != curtime and is if type ID_OB */
-static void flush_update_node(Main *bmain, DagNode *node, unsigned int layer, int curtime)
-{
- DagAdjList *itA;
- Object *ob, *obc;
- int oldflag;
- bool changed = false;
- unsigned int all_layer;
-
- node->lasttime = curtime;
-
- ob = node->ob;
- if (ob && (ob->recalc & OB_RECALC_ALL)) {
- all_layer = node->scelay;
-
- /* got an object node that changes, now check relations */
- for (itA = node->child; itA; itA = itA->next) {
- all_layer |= itA->lay;
- /* the relationship is visible */
- if ((itA->lay & layer)) { // XXX || (itA->node->ob == obedit)
- if (itA->node->type == ID_OB) {
- obc = itA->node->ob;
- oldflag = obc->recalc;
-
- /* got a ob->obc relation, now check if flag needs flush */
- if (ob->recalc & OB_RECALC_OB) {
- if (itA->type & DAG_RL_OB_OB) {
- //printf("ob %s changes ob %s\n", ob->id.name, obc->id.name);
- obc->recalc |= OB_RECALC_OB;
- lib_id_recalc_tag(bmain, &obc->id);
- }
- if (itA->type & DAG_RL_OB_DATA) {
- //printf("ob %s changes obdata %s\n", ob->id.name, obc->id.name);
- obc->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obc->id);
- }
- }
- if (ob->recalc & OB_RECALC_DATA) {
- if (itA->type & DAG_RL_DATA_OB) {
- //printf("obdata %s changes ob %s\n", ob->id.name, obc->id.name);
- obc->recalc |= OB_RECALC_OB;
- lib_id_recalc_tag(bmain, &obc->id);
- }
- if (itA->type & DAG_RL_DATA_DATA) {
- //printf("obdata %s changes obdata %s\n", ob->id.name, obc->id.name);
- obc->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obc->id);
- }
- }
- if (oldflag != obc->recalc) changed = 1;
- }
- }
- }
- /* even nicer, we can clear recalc flags... */
- if ((all_layer & layer) == 0) { // XXX && (ob != obedit)) {
- /* but existing displaylists or derivedmesh should be freed */
- if (ob->recalc & OB_RECALC_DATA)
- BKE_object_free_derived_caches(ob);
-
- ob->recalc &= ~OB_RECALC_ALL;
- }
- }
-
- /* check case where child changes and parent forcing obdata to change */
- /* should be done regardless if this ob has recalc set */
- /* could merge this in with loop above...? (ton) */
- for (itA = node->child; itA; itA = itA->next) {
- /* the relationship is visible */
- if ((itA->lay & layer)) { // XXX || (itA->node->ob == obedit)
- if (itA->node->type == ID_OB) {
- obc = itA->node->ob;
- /* child moves */
- if ((obc->recalc & OB_RECALC_ALL) == OB_RECALC_OB) {
- /* parent has deforming info */
- if (itA->type & (DAG_RL_OB_DATA | DAG_RL_DATA_DATA)) {
- // printf("parent %s changes ob %s\n", ob->id.name, obc->id.name);
- obc->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obc->id);
- }
- }
- }
- }
- }
-
- /* we only go deeper if node not checked or something changed */
- for (itA = node->child; itA; itA = itA->next) {
- if (changed || itA->node->lasttime != curtime)
- flush_update_node(bmain, itA->node, layer, curtime);
- }
-
-}
-
-/* node was checked to have lasttime != curtime, and is of type ID_OB */
-static unsigned int flush_layer_node(Scene *sce, DagNode *node, int curtime)
-{
- DagAdjList *itA;
-
- node->lasttime = curtime;
- node->lay = node->scelay;
-
- for (itA = node->child; itA; itA = itA->next) {
- if (itA->node->type == ID_OB) {
- if (itA->node->lasttime != curtime) {
- itA->lay = flush_layer_node(sce, itA->node, curtime); /* lay is only set once for each relation */
- }
- else {
- itA->lay = itA->node->lay;
- }
-
- node->lay |= itA->lay;
- }
- }
-
- return node->lay;
-}
-
-/* node was checked to have lasttime != curtime, and is of type ID_OB */
-static void flush_pointcache_reset(Main *bmain, Scene *scene, DagNode *node,
- int curtime, unsigned int lay, bool reset)
-{
- DagAdjList *itA;
- Object *ob;
-
- node->lasttime = curtime;
-
- for (itA = node->child; itA; itA = itA->next) {
- if (itA->node->type == ID_OB) {
- if (itA->node->lasttime != curtime) {
- ob = (Object *)(itA->node->ob);
-
- if (reset || (ob->recalc & OB_RECALC_ALL)) {
- if (BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH)) {
- /* Don't tag nodes which are on invisible layer. */
- if (itA->node->lay & lay) {
- ob->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &ob->id);
- }
- }
-
- flush_pointcache_reset(bmain, scene, itA->node, curtime, lay, true);
- }
- else
- flush_pointcache_reset(bmain, scene, itA->node, curtime, lay, false);
- }
- }
- }
-}
-
-/* flush layer flags to dependencies */
-static void dag_scene_flush_layers(Scene *sce, int lay)
-{
- DagNode *node, *firstnode;
- DagAdjList *itA;
- Base *base;
- int lasttime;
-
- firstnode = sce->theDag->DagNode.first; /* always scene node */
-
- for (itA = firstnode->child; itA; itA = itA->next)
- itA->lay = 0;
-
- sce->theDag->time++; /* so we know which nodes were accessed */
- lasttime = sce->theDag->time;
-
- /* update layer flags in nodes */
- for (base = sce->base.first; base; base = base->next) {
- node = dag_get_node(sce->theDag, base->object);
- node->scelay = base->object->lay;
- }
-
- /* ensure cameras are set as if they are on a visible layer, because
- * they ared still used for rendering or setting the camera view
- *
- * XXX, this wont work for local view / unlocked camera's */
- if (sce->camera) {
- node = dag_get_node(sce->theDag, sce->camera);
- node->scelay |= lay;
- }
-
-#ifdef DURIAN_CAMERA_SWITCH
- {
- TimeMarker *m;
-
- for (m = sce->markers.first; m; m = m->next) {
- if (m->camera) {
- node = dag_get_node(sce->theDag, m->camera);
- node->scelay |= lay;
- }
- }
- }
-#endif
-
- /* flush layer nodes to dependencies */
- for (itA = firstnode->child; itA; itA = itA->next)
- if (itA->node->lasttime != lasttime && itA->node->type == ID_OB)
- flush_layer_node(sce, itA->node, lasttime);
-}
-
-static void dag_tag_renderlayers(Scene *sce, unsigned int lay)
-{
- if (sce->nodetree) {
- bNode *node;
- Base *base;
- unsigned int lay_changed = 0;
-
- for (base = sce->base.first; base; base = base->next)
- if (base->lay & lay)
- if (base->object->recalc)
- lay_changed |= base->lay;
-
- for (node = sce->nodetree->nodes.first; node; node = node->next) {
- if (node->id == (ID *)sce) {
- SceneRenderLayer *srl = BLI_findlink(&sce->r.layers, node->custom1);
- if (srl && (srl->lay & lay_changed))
- nodeUpdate(sce->nodetree, node);
- }
- }
- }
-}
-
-/* flushes all recalc flags in objects down the dependency tree */
-void DAG_scene_flush_update(Main *bmain, Scene *sce, unsigned int lay, const short time)
-{
- DagNode *firstnode;
- DagAdjList *itA;
- Object *ob;
- int lasttime;
-
- if (!DEG_depsgraph_use_legacy()) {
- DEG_scene_flush_update(bmain, sce);
- return;
- }
-
- if (sce->theDag == NULL || sce->theDag->need_update) {
- printf("DAG zero... not allowed to happen!\n");
- DAG_scene_relations_update(bmain, sce);
- }
-
- firstnode = sce->theDag->DagNode.first; /* always scene node */
-
- /* first we flush the layer flags */
- dag_scene_flush_layers(sce, lay);
-
- /* then we use the relationships + layer info to flush update events */
- sce->theDag->time++; /* so we know which nodes were accessed */
- lasttime = sce->theDag->time;
- for (itA = firstnode->child; itA; itA = itA->next)
- if (itA->node->lasttime != lasttime && itA->node->type == ID_OB)
- flush_update_node(bmain, itA->node, lay, lasttime);
-
- /* if update is not due to time change, do pointcache clears */
- if (!time) {
- sce->theDag->time++; /* so we know which nodes were accessed */
- lasttime = sce->theDag->time;
- for (itA = firstnode->child; itA; itA = itA->next) {
- if (itA->node->lasttime != lasttime && itA->node->type == ID_OB) {
- ob = (Object *)(itA->node->ob);
-
- if (ob->recalc & OB_RECALC_ALL) {
- if (BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH)) {
- ob->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &ob->id);
- }
-
- flush_pointcache_reset(bmain, sce, itA->node, lasttime,
- lay, true);
- }
- else
- flush_pointcache_reset(bmain, sce, itA->node, lasttime,
- lay, false);
- }
- }
- }
-
- dag_tag_renderlayers(sce, lay);
-}
-
-static bool modifier_nlastrips_use_time(ListBase *strips)
-{
- NlaStrip *strip;
-
- if (strips) {
- for (strip = strips->first; strip; strip = strip->next) {
- if (modifier_nlastrips_use_time(&strip->strips)) {
- return true;
- }
- else if (strip->act) {
- FCurve *fcu;
-
- for (fcu = strip->act->curves.first; fcu; fcu = fcu->next) {
- if (fcu->rna_path && strstr(fcu->rna_path, "modifiers["))
- return true;
- }
- }
- }
- }
-
- return false;
-}
-
-static bool object_modifiers_use_time(Object *ob)
-{
- ModifierData *md;
-
- /* check if a modifier in modifier stack needs time input */
- for (md = ob->modifiers.first; md; md = md->next) {
- if (modifier_dependsOnTime(md))
- return true;
- }
-
- /* check whether any modifiers are animated */
- if (ob->adt) {
- AnimData *adt = ob->adt;
- NlaTrack *nlt;
- FCurve *fcu;
-
- /* action - check for F-Curves with paths containing 'modifiers[' */
- if (adt->action) {
- for (fcu = adt->action->curves.first; fcu; fcu = fcu->next) {
- if (fcu->rna_path && strstr(fcu->rna_path, "modifiers["))
- return true;
- }
- }
-
- /* This here allows modifier properties to get driven and still update properly
- *
- * Workaround to get [#26764] (e.g. subsurf levels not updating when animated/driven)
- * working, without the updating problems ([#28525] [#28690] [#28774] [#28777]) caused
- * by the RNA updates cache introduced in r.38649
- */
- for (fcu = adt->drivers.first; fcu; fcu = fcu->next) {
- if (fcu->rna_path && strstr(fcu->rna_path, "modifiers["))
- return true;
- }
-
- /* Also check NLA Strips... [#T45938] */
- for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
- if (modifier_nlastrips_use_time(&nlt->strips))
- return true;
- }
- }
-
- return false;
-}
-
-static short animdata_use_time(AnimData *adt)
-{
- NlaTrack *nlt;
-
- if (adt == NULL) return 0;
-
- /* check action - only if assigned, and it has anim curves */
- if (adt->action && adt->action->curves.first)
- return 1;
-
- /* check NLA tracks + strips */
- for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
- if (nlt->strips.first)
- return 1;
- }
-
- /* If we have drivers, more likely than not, on a frame change
- * they'll need updating because their owner changed
- *
- * This is kindof a hack to get around a whole host of problems
- * involving drivers using non-object datablock data (which the
- * depsgraph currently has no way of representing let alone correctly
- * dependency sort+tagging). By doing this, at least we ensure that
- * some commonly attempted drivers (such as scene -> current frame;
- * see "Driver updates fail" thread on Bf-committers dated July 2)
- * will work correctly, and that other non-object datablocks will have
- * their drivers update at least on frame change.
- *
- * -- Aligorith, July 4 2011
- */
- if (adt->drivers.first)
- return 1;
-
- return 0;
-}
-
-static void dag_object_time_update_flags(Main *bmain, Scene *scene, Object *ob)
-{
- if (ob->constraints.first) {
- bConstraint *con;
- for (con = ob->constraints.first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- if (cti) {
- /* special case for camera tracking -- it doesn't use targets to define relations */
- if (ELEM(cti->type,
- CONSTRAINT_TYPE_FOLLOWTRACK,
- CONSTRAINT_TYPE_CAMERASOLVER,
- CONSTRAINT_TYPE_OBJECTSOLVER,
- CONSTRAINT_TYPE_TRANSFORM_CACHE))
- {
- ob->recalc |= OB_RECALC_OB;
- }
- else if (cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- if (ct->tar) {
- ob->recalc |= OB_RECALC_OB;
- break;
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 1);
- }
-
- }
- }
- }
-
- if (ob->parent) {
- /* motion path or bone child */
- if (ob->parent->type == OB_CURVE || ob->parent->type == OB_ARMATURE) ob->recalc |= OB_RECALC_OB;
- }
-
-#if 0 // XXX old animation system
- if (ob->nlastrips.first) {
- if (ob->dup_group) {
- bActionStrip *strip;
- /* this case is for groups with nla, whilst nla target has no action or nla */
- for (strip = ob->nlastrips.first; strip; strip = strip->next) {
- if (strip->object)
- strip->object->recalc |= OB_RECALC_ALL;
- }
- }
- }
-#endif // XXX old animation system
-
- if (animdata_use_time(ob->adt)) {
- ob->recalc |= OB_RECALC_OB;
- ob->adt->recalc |= ADT_RECALC_ANIM;
- }
-
- if ((ob->adt) && (ob->type == OB_ARMATURE)) ob->recalc |= OB_RECALC_DATA;
-
- if (object_modifiers_use_time(ob)) ob->recalc |= OB_RECALC_DATA;
- if ((ob->pose) && (ob->pose->flag & POSE_CONSTRAINTS_TIMEDEPEND)) ob->recalc |= OB_RECALC_DATA;
-
- // XXX: scene here may not be the scene that contains the rigidbody world affecting this!
- if (ob->rigidbody_object && BKE_scene_check_rigidbody_active(scene))
- ob->recalc |= OB_RECALC_OB;
-
- {
- AnimData *adt = BKE_animdata_from_id((ID *)ob->data);
- Mesh *me;
- Curve *cu;
- Lattice *lt;
-
- switch (ob->type) {
- case OB_MESH:
- me = ob->data;
- if (me->key) {
- if (!(ob->shapeflag & OB_SHAPE_LOCK)) {
- ob->recalc |= OB_RECALC_DATA;
- }
- }
- if (ob->particlesystem.first)
- ob->recalc |= OB_RECALC_DATA;
- break;
- case OB_CURVE:
- case OB_SURF:
- cu = ob->data;
- if (cu->key) {
- if (!(ob->shapeflag & OB_SHAPE_LOCK)) {
- ob->recalc |= OB_RECALC_DATA;
- }
- }
- break;
- case OB_FONT:
- cu = ob->data;
- if (cu->str && cu->vfont) {
- /* Can be in the curve-cache or the curve. */
- if (ob->curve_cache && !BLI_listbase_is_empty(&ob->curve_cache->disp)) {
- /* pass */
- }
- else if (!BLI_listbase_is_empty(&cu->nurb)) {
- /* pass */
- }
- else {
- ob->recalc |= OB_RECALC_DATA;
- }
- }
- break;
- case OB_LATTICE:
- lt = ob->data;
- if (lt->key) {
- if (!(ob->shapeflag & OB_SHAPE_LOCK)) {
- ob->recalc |= OB_RECALC_DATA;
- }
- }
- break;
- case OB_MBALL:
- if (ob->transflag & OB_DUPLI) ob->recalc |= OB_RECALC_DATA;
- break;
- case OB_EMPTY:
- /* update animated images */
- if (ob->empty_drawtype == OB_EMPTY_IMAGE && ob->data)
- if (BKE_image_is_animated(ob->data))
- ob->recalc |= OB_RECALC_DATA;
- break;
- }
-
- if (animdata_use_time(adt)) {
- ob->recalc |= OB_RECALC_DATA;
- adt->recalc |= ADT_RECALC_ANIM;
- }
-
- if (ob->particlesystem.first) {
- ParticleSystem *psys = ob->particlesystem.first;
-
- for (; psys; psys = psys->next) {
- if (psys_check_enabled(ob, psys, G.is_rendering)) {
- ob->recalc |= OB_RECALC_DATA;
- break;
- }
- }
- }
- }
-
- if (ob->recalc & OB_RECALC_OB)
- lib_id_recalc_tag(bmain, &ob->id);
- if (ob->recalc & OB_RECALC_DATA)
- lib_id_recalc_data_tag(bmain, &ob->id);
-
-}
-
-/* recursively update objects in groups, each group is done at most once */
-static void dag_group_update_flags(Main *bmain, Scene *scene, Group *group, const bool do_time)
-{
- GroupObject *go;
-
- if (group->id.tag & LIB_TAG_DOIT)
- return;
-
- group->id.tag |= LIB_TAG_DOIT;
-
- for (go = group->gobject.first; go; go = go->next) {
- if (do_time)
- dag_object_time_update_flags(bmain, scene, go->ob);
- if (go->ob->dup_group)
- dag_group_update_flags(bmain, scene, go->ob->dup_group, do_time);
- }
-}
-
-/* flag all objects that need recalc, for changes in time for example */
-/* do_time: make this optional because undo resets objects to their animated locations without this */
-void DAG_scene_update_flags(Main *bmain, Scene *scene, unsigned int lay, const bool do_time, const bool do_invisible_flush)
-{
- Base *base;
- Object *ob;
- Group *group;
- GroupObject *go;
- Scene *sce_iter;
-
- BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false);
-
- /* set ob flags where animated systems are */
- for (SETLOOPER(scene, sce_iter, base)) {
- ob = base->object;
-
- if (do_time) {
- /* now if DagNode were part of base, the node->lay could be checked... */
- /* we do all now, since the scene_flush checks layers and clears recalc flags even */
-
- /* NOTE: "sce_iter" not "scene" so that rigidbodies in background scenes work
- * (i.e. muting + rbw availability can be checked and tagged properly) [#33970]
- */
- dag_object_time_update_flags(bmain, sce_iter, ob);
- }
-
- /* recursively tag groups with LIB_TAG_DOIT, and update flags for objects */
- if (ob->dup_group)
- dag_group_update_flags(bmain, scene, ob->dup_group, do_time);
- }
-
- for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set)
- DAG_scene_flush_update(bmain, sce_iter, lay, 1);
-
- if (do_time) {
- /* test: set time flag, to disable baked systems to update */
- for (SETLOOPER(scene, sce_iter, base)) {
- ob = base->object;
- if (ob->recalc & OB_RECALC_ALL)
- ob->recalc |= OB_RECALC_TIME;
- }
-
- /* hrmf... an exception to look at once, for invisible camera object we do it over */
- if (scene->camera)
- dag_object_time_update_flags(bmain, scene, scene->camera);
- }
-
- /* and store the info in groupobject */
- for (group = bmain->group.first; group; group = group->id.next) {
- if (group->id.tag & LIB_TAG_DOIT) {
- for (go = group->gobject.first; go; go = go->next) {
- go->recalc = go->ob->recalc;
- // printf("ob %s recalc %d\n", go->ob->id.name, go->recalc);
- }
- group->id.tag &= ~LIB_TAG_DOIT;
- }
- }
-
- if (do_invisible_flush) {
- dag_invisible_dependencies_check_flush(bmain, scene);
- }
-}
-
-/* struct returned by DagSceneLayer */
-typedef struct DagSceneLayer {
- struct DagSceneLayer *next, *prev;
- Scene *scene;
- unsigned int layer;
-} DagSceneLayer;
-
-/* returns visible scenes with valid DAG */
-static void dag_current_scene_layers(Main *bmain, ListBase *lb)
-{
- wmWindowManager *wm;
- wmWindow *win;
-
- BLI_listbase_clear(lb);
-
- /* if we have a windowmanager, look into windows */
- if ((wm = bmain->wm.first)) {
-
- BKE_main_id_flag_listbase(&bmain->scene, LIB_TAG_DOIT, 1);
-
- for (win = wm->windows.first; win; win = win->next) {
- if (win->screen && win->screen->scene->theDag) {
- Scene *scene = win->screen->scene;
- DagSceneLayer *dsl;
-
- if (scene->id.tag & LIB_TAG_DOIT) {
- dsl = MEM_mallocN(sizeof(DagSceneLayer), "dag scene layer");
-
- BLI_addtail(lb, dsl);
-
- dsl->scene = scene;
- dsl->layer = BKE_screen_visible_layers(win->screen, scene);
-
- scene->id.tag &= ~LIB_TAG_DOIT;
- }
- else {
- /* It is possible that multiple windows shares the same scene
- * and have different layers visible.
- *
- * Here we deal with such cases by squashing layers bits from
- * multiple windoew to the DagSceneLayer.
- *
- * TODO(sergey): Such a lookup could be optimized perhaps,
- * however should be fine for now since we usually have only
- * few open windows.
- */
- for (dsl = lb->first; dsl; dsl = dsl->next) {
- if (dsl->scene == scene) {
- dsl->layer |= BKE_screen_visible_layers(win->screen, scene);
- break;
- }
- }
- }
- }
- }
- }
- else {
- /* if not, use the first sce */
- DagSceneLayer *dsl = MEM_mallocN(sizeof(DagSceneLayer), "dag scene layer");
-
- BLI_addtail(lb, dsl);
-
- dsl->scene = bmain->scene.first;
- dsl->layer = dsl->scene->lay;
-
- /* XXX for background mode, we should get the scene
- * from somewhere, for the -S option, but it's in
- * the context, how to get it here? */
- }
-}
-
-static void dag_group_on_visible_update(Scene *scene, Group *group)
-{
- GroupObject *go;
-
- if (group->id.tag & LIB_TAG_DOIT)
- return;
-
- group->id.tag |= LIB_TAG_DOIT;
-
- for (go = group->gobject.first; go; go = go->next) {
- if (ELEM(go->ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE)) {
- go->ob->recalc |= OB_RECALC_DATA;
- go->ob->id.tag |= LIB_TAG_DOIT;
- lib_id_recalc_tag(G.main, &go->ob->id);
- }
- if (go->ob->proxy_from) {
- go->ob->recalc |= OB_RECALC_OB;
- go->ob->id.tag |= LIB_TAG_DOIT;
- lib_id_recalc_tag(G.main, &go->ob->id);
- }
-
- if (go->ob->dup_group)
- dag_group_on_visible_update(scene, go->ob->dup_group);
- }
-}
-
-void DAG_on_visible_update(Main *bmain, const bool do_time)
-{
- ListBase listbase;
- DagSceneLayer *dsl;
-
- if (!DEG_depsgraph_use_legacy()) {
- /* Inform new dependnecy graphs about visibility changes. */
- DEG_on_visible_update(bmain, do_time);
- return;
- }
-
- /* get list of visible scenes and layers */
- dag_current_scene_layers(bmain, &listbase);
-
- for (dsl = listbase.first; dsl; dsl = dsl->next) {
- Scene *scene = dsl->scene;
- Scene *sce_iter;
- Base *base;
- Object *ob;
- DagNode *node;
- unsigned int lay = dsl->layer, oblay;
-
- /* derivedmeshes and displists are not saved to file so need to be
- * remade, tag them so they get remade in the scene update loop,
- * note armature poses or object matrices are preserved and do not
- * require updates, so we skip those */
- for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set)
- dag_scene_flush_layers(sce_iter, lay);
-
- BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false);
-
- for (SETLOOPER(scene, sce_iter, base)) {
- ob = base->object;
- node = (sce_iter->theDag) ? dag_get_node(sce_iter->theDag, ob) : NULL;
- oblay = (node) ? node->lay : ob->lay;
-
- if ((oblay & lay) & ~scene->lay_updated) {
- /* TODO(sergey): Why do we need armature here now but didn't need before? */
- if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL, OB_LATTICE, OB_ARMATURE)) {
- ob->recalc |= OB_RECALC_DATA;
- lib_id_recalc_tag(bmain, &ob->id);
- }
- /* This should not be needed here, but in some cases, like after a redo, we can end up with
- * a wrong final matrix (see T42472).
- * Quoting Sergey, this comes from BKE_object_handle_update_ex, which is calling
- * BKE_object_where_is_calc_ex when it shouldn't, but that issue is not easily fixable.
- */
- else {
- ob->recalc |= OB_RECALC_OB;
- lib_id_recalc_tag(bmain, &ob->id);
- }
- if (ob->proxy && (ob->proxy_group == NULL)) {
- ob->proxy->recalc |= OB_RECALC_DATA;
- lib_id_recalc_tag(bmain, &ob->id);
- }
- if (ob->dup_group)
- dag_group_on_visible_update(scene, ob->dup_group);
- }
- }
-
- BKE_main_id_tag_idcode(bmain, ID_GR, LIB_TAG_DOIT, false);
-
- /* now tag update flags, to ensure deformers get calculated on redraw */
- DAG_scene_update_flags(bmain, scene, lay, do_time, true);
- scene->lay_updated |= lay;
- }
-
- BLI_freelistN(&listbase);
-
- /* hack to get objects updating on layer changes */
- DAG_id_type_tag(bmain, ID_OB);
-
- /* so masks update on load */
- if (bmain->mask.first) {
- Mask *mask;
-
- for (mask = bmain->mask.first; mask; mask = mask->id.next) {
- DAG_id_tag_update(&mask->id, 0);
- }
- }
-}
-
-static void dag_id_flush_update__isDependentTexture(
- void *userData, Object *UNUSED(ob), ID **idpoin, int UNUSED(cb_flag))
-{
- struct { ID *id; bool is_dependent; } *data = userData;
-
- if (*idpoin && GS((*idpoin)->name) == ID_TE) {
- if (data->id == (*idpoin))
- data->is_dependent = 1;
- }
-}
-
-static void dag_id_flush_update(Main *bmain, Scene *sce, ID *id)
-{
- Object *obt, *ob = NULL;
- short idtype;
-
- /* here we flush a few things before actual scene wide flush, mostly
- * due to only objects and not other datablocks being in the depsgraph */
-
- /* set flags & pointcache for object */
- if (GS(id->name) == ID_OB) {
- ob = (Object *)id;
- BKE_ptcache_object_reset(sce, ob, PTCACHE_RESET_DEPSGRAPH);
-
- /* So if someone tagged object recalc directly,
- * id_tag_update bit-field stays relevant
- */
- if (ob->recalc & OB_RECALC_ALL) {
- DAG_id_type_tag(bmain, GS(id->name));
- }
-
- if (ob->recalc & OB_RECALC_DATA) {
- /* all users of this ob->data should be checked */
- id = ob->data;
-
- /* no point in trying in this cases */
- if (id && id->us <= 1) {
- dag_editors_id_update(bmain, id);
- id = NULL;
- }
- }
- }
-
- /* set flags & pointcache for object data */
- if (id) {
- idtype = GS(id->name);
-
-
- if (OB_DATA_SUPPORT_ID(idtype)) {
- for (obt = bmain->object.first; obt; obt = obt->id.next) {
- if (!(ob && obt == ob) && obt->data == id) {
- obt->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obt->id);
- BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
- }
- }
- }
- else if (idtype == ID_VF) {
- for (obt = bmain->object.first; obt; obt = obt->id.next) {
- if (obt->type == OB_FONT) {
- Curve *cu = obt->data;
- if (ELEM((struct VFont *)id, CURVE_VFONT_ANY(cu))) {
- obt->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obt->id);
- }
- }
- }
- }
-
- /* set flags based on textures - can influence depgraph via modifiers */
- if (idtype == ID_TE) {
- for (obt = bmain->object.first; obt; obt = obt->id.next) {
- struct { ID *id; bool is_dependent; } data;
- data.id = id;
- data.is_dependent = 0;
-
- modifiers_foreachIDLink(obt, dag_id_flush_update__isDependentTexture, &data);
- if (data.is_dependent) {
- obt->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obt->id);
- }
-
- /* particle settings can use the texture as well */
- if (obt->particlesystem.first) {
- ParticleSystem *psys = obt->particlesystem.first;
- MTex **mtexp, *mtex;
- int a;
- for (; psys; psys = psys->next) {
- mtexp = psys->part->mtex;
- for (a = 0; a < MAX_MTEX; a++, mtexp++) {
- mtex = *mtexp;
- if (mtex && mtex->tex == (Tex *)id) {
- obt->recalc |= OB_RECALC_DATA;
- lib_id_recalc_data_tag(bmain, &obt->id);
-
- if (mtex->mapto & PAMAP_INIT)
- psys->recalc |= PSYS_RECALC_RESET;
- if (mtex->mapto & PAMAP_CHILD)
- psys->recalc |= PSYS_RECALC_CHILD;
-
- BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
- }
- }
- }
- }
- }
- }
-
- /* set flags based on ShapeKey */
- if (idtype == ID_KE) {
- for (obt = bmain->object.first; obt; obt = obt->id.next) {
- Key *key = BKE_key_from_object(obt);
- if (!(ob && obt == ob) && ((ID *)key == id)) {
- obt->flag |= (OB_RECALC_OB | OB_RECALC_DATA);
- lib_id_recalc_tag(bmain, &obt->id);
- lib_id_recalc_data_tag(bmain, &obt->id);
- BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
- }
- }
- }
-
- /* set flags based on particle settings */
- if (idtype == ID_PA) {
- ParticleSystem *psys;
- for (obt = bmain->object.first; obt; obt = obt->id.next)
- for (psys = obt->particlesystem.first; psys; psys = psys->next)
- if (&psys->part->id == id)
- BKE_ptcache_object_reset(sce, obt, PTCACHE_RESET_DEPSGRAPH);
- }
-
- if (ELEM(idtype, ID_MA, ID_TE)) {
- obt = sce->basact ? sce->basact->object : NULL;
- if (obt && obt->mode & OB_MODE_TEXTURE_PAINT) {
- BKE_texpaint_slots_refresh_object(sce, obt);
- BKE_paint_proj_mesh_data_check(sce, obt, NULL, NULL, NULL, NULL);
- GPU_drawobject_free(obt->derivedFinal);
- }
- }
-
- if (idtype == ID_MC) {
- MovieClip *clip = (MovieClip *) id;
-
- BKE_tracking_dopesheet_tag_update(&clip->tracking);
-
- for (obt = bmain->object.first; obt; obt = obt->id.next) {
- bConstraint *con;
- for (con = obt->constraints.first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- if (ELEM(cti->type, CONSTRAINT_TYPE_FOLLOWTRACK, CONSTRAINT_TYPE_CAMERASOLVER,
- CONSTRAINT_TYPE_OBJECTSOLVER))
- {
- obt->recalc |= OB_RECALC_OB;
- lib_id_recalc_tag(bmain, &obt->id);
- break;
- }
- }
- }
-
- if (sce->nodetree) {
- bNode *node;
-
- for (node = sce->nodetree->nodes.first; node; node = node->next) {
- if (node->id == id) {
- nodeUpdate(sce->nodetree, node);
- }
- }
- }
- }
-
- /* Not pretty to iterate all the nodes here, but it's as good as it
- * could be with the current depsgraph design/
- */
- if (idtype == ID_IM) {
- FOREACH_NODETREE(bmain, ntree, parent_id) {
- if (ntree->type == NTREE_SHADER) {
- bNode *node;
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->id == id) {
- lib_id_recalc_tag(bmain, &ntree->id);
- break;
- }
- }
- }
- } FOREACH_NODETREE_END
- }
-
- if (idtype == ID_MSK) {
- if (sce->nodetree) {
- bNode *node;
-
- for (node = sce->nodetree->nodes.first; node; node = node->next) {
- if (node->id == id) {
- nodeUpdate(sce->nodetree, node);
- }
- }
- }
- }
-
- /* camera's matrix is used to orient reconstructed stuff,
- * so it should happen tracking-related constraints recalculation
- * when camera is changing (sergey) */
- if (sce->camera && &sce->camera->id == id) {
- MovieClip *clip = BKE_object_movieclip_get(sce, sce->camera, true);
-
- if (clip)
- dag_id_flush_update(bmain, sce, &clip->id);
- }
-
- /* update editors */
- dag_editors_id_update(bmain, id);
- }
-}
-
-void DAG_ids_flush_tagged(Main *bmain)
-{
- ListBase listbase;
- DagSceneLayer *dsl;
- ListBase *lbarray[MAX_LIBARRAY];
- int a;
- bool do_flush = false;
-
- if (!DEG_depsgraph_use_legacy()) {
- DEG_ids_flush_tagged(bmain);
- return;
- }
-
- /* get list of visible scenes and layers */
- dag_current_scene_layers(bmain, &listbase);
-
- if (BLI_listbase_is_empty(&listbase))
- return;
-
- /* loop over all ID types */
- a = set_listbasepointers(bmain, lbarray);
-
- while (a--) {
- ListBase *lb = lbarray[a];
- ID *id = lb->first;
-
- if (id && bmain->id_tag_update[BKE_idcode_to_index(GS(id->name))]) {
- for (; id; id = id->next) {
- if (id->recalc & ID_RECALC_ALL) {
- for (dsl = listbase.first; dsl; dsl = dsl->next)
- dag_id_flush_update(bmain, dsl->scene, id);
-
- do_flush = true;
- }
- }
- }
- }
-
- /* flush changes to other objects */
- if (do_flush) {
- for (dsl = listbase.first; dsl; dsl = dsl->next)
- DAG_scene_flush_update(bmain, dsl->scene, dsl->layer, 0);
- }
-
- BLI_freelistN(&listbase);
-}
-
-void DAG_ids_check_recalc(Main *bmain, Scene *scene, bool time)
-{
- ListBase *lbarray[MAX_LIBARRAY];
- int a;
- bool updated = false;
-
- if (!DEG_depsgraph_use_legacy()) {
- DEG_ids_check_recalc(bmain, scene, time);
- return;
- }
-
- /* loop over all ID types */
- a = set_listbasepointers(bmain, lbarray);
-
- while (a--) {
- ListBase *lb = lbarray[a];
- ID *id = lb->first;
-
- if (id && bmain->id_tag_update[BKE_idcode_to_index(GS(id->name))]) {
- updated = true;
- break;
- }
- }
-
- dag_editors_scene_update(bmain, scene, (updated || time));
-}
-
-/* It is possible that scene_update_post and frame_update_post handlers
- * will modify objects. The issue is that DAG_ids_clear_recalc is called
- * just after callbacks, which leaves objects with recalc flags but no
- * corresponding bit in ID recalc bitfield. This leads to some kind of
- * regression when using ID type tag fields to check whether there objects
- * to be updated internally comparing threaded DAG with legacy one.
- *
- * For now let's have a workaround which will preserve tag for ID_OB
- * if there're objects with OB_RECALC_ALL bits. This keeps behavior
- * unchanged comparing with 2.69 release.
- *
- * TODO(sergey): Need to get rid of such a workaround.
- *
- * - sergey -
- */
-
-#define POST_UPDATE_HANDLER_WORKAROUND
-
-void DAG_ids_clear_recalc(Main *bmain)
-{
- ListBase *lbarray[MAX_LIBARRAY];
- bNodeTree *ntree;
- int a;
-
-#ifdef POST_UPDATE_HANDLER_WORKAROUND
- bool have_updated_objects = false;
-
- if (DAG_id_type_tagged(bmain, ID_OB)) {
- ListBase listbase;
- DagSceneLayer *dsl;
-
- /* We need to check all visible scenes, otherwise resetting
- * OB_ID changed flag will only work fine for first scene of
- * multiple visible and all the rest will skip update.
- *
- * This could also lead to wrong behavior scene update handlers
- * because of missing ID datablock changed flags.
- *
- * This is a bit of a bummer to allocate list here, but likely
- * it wouldn't become too much bad because it only happens when
- * objects were actually changed.
- */
- dag_current_scene_layers(bmain, &listbase);
-
- for (dsl = listbase.first; dsl; dsl = dsl->next) {
- Scene *scene = dsl->scene;
- DagNode *node;
- for (node = scene->theDag->DagNode.first;
- node != NULL && have_updated_objects == false;
- node = node->next)
- {
- if (node->type == ID_OB) {
- Object *object = (Object *) node->ob;
- if (object->recalc & OB_RECALC_ALL) {
- have_updated_objects = true;
- break;
- }
- }
- }
- }
-
- BLI_freelistN(&listbase);
- }
-#endif
-
- /* loop over all ID types */
- a = set_listbasepointers(bmain, lbarray);
-
- while (a--) {
- ListBase *lb = lbarray[a];
- ID *id = lb->first;
-
- if (id && bmain->id_tag_update[BKE_idcode_to_index(GS(id->name))]) {
- for (; id; id = id->next) {
- id->recalc &= ~ID_RECALC_ALL;
-
- /* some ID's contain semi-datablock nodetree */
- ntree = ntreeFromID(id);
- if (ntree)
- ntree->id.recalc &= ~ID_RECALC_ALL;
- }
- }
- }
-
- memset(bmain->id_tag_update, 0, sizeof(bmain->id_tag_update));
-
-#ifdef POST_UPDATE_HANDLER_WORKAROUND
- if (have_updated_objects) {
- DAG_id_type_tag(bmain, ID_OB);
- }
-#endif
-}
-
-void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag)
-{
- if (!DEG_depsgraph_use_legacy()) {
- DEG_id_tag_update_ex(bmain, id, flag);
- return;
- }
-
- if (id == NULL) return;
-
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s: id=%s flag=%d\n", __func__, id->name, flag);
- }
-
- /* tag ID for update */
- if (flag) {
- if (flag & OB_RECALC_OB)
- lib_id_recalc_tag(bmain, id);
- if (flag & (OB_RECALC_DATA | PSYS_RECALC))
- lib_id_recalc_data_tag(bmain, id);
- }
- else
- lib_id_recalc_tag(bmain, id);
-
- /* flag is for objects and particle systems */
- if (flag) {
- Object *ob;
- short idtype = GS(id->name);
-
- if (idtype == ID_OB) {
- /* only quick tag */
- ob = (Object *)id;
- ob->recalc |= (flag & OB_RECALC_ALL);
- }
- else if (idtype == ID_PA) {
- ParticleSystem *psys;
- /* this is weak still, should be done delayed as well */
- for (ob = bmain->object.first; ob; ob = ob->id.next) {
- for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- if (&psys->part->id == id) {
- ob->recalc |= (flag & OB_RECALC_ALL);
- psys->recalc |= (flag & PSYS_RECALC);
- lib_id_recalc_tag(bmain, &ob->id);
- lib_id_recalc_data_tag(bmain, &ob->id);
- }
- }
- }
- }
- else {
- /* disable because this is called on various ID types automatically.
- * where printing warning is not useful. for now just ignore */
- /* BLI_assert(!"invalid flag for this 'idtype'"); */
- }
- }
- else if (GS(id->name) == ID_CF) {
- for (Object *ob = bmain->object.first; ob; ob = ob->id.next) {
- ModifierData *md = modifiers_findByType(ob, eModifierType_MeshSequenceCache);
-
- if (md) {
- MeshSeqCacheModifierData *mcmd = (MeshSeqCacheModifierData *)md;
-
- if (mcmd->cache_file && (&mcmd->cache_file->id == id)) {
- ob->recalc |= OB_RECALC_ALL;
- continue;
- }
- }
-
- for (bConstraint *con = ob->constraints.first; con; con = con->next) {
- if (con->type != CONSTRAINT_TYPE_TRANSFORM_CACHE) {
- continue;
- }
-
- bTransformCacheConstraint *data = con->data;
-
- if (data->cache_file && (&data->cache_file->id == id)) {
- ob->recalc |= OB_RECALC_ALL;
- break;
- }
- }
- }
- }
-}
-
-void DAG_id_tag_update(ID *id, short flag)
-{
- DAG_id_tag_update_ex(G.main, id, flag);
-}
-
-void DAG_id_type_tag(Main *bmain, short idtype)
-{
- if (idtype == ID_NT) {
- /* stupid workaround so parent datablocks of nested nodetree get looped
- * over when we loop over tagged datablock types */
- DAG_id_type_tag(bmain, ID_MA);
- DAG_id_type_tag(bmain, ID_TE);
- DAG_id_type_tag(bmain, ID_LA);
- DAG_id_type_tag(bmain, ID_WO);
- DAG_id_type_tag(bmain, ID_SCE);
- }
-
- atomic_fetch_and_or_uint8((uint8_t *)&bmain->id_tag_update[BKE_idcode_to_index(idtype)], 1);
-}
-
-int DAG_id_type_tagged(Main *bmain, short idtype)
-{
- return bmain->id_tag_update[BKE_idcode_to_index(idtype)];
-}
-
-#if 0 // UNUSED
-/* recursively descends tree, each node only checked once */
-/* node is checked to be of type object */
-static int parent_check_node(DagNode *node, int curtime)
-{
- DagAdjList *itA;
-
- node->lasttime = curtime;
-
- if (node->color == DAG_GRAY)
- return DAG_GRAY;
-
- for (itA = node->child; itA; itA = itA->next) {
- if (itA->node->type == ID_OB) {
-
- if (itA->node->color == DAG_GRAY)
- return DAG_GRAY;
-
- /* descend if not done */
- if (itA->node->lasttime != curtime) {
- itA->node->color = parent_check_node(itA->node, curtime);
-
- if (itA->node->color == DAG_GRAY)
- return DAG_GRAY;
- }
- }
- }
-
- return DAG_WHITE;
-}
-#endif
-
-/* ******************* DAG FOR ARMATURE POSE ***************** */
-
-/* we assume its an armature with pose */
-void DAG_pose_sort(Object *ob)
-{
- bPose *pose = ob->pose;
- bPoseChannel *pchan;
- bConstraint *con;
- DagNode *node;
- DagNode *node2, *node3;
- DagNode *rootnode;
- DagForest *dag;
- DagNodeQueue *nqueue;
- DagAdjList *itA;
- ListBase tempbase;
- int skip = 0;
-
- dag = dag_init();
- dag->ugly_hack_sorry = false; /* no ID structs */
-
- rootnode = dag_add_node(dag, NULL); /* node->ob becomes NULL */
-
- /* we add the hierarchy and the constraints */
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- int addtoroot = 1;
-
- node = dag_get_node(dag, pchan);
-
- if (pchan->parent) {
- node2 = dag_get_node(dag, pchan->parent);
- dag_add_relation(dag, node2, node, 0, "Parent Relation");
- addtoroot = 0;
- }
- for (con = pchan->constraints.first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- if (ct->tar == ob && ct->subtarget[0]) {
- bPoseChannel *target = BKE_pose_channel_find_name(ob->pose, ct->subtarget);
- if (target) {
- node2 = dag_get_node(dag, target);
- dag_add_relation(dag, node2, node, 0, "Pose Constraint");
-
- if (con->type == CONSTRAINT_TYPE_KINEMATIC) {
- bKinematicConstraint *data = (bKinematicConstraint *)con->data;
- bPoseChannel *parchan;
- int segcount = 0;
-
- /* exclude tip from chain? */
- if (!(data->flag & CONSTRAINT_IK_TIP))
- parchan = pchan->parent;
- else
- parchan = pchan;
-
- /* Walk to the chain's root */
- while (parchan) {
- node3 = dag_get_node(dag, parchan);
- dag_add_relation(dag, node2, node3, 0, "IK Constraint");
-
- segcount++;
- if (segcount == data->rootbone || segcount > 255) break; /* 255 is weak */
- parchan = parchan->parent;
- }
- }
- }
- }
- }
-
- if (cti->flush_constraint_targets)
- cti->flush_constraint_targets(con, &targets, 1);
- }
- }
- if (addtoroot == 1) {
- dag_add_relation(dag, rootnode, node, 0, "Root Bone Relation");
- }
- }
-
- dag_check_cycle(dag);
-
- /* now we try to sort... */
- BLI_listbase_clear(&tempbase);
-
- nqueue = queue_create(DAGQUEUEALLOC);
-
- /* tag nodes unchecked */
- for (node = dag->DagNode.first; node; node = node->next)
- node->color = DAG_WHITE;
-
- rootnode->color = DAG_GRAY;
- push_stack(nqueue, rootnode);
-
- while (nqueue->count) {
-
- skip = 0;
- node = get_top_node_queue(nqueue);
-
- itA = node->child;
- while (itA != NULL) {
- if (itA->node->color == DAG_WHITE) {
- itA->node->color = DAG_GRAY;
- push_stack(nqueue, itA->node);
- skip = 1;
- break;
- }
- itA = itA->next;
- }
-
- if (!skip) {
- if (node) {
- node = pop_queue(nqueue);
- if (node->ob == NULL) /* we are done */
- break;
- node->color = DAG_BLACK;
-
- /* put node in new list */
- BLI_remlink(&pose->chanbase, node->ob);
- BLI_addhead(&tempbase, node->ob);
- }
- }
- }
-
- /* temporal correction for circular dependencies */
- while (pose->chanbase.first) {
- pchan = pose->chanbase.first;
- BLI_remlink(&pose->chanbase, pchan);
- BLI_addhead(&tempbase, pchan);
-
- printf("cyclic %s\n", pchan->name);
- }
-
- pose->chanbase = tempbase;
- queue_delete(nqueue);
-
-// printf("\nordered\n");
-// for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
-// printf(" %s\n", pchan->name);
-// }
-
- free_forest(dag);
- MEM_freeN(dag);
-}
-
-/* ************************ DAG FOR THREADED UPDATE ********************* */
-
-/* Initialize run-time data in the graph needed for traversing it
- * from multiple threads and start threaded tree traversal by adding
- * the root node to the queue.
- *
- * This will mark DAG nodes as object/non-object and will calculate
- * num_pending_parents of nodes (which is how many non-updated parents node
- * have, which helps a lot checking whether node could be scheduled
- * already or not).
- */
-void DAG_threaded_update_begin(Scene *scene,
- void (*func)(void *node, void *user_data),
- void *user_data)
-{
- DagNode *node;
-
- /* We reset num_pending_parents to zero first and tag node as not scheduled yet... */
- for (node = scene->theDag->DagNode.first; node; node = node->next) {
- node->num_pending_parents = 0;
- node->scheduled = false;
- }
-
- /* ... and then iterate over all the nodes and
- * increase num_pending_parents for node childs.
- */
- for (node = scene->theDag->DagNode.first; node; node = node->next) {
- DagAdjList *itA;
-
- for (itA = node->child; itA; itA = itA->next) {
- if (itA->node != node) {
- itA->node->num_pending_parents++;
- }
- }
- }
-
- /* Add root nodes to the queue. */
- BLI_spin_lock(&threaded_update_lock);
- for (node = scene->theDag->DagNode.first; node; node = node->next) {
- if (node->num_pending_parents == 0) {
- node->scheduled = true;
- func(node, user_data);
- }
- }
- BLI_spin_unlock(&threaded_update_lock);
-}
-
-/* This function is called when handling node is done.
- *
- * This function updates num_pending_parents for all childs and
- * schedules them if they're ready.
- */
-void DAG_threaded_update_handle_node_updated(void *node_v,
- void (*func)(void *node, void *user_data),
- void *user_data)
-{
- DagNode *node = node_v;
- DagAdjList *itA;
-
- for (itA = node->child; itA; itA = itA->next) {
- DagNode *child_node = itA->node;
- if (child_node != node) {
- atomic_sub_and_fetch_uint32(&child_node->num_pending_parents, 1);
-
- if (child_node->num_pending_parents == 0) {
- bool need_schedule;
-
- BLI_spin_lock(&threaded_update_lock);
- need_schedule = child_node->scheduled == false;
- child_node->scheduled = true;
- BLI_spin_unlock(&threaded_update_lock);
-
- if (need_schedule) {
- func(child_node, user_data);
- }
- }
- }
- }
-}
-
-/* ************************ DAG DEBUGGING ********************* */
-
-void DAG_print_dependencies(Main *bmain, Scene *scene, Object *ob)
-{
- /* utility for debugging dependencies */
- dag_print_dependencies = 1;
-
- if (ob && (ob->mode & OB_MODE_POSE)) {
- printf("\nDEPENDENCY RELATIONS for %s\n\n", ob->id.name + 2);
- DAG_pose_sort(ob);
- }
- else {
- printf("\nDEPENDENCY RELATIONS for %s\n\n", scene->id.name + 2);
- DAG_scene_relations_rebuild(bmain, scene);
- }
-
- dag_print_dependencies = 0;
-}
-
-/* ************************ DAG querying ********************* */
-
-/* Will return Object ID if node represents Object,
- * and will return NULL otherwise.
- */
-Object *DAG_get_node_object(void *node_v)
-{
- DagNode *node = node_v;
-
- if (node->type == ID_OB) {
- return node->ob;
- }
-
- return NULL;
-}
-
-/* Returns node name, used for debug output only, atm. */
-const char *DAG_get_node_name(Scene *scene, void *node_v)
-{
- DagNode *node = node_v;
-
- return dag_node_name(scene->theDag, node);
-}
-
-short DAG_get_eval_flags_for_object(Scene *scene, void *object)
-{
- DagNode *node;
-
- if (!DEG_depsgraph_use_legacy()) {
- return DEG_get_eval_flags_for_id(scene->depsgraph, (ID *)object);
- }
-
- if (scene->theDag == NULL) {
- /* Happens when converting objects to mesh from a python script
- * after modifying scene graph.
- *
- * Currently harmless because it's only called for temporary
- * objects which are out of the DAG anyway.
- */
- return 0;
- }
-
- node = dag_find_node(scene->theDag, object);
-
- if (node) {
- return node->eval_flags;
- }
- else {
- /* Happens when external render engine exports temporary objects
- * which are not in the DAG.
- */
-
- /* TODO(sergey): Doublecheck objects with Curve Deform exports all fine. */
-
- /* TODO(sergey): Weak but currently we can't really access proper DAG from
- * the modifiers stack. This is because in most cases modifier is to use
- * the foreground scene, but to access evaluation flags we need to know
- * active background scene, which we don't know.
- */
- if (scene->set) {
- return DAG_get_eval_flags_for_object(scene->set, object);
- }
- return 0;
- }
-}
-
-bool DAG_is_acyclic(Scene *scene)
-{
- return scene->theDag->is_acyclic;
-}
-
-#else
-
-/* *********************************************************************
- * Stubs to avoid linking issues and make sure legacy crap is not used *
- * *********************************************************************
- */
-
-DagNodeQueue *queue_create(int UNUSED(slots))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return NULL;
-}
-
-void queue_raz(DagNodeQueue *UNUSED(queue))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-void queue_delete(DagNodeQueue *UNUSED(queue))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-void push_queue(DagNodeQueue *UNUSED(queue), DagNode *UNUSED(node))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-void push_stack(DagNodeQueue *UNUSED(queue), DagNode *UNUSED(node))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-DagNode *pop_queue(DagNodeQueue *UNUSED(queue))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return NULL;
-}
-
-DagNode *get_top_node_queue(DagNodeQueue *UNUSED(queue))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return NULL;
-}
-
-DagForest *dag_init(void)
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return NULL;
-}
-
-DagForest *build_dag(Main *UNUSED(bmain),
- Scene *UNUSED(sce),
- short UNUSED(mask))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return NULL;
-}
-
-void free_forest(DagForest *UNUSED(Dag))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-DagNode *dag_find_node(DagForest *UNUSED(forest), void *UNUSED(fob))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return NULL;
-}
-
-DagNode *dag_add_node(DagForest *UNUSED(forest), void *UNUSED(fob))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return NULL;
-}
-
-DagNode *dag_get_node(DagForest *UNUSED(forest), void *UNUSED(fob))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return NULL;
-}
-
-DagNode *dag_get_sub_node(DagForest *UNUSED(forest), void *UNUSED(fob))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return NULL;
-}
-
-void dag_add_relation(DagForest *UNUSED(forest),
- DagNode *UNUSED(fob1),
- DagNode *UNUSED(fob2),
- short UNUSED(rel),
- const char *UNUSED(name))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-/* debug test functions */
-
-void graph_print_queue(DagNodeQueue *UNUSED(nqueue))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-void graph_print_queue_dist(DagNodeQueue *UNUSED(nqueue))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-void graph_print_adj_list(DagForest *UNUSED(dag))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-void DAG_scene_flush_update(Main *UNUSED(bmain),
- Scene *UNUSED(sce),
- unsigned int UNUSED(lay),
- const short UNUSED(time))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-void DAG_scene_update_flags(Main *UNUSED(bmain),
- Scene *UNUSED(scene),
- unsigned int UNUSED(lay),
- const bool UNUSED(do_time),
- const bool UNUSED(do_invisible_flush))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-/* ******************* DAG FOR ARMATURE POSE ***************** */
-
-void DAG_pose_sort(Object *UNUSED(ob))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
-}
-
-/* ************************ DAG FOR THREADED UPDATE ********************* */
-
-void DAG_threaded_update_begin(Scene *UNUSED(scene),
- void (*func)(void *node, void *user_data),
- void *UNUSED(user_data))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- (void)func;
-}
-
-void DAG_threaded_update_handle_node_updated(void *UNUSED(node_v),
- void (*func)(void *node, void *user_data),
- void *UNUSED(user_data))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- (void)func;
-}
-
-/* ************************ DAG querying ********************* */
-
-Object *DAG_get_node_object(void *UNUSED(node_v))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return NULL;
-}
-
-const char *DAG_get_node_name(Scene *UNUSED(scene), void *UNUSED(node_v))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return "INVALID";
-}
-
-bool DAG_is_acyclic(Scene *UNUSED(scene))
-{
- BLI_assert(!"Should not be used with new dependnecy graph");
- return false;
-}
-
-/* ************************************
- * This functions are to be supported *
- * ************************************
- */
-
-void DAG_init(void)
-{
- DEG_register_node_types();
-}
-
-void DAG_exit(void)
-{
- DEG_free_node_types();
-}
-
-/* ************************ API *********************** */
-
-void DAG_editors_update_cb(DEG_EditorUpdateIDCb id_func,
- DEG_EditorUpdateSceneCb scene_func,
- DEG_EditorUpdateScenePreCb scene_func_pre)
-{
- DEG_editors_set_update_cb(id_func, scene_func, scene_func_pre);
-}
-
-void DAG_editors_update_pre(Main *bmain, Scene *scene, bool time)
-{
- DEG_editors_update_pre(bmain, scene, time);
-}
-
-/* Tag all relations for update. */
-void DAG_relations_tag_update(Main *bmain)
-{
- DEG_relations_tag_update(bmain);
-}
-
-/* Rebuild dependency graph only for a given scene. */
-void DAG_scene_relations_rebuild(Main *bmain, Scene *scene)
-{
- DEG_scene_relations_rebuild(bmain, scene);
-}
-
-/* Create dependency graph if it was cleared or didn't exist yet. */
-void DAG_scene_relations_update(Main *bmain, Scene *scene)
-{
- DEG_scene_relations_update(bmain, scene);
-}
-
-void DAG_scene_relations_validate(Main *bmain, Scene *scene)
-{
- DEG_debug_scene_relations_validate(bmain, scene);
-}
-
-void DAG_scene_free(Scene *scene)
-{
- DEG_scene_graph_free(scene);
-}
-
-void DAG_on_visible_update(Main *bmain, const bool do_time)
-{
- DEG_on_visible_update(bmain, do_time);
-}
-
-void DAG_ids_check_recalc(Main *bmain, Scene *scene, bool time)
-{
- DEG_ids_check_recalc(bmain, scene, time);
-}
-
-void DAG_id_tag_update(ID *id, short flag)
-{
- DEG_id_tag_update_ex(G.main, id, flag);
-}
-
-void DAG_id_tag_update_ex(Main *bmain, ID *id, short flag)
-{
- DEG_id_tag_update_ex(bmain, id, flag);
-}
-
-void DAG_id_type_tag(Main *bmain, short idtype)
-{
- DEG_id_type_tag(bmain, idtype);
-}
-
-int DAG_id_type_tagged(Main *bmain, short idtype)
-{
- return DEG_id_type_tagged(bmain, idtype);
-}
-
-void DAG_ids_clear_recalc(Main *bmain)
-{
- DEG_ids_clear_recalc(bmain);
-}
-
-short DAG_get_eval_flags_for_object(Scene *scene, void *object)
-{
- return DEG_get_eval_flags_for_id(scene->depsgraph, (ID *)object);
-}
-
-void DAG_ids_flush_tagged(Main *bmain)
-{
- DEG_ids_flush_tagged(bmain);
-}
-
-/* ************************ DAG DEBUGGING ********************* */
-
-void DAG_print_dependencies(Main *UNUSED(bmain),
- Scene *scene,
- Object *UNUSED(ob))
-{
- DEG_debug_relations_graphviz(scene->depsgraph, stdout, "Depsgraph");
-}
-
-#endif
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 2a300cbe47b..15a520fe8ce 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -48,7 +48,6 @@
#include "BLI_utildefines.h"
#include "BKE_global.h"
-#include "BKE_depsgraph.h"
#include "BKE_displist.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_object.h"
@@ -63,6 +62,9 @@
#include "BLI_sys_types.h" // for intptr_t support
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
static void boundbox_displist_object(Object *ob);
void BKE_displist_elem_free(DispList *dl)
@@ -676,7 +678,7 @@ static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dis
* - first point left, last point right
* - based on subdivided points in original curve, not on points in taper curve (still)
*/
-static float displist_calc_taper(Scene *scene, Object *taperobj, float fac)
+static float displist_calc_taper(const EvaluationContext *eval_ctx, Scene *scene, Object *taperobj, float fac)
{
DispList *dl;
@@ -685,7 +687,7 @@ static float displist_calc_taper(Scene *scene, Object *taperobj, float fac)
dl = taperobj->curve_cache ? taperobj->curve_cache->disp.first : NULL;
if (dl == NULL) {
- BKE_displist_make_curveTypes(scene, taperobj, 0);
+ BKE_displist_make_curveTypes(eval_ctx, scene, taperobj, 0);
dl = taperobj->curve_cache->disp.first;
}
if (dl) {
@@ -716,14 +718,14 @@ static float displist_calc_taper(Scene *scene, Object *taperobj, float fac)
return 1.0;
}
-float BKE_displist_calc_taper(Scene *scene, Object *taperobj, int cur, int tot)
+float BKE_displist_calc_taper(const EvaluationContext *eval_ctx, Scene *scene, Object *taperobj, int cur, int tot)
{
float fac = ((float)cur) / (float)(tot - 1);
- return displist_calc_taper(scene, taperobj, fac);
+ return displist_calc_taper(eval_ctx, scene, taperobj, fac);
}
-void BKE_displist_make_mball(EvaluationContext *eval_ctx, Scene *scene, Object *ob)
+void BKE_displist_make_mball(const EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
if (!ob || ob->type != OB_MBALL)
return;
@@ -746,7 +748,7 @@ void BKE_displist_make_mball(EvaluationContext *eval_ctx, Scene *scene, Object *
}
}
-void BKE_displist_make_mball_forRender(EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase)
+void BKE_displist_make_mball_forRender(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase)
{
BKE_mball_polygonize(eval_ctx, scene, ob, dispbase);
BKE_mball_texspace_calc(ob);
@@ -796,8 +798,9 @@ static ModifierData *curve_get_tessellate_point(Scene *scene, Object *ob,
return pretessellatePoint;
}
-static void curve_calc_modifiers_pre(Scene *scene, Object *ob, ListBase *nurb,
- const bool for_render, const bool use_render_resolution)
+static void curve_calc_modifiers_pre(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *nurb,
+ const bool for_render, const bool use_render_resolution)
{
VirtualModifierData virtualModifierData;
ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
@@ -854,7 +857,7 @@ static void curve_calc_modifiers_pre(Scene *scene, Object *ob, ListBase *nurb,
deformedVerts = BKE_curve_nurbs_vertexCos_get(nurb, &numVerts);
}
- mti->deformVerts(md, ob, NULL, deformedVerts, numVerts, app_flag);
+ mti->deformVerts(md, eval_ctx, ob, NULL, deformedVerts, numVerts, app_flag);
if (md == pretessellatePoint)
break;
@@ -906,9 +909,10 @@ static void displist_apply_allverts(ListBase *dispbase, float (*allverts)[3])
}
}
-static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *nurb,
- ListBase *dispbase, DerivedMesh **r_dm_final,
- const bool for_render, const bool use_render_resolution)
+static void curve_calc_modifiers_post(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *nurb,
+ ListBase *dispbase, DerivedMesh **r_dm_final,
+ const bool for_render, const bool use_render_resolution)
{
VirtualModifierData virtualModifierData;
ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
@@ -962,14 +966,14 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *nurb,
dm->getVertCos(dm, vertCos);
}
- mti->deformVerts(md, ob, dm, vertCos, totvert, appf);
+ mti->deformVerts(md, eval_ctx, ob, dm, vertCos, totvert, appf);
}
else {
if (!vertCos) {
vertCos = displist_get_allverts(dispbase, &totvert);
}
- mti->deformVerts(md, ob, NULL, vertCos, totvert, appf);
+ mti->deformVerts(md, eval_ctx, ob, NULL, vertCos, totvert, appf);
}
}
else {
@@ -1011,7 +1015,7 @@ static void curve_calc_modifiers_post(Scene *scene, Object *ob, ListBase *nurb,
if (useCache)
appf |= MOD_APPLY_USECACHE;
- ndm = modwrap_applyModifier(md, ob, dm, appf);
+ ndm = modwrap_applyModifier(md, eval_ctx, ob, dm, appf);
if (ndm) {
/* Modifier returned a new derived mesh */
@@ -1088,13 +1092,13 @@ static void displist_surf_indices(DispList *dl)
}
}
-static DerivedMesh *create_orco_dm(Scene *scene, Object *ob)
+static DerivedMesh *create_orco_dm(const EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
DerivedMesh *dm;
ListBase disp = {NULL, NULL};
/* OrcoDM should be created from underformed disp lists */
- BKE_displist_make_curveTypes_forOrco(scene, ob, &disp);
+ BKE_displist_make_curveTypes_forOrco(eval_ctx, scene, ob, &disp);
dm = CDDM_from_curve_displist(ob, &disp);
BKE_displist_free(&disp);
@@ -1132,8 +1136,9 @@ static void add_orco_dm(Object *ob, DerivedMesh *dm, DerivedMesh *orcodm)
DM_add_vert_layer(dm, CD_ORCO, CD_ASSIGN, orco);
}
-static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *dm_final,
- const bool for_render, const bool use_render_resolution)
+static void curve_calc_orcodm(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, DerivedMesh *dm_final,
+ const bool for_render, const bool use_render_resolution)
{
/* this function represents logic of mesh's orcodm calculation
* for displist-based objects
@@ -1170,7 +1175,7 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *dm_final,
* This means we can create ORCO DM in advance and assume it's
* never NULL.
*/
- orcodm = create_orco_dm(scene, ob);
+ orcodm = create_orco_dm(eval_ctx, scene, ob);
for (; md; md = md->next) {
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -1182,7 +1187,7 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *dm_final,
if (mti->type != eModifierTypeType_Constructive)
continue;
- ndm = modwrap_applyModifier(md, ob, orcodm, app_flag);
+ ndm = modwrap_applyModifier(md, eval_ctx, ob, orcodm, app_flag);
if (ndm) {
/* if the modifier returned a new dm, release the old one */
@@ -1199,9 +1204,10 @@ static void curve_calc_orcodm(Scene *scene, Object *ob, DerivedMesh *dm_final,
orcodm->release(orcodm);
}
-void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase,
- DerivedMesh **r_dm_final,
- const bool for_render, const bool for_orco, const bool use_render_resolution)
+void BKE_displist_make_surf(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase,
+ DerivedMesh **r_dm_final,
+ const bool for_render, const bool for_orco, const bool use_render_resolution)
{
ListBase nubase = {NULL, NULL};
Nurb *nu;
@@ -1218,7 +1224,7 @@ void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase,
}
if (!for_orco)
- curve_calc_modifiers_pre(scene, ob, &nubase, for_render, use_render_resolution);
+ curve_calc_modifiers_pre(eval_ctx, scene, ob, &nubase, for_render, use_render_resolution);
for (nu = nubase.first; nu; nu = nu->next) {
if ((for_render || nu->hide == 0) && BKE_nurb_check_valid_uv(nu)) {
@@ -1285,7 +1291,7 @@ void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase,
if (!for_orco) {
BKE_nurbList_duplicate(&ob->curve_cache->deformed_nurbs, &nubase);
- curve_calc_modifiers_post(scene, ob, &nubase, dispbase, r_dm_final,
+ curve_calc_modifiers_post(eval_ctx, scene, ob, &nubase, dispbase, r_dm_final,
for_render, use_render_resolution);
}
@@ -1511,9 +1517,10 @@ static void calc_bevfac_mapping(Curve *cu, BevList *bl, Nurb *nu,
}
}
-static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispbase,
- DerivedMesh **r_dm_final,
- const bool for_render, const bool for_orco, const bool use_render_resolution)
+static void do_makeDispListCurveTypes(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase,
+ DerivedMesh **r_dm_final,
+ const bool for_render, const bool for_orco, const bool use_render_resolution)
{
Curve *cu = ob->data;
@@ -1521,7 +1528,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
if (!ELEM(ob->type, OB_SURF, OB_CURVE, OB_FONT)) return;
if (ob->type == OB_SURF) {
- BKE_displist_make_surf(scene, ob, dispbase, r_dm_final, for_render, for_orco, use_render_resolution);
+ BKE_displist_make_surf(eval_ctx, scene, ob, dispbase, r_dm_final, for_render, for_orco, use_render_resolution);
}
else if (ELEM(ob->type, OB_CURVE, OB_FONT)) {
ListBase dlbev;
@@ -1546,12 +1553,12 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
}
if (!for_orco)
- curve_calc_modifiers_pre(scene, ob, &nubase, for_render, use_render_resolution);
+ curve_calc_modifiers_pre(eval_ctx, scene, ob, &nubase, for_render, use_render_resolution);
BKE_curve_bevelList_make(ob, &nubase, for_render != false);
/* If curve has no bevel will return nothing */
- BKE_curve_bevel_make(scene, ob, &dlbev, for_render, use_render_resolution);
+ BKE_curve_bevel_make(eval_ctx, scene, ob, &dlbev, for_render, use_render_resolution);
/* no bevel or extrude, and no width correction? */
if (!dlbev.first && cu->width == 1.0f) {
@@ -1686,7 +1693,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
taper_fac -= (1.0f - lastblend) / len;
}
- fac = displist_calc_taper(scene, cu->taperobj, taper_fac);
+ fac = displist_calc_taper(eval_ctx, scene, cu->taperobj, taper_fac);
}
if (bevp->split_tag) {
@@ -1739,7 +1746,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
if (!for_orco) {
if ((cu->flag & CU_PATH) ||
- DAG_get_eval_flags_for_object(scene, ob) & DAG_EVAL_NEED_CURVE_PATH)
+ DEG_get_eval_flags_for_id(eval_ctx->depsgraph, &ob->id) & DAG_EVAL_NEED_CURVE_PATH)
{
calc_curvepath(ob, &nubase);
}
@@ -1747,7 +1754,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
if (!for_orco) {
BKE_nurbList_duplicate(&ob->curve_cache->deformed_nurbs, &nubase);
- curve_calc_modifiers_post(scene, ob, &nubase, dispbase, r_dm_final, for_render, use_render_resolution);
+ curve_calc_modifiers_post(eval_ctx, scene, ob, &nubase, dispbase, r_dm_final, for_render, use_render_resolution);
}
if (cu->flag & CU_DEFORM_FILL && !ob->derivedFinal) {
@@ -1758,7 +1765,7 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba
}
}
-void BKE_displist_make_curveTypes(Scene *scene, Object *ob, const bool for_orco)
+void BKE_displist_make_curveTypes(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, const bool for_orco)
{
ListBase *dispbase;
@@ -1776,35 +1783,38 @@ void BKE_displist_make_curveTypes(Scene *scene, Object *ob, const bool for_orco)
dispbase = &(ob->curve_cache->disp);
- do_makeDispListCurveTypes(scene, ob, dispbase, &ob->derivedFinal, 0, for_orco, 0);
+ do_makeDispListCurveTypes(eval_ctx, scene, ob, dispbase, &ob->derivedFinal, 0, for_orco, 0);
boundbox_displist_object(ob);
}
-void BKE_displist_make_curveTypes_forRender(Scene *scene, Object *ob, ListBase *dispbase,
- DerivedMesh **r_dm_final, const bool for_orco,
- const bool use_render_resolution)
+void BKE_displist_make_curveTypes_forRender(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase,
+ DerivedMesh **r_dm_final, const bool for_orco,
+ const bool use_render_resolution)
{
if (ob->curve_cache == NULL) {
ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve");
}
- do_makeDispListCurveTypes(scene, ob, dispbase, r_dm_final, true, for_orco, use_render_resolution);
+ do_makeDispListCurveTypes(eval_ctx, scene, ob, dispbase, r_dm_final, true, for_orco, use_render_resolution);
}
-void BKE_displist_make_curveTypes_forOrco(struct Scene *scene, struct Object *ob, struct ListBase *dispbase)
+void BKE_displist_make_curveTypes_forOrco(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase)
{
if (ob->curve_cache == NULL) {
ob->curve_cache = MEM_callocN(sizeof(CurveCache), "CurveCache for Curve");
}
- do_makeDispListCurveTypes(scene, ob, dispbase, NULL, 1, 1, 1);
+ do_makeDispListCurveTypes(eval_ctx, scene, ob, dispbase, NULL, 1, 1, 1);
}
/* add Orco layer to the displist object which has got derived mesh and return orco */
-float *BKE_displist_make_orco(Scene *scene, Object *ob, DerivedMesh *dm_final,
- const bool for_render,
- const bool use_render_resolution)
+float *BKE_displist_make_orco(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, DerivedMesh *dm_final,
+ const bool for_render,
+ const bool use_render_resolution)
{
float *orco;
@@ -1812,7 +1822,7 @@ float *BKE_displist_make_orco(Scene *scene, Object *ob, DerivedMesh *dm_final,
dm_final = ob->derivedFinal;
if (!dm_final->getVertDataArray(dm_final, CD_ORCO)) {
- curve_calc_orcodm(scene, ob, dm_final, for_render, use_render_resolution);
+ curve_calc_orcodm(eval_ctx, scene, ob, dm_final, for_render, use_render_resolution);
}
orco = dm_final->getVertDataArray(dm_final, CD_ORCO);
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 41a5d8574e6..2591c3c3c47 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -74,6 +74,8 @@
#include "BKE_pointcache.h"
#include "BKE_scene.h"
+#include "DEG_depsgraph.h"
+
/* for image output */
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -486,36 +488,27 @@ static void scene_setSubframe(Scene *scene, float subframe)
scene->r.subframe = subframe;
}
-static int surface_getBrushFlags(DynamicPaintSurface *surface, const Scene *scene)
+static int surface_getBrushFlags(DynamicPaintSurface *surface, const ViewLayer *view_layer)
{
Base *base = NULL;
- GroupObject *go = NULL;
Object *brushObj = NULL;
ModifierData *md = NULL;
int flags = 0;
if (surface->brush_group)
- go = surface->brush_group->gobject.first;
+ base = FIRSTBASE(surface->brush_group->view_layer);
else
- base = scene->base.first;
+ base = FIRSTBASE(view_layer);
- while (base || go) {
+ while (base) {
brushObj = NULL;
/* select object */
- if (surface->brush_group) {
- if (go->ob)
- brushObj = go->ob;
- }
- else {
- brushObj = base->object;
- }
+ brushObj = base->object;
- if (surface->brush_group)
- go = go->next;
- else
- base = base->next;
+ /* next item */
+ base = base->next;
if (!brushObj) {
continue;
@@ -2071,7 +2064,9 @@ static void canvas_copyDerivedMesh(DynamicPaintCanvasSettings *canvas, DerivedMe
/*
* Updates derived mesh copy and processes dynamic paint step / caches.
*/
-static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd, Scene *scene, Object *ob, DerivedMesh *dm)
+static void dynamicPaint_frameUpdate(
+ DynamicPaintModifierData *pmd, const struct EvaluationContext *eval_ctx, Scene *scene,
+ Object *ob, DerivedMesh *dm)
{
if (pmd->canvas) {
DynamicPaintCanvasSettings *canvas = pmd->canvas;
@@ -2134,7 +2129,7 @@ static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd, Scene *scene
else if (can_simulate) {
/* calculate surface frame */
canvas->flags |= MOD_DPAINT_BAKING;
- dynamicPaint_calculateFrame(surface, scene, ob, current_frame);
+ dynamicPaint_calculateFrame(surface, eval_ctx, scene, ob, current_frame);
canvas->flags &= ~MOD_DPAINT_BAKING;
/* restore canvas derivedmesh if required */
@@ -2153,13 +2148,15 @@ static void dynamicPaint_frameUpdate(DynamicPaintModifierData *pmd, Scene *scene
}
/* Modifier call. Processes dynamic paint modifier step. */
-DerivedMesh *dynamicPaint_Modifier_do(DynamicPaintModifierData *pmd, Scene *scene, Object *ob, DerivedMesh *dm)
+DerivedMesh *dynamicPaint_Modifier_do(
+ DynamicPaintModifierData *pmd, const struct EvaluationContext *eval_ctx, Scene *scene,
+ Object *ob, DerivedMesh *dm)
{
if (pmd->canvas) {
DerivedMesh *ret;
/* Update canvas data for a new frame */
- dynamicPaint_frameUpdate(pmd, scene, ob, dm);
+ dynamicPaint_frameUpdate(pmd, eval_ctx, scene, ob, dm);
/* Return output mesh */
ret = dynamicPaint_Modifier_apply(pmd, ob, dm);
@@ -2168,7 +2165,7 @@ DerivedMesh *dynamicPaint_Modifier_do(DynamicPaintModifierData *pmd, Scene *scen
}
else {
/* Update canvas data for a new frame */
- dynamicPaint_frameUpdate(pmd, scene, ob, dm);
+ dynamicPaint_frameUpdate(pmd, eval_ctx, scene, ob, dm);
/* Return output mesh */
return dynamicPaint_Modifier_apply(pmd, ob, dm);
@@ -3743,7 +3740,8 @@ static void dynamic_paint_brush_velocity_compute_cb(
}
static void dynamicPaint_brushMeshCalculateVelocity(
- Scene *scene, Object *ob, DynamicPaintBrushSettings *brush, Vec3f **brushVel, float timescale)
+ const struct EvaluationContext *eval_ctx, Scene *scene,
+ Object *ob, DynamicPaintBrushSettings *brush, Vec3f **brushVel, float timescale)
{
float prev_obmat[4][4];
DerivedMesh *dm_p, *dm_c;
@@ -3765,7 +3763,7 @@ static void dynamicPaint_brushMeshCalculateVelocity(
scene->r.subframe = prev_sfra;
BKE_object_modifier_update_subframe(
- scene, ob, true, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint);
+ eval_ctx, scene, ob, true, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint);
dm_p = CDDM_copy(brush->dm);
numOfVerts_p = dm_p->getNumVerts(dm_p);
mvert_p = dm_p->getVertArray(dm_p);
@@ -3776,7 +3774,7 @@ static void dynamicPaint_brushMeshCalculateVelocity(
scene->r.subframe = cur_sfra;
BKE_object_modifier_update_subframe(
- scene, ob, true, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint);
+ eval_ctx, scene, ob, true, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint);
dm_c = brush->dm;
numOfVerts_c = dm_c->getNumVerts(dm_c);
mvert_c = dm_p->getVertArray(dm_c);
@@ -3807,7 +3805,7 @@ static void dynamicPaint_brushMeshCalculateVelocity(
}
/* calculate velocity for object center point */
-static void dynamicPaint_brushObjectCalculateVelocity(Scene *scene, Object *ob, Vec3f *brushVel, float timescale)
+static void dynamicPaint_brushObjectCalculateVelocity(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, Vec3f *brushVel, float timescale)
{
float prev_obmat[4][4];
float cur_loc[3] = {0.0f}, prev_loc[3] = {0.0f};
@@ -3826,14 +3824,14 @@ static void dynamicPaint_brushObjectCalculateVelocity(Scene *scene, Object *ob,
scene->r.cfra = prev_fra;
scene->r.subframe = prev_sfra;
BKE_object_modifier_update_subframe(
- scene, ob, false, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint);
+ eval_ctx, scene, ob, false, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint);
copy_m4_m4(prev_obmat, ob->obmat);
/* current frame dm */
scene->r.cfra = cur_fra;
scene->r.subframe = cur_sfra;
BKE_object_modifier_update_subframe(
- scene, ob, false, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint);
+ eval_ctx, scene, ob, false, SUBFRAME_RECURSION, BKE_scene_frame_get(scene), eModifierType_DynamicPaint);
/* calculate speed */
mul_m4_v3(prev_obmat, prev_loc);
@@ -4205,7 +4203,7 @@ static void dynamic_paint_paint_mesh_cell_point_cb_ex(
}
}
-static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
+static int dynamicPaint_paintMesh(const struct EvaluationContext *eval_ctx, DynamicPaintSurface *surface,
DynamicPaintBrushSettings *brush,
Object *brushOb,
BrushMaterials *bMats,
@@ -4221,7 +4219,7 @@ static int dynamicPaint_paintMesh(DynamicPaintSurface *surface,
const MLoop *mloop = NULL;
if (brush->flags & MOD_DPAINT_USES_VELOCITY)
- dynamicPaint_brushMeshCalculateVelocity(scene, brushOb, brush, &brushVelocity, timescale);
+ dynamicPaint_brushMeshCalculateVelocity(eval_ctx, scene, brushOb, brush, &brushVelocity, timescale);
if (!brush->dm)
return 0;
@@ -4711,7 +4709,7 @@ static void dynamic_paint_paint_single_point_cb_ex(
}
static int dynamicPaint_paintSinglePoint(
- DynamicPaintSurface *surface, float *pointCoord, DynamicPaintBrushSettings *brush,
+ const struct EvaluationContext *eval_ctx, DynamicPaintSurface *surface, float *pointCoord, DynamicPaintBrushSettings *brush,
Object *brushOb, BrushMaterials *bMats, Scene *scene, float timescale)
{
PaintSurfaceData *sData = surface->data;
@@ -4719,7 +4717,7 @@ static int dynamicPaint_paintSinglePoint(
Vec3f brushVel;
if (brush->flags & MOD_DPAINT_USES_VELOCITY)
- dynamicPaint_brushObjectCalculateVelocity(scene, brushOb, &brushVel, timescale);
+ dynamicPaint_brushObjectCalculateVelocity(eval_ctx, scene, brushOb, &brushVel, timescale);
const MVert *mvert = brush->dm->getVertArray(brush->dm);
@@ -5041,7 +5039,7 @@ static void dynamic_paint_prepare_effect_cb(
}
static int dynamicPaint_prepareEffectStep(
- DynamicPaintSurface *surface, Scene *scene, Object *ob, float **force, float timescale)
+ const struct EvaluationContext *eval_ctx, DynamicPaintSurface *surface, Scene *scene, Object *ob, float **force, float timescale)
{
double average_force = 0.0f;
float shrink_speed = 0.0f, spread_speed = 0.0f;
@@ -5052,7 +5050,7 @@ static int dynamicPaint_prepareEffectStep(
/* Init force data if required */
if (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) {
- ListBase *effectors = pdInitEffectors(scene, ob, NULL, surface->effector_weights, true);
+ ListBase *effectors = pdInitEffectors(eval_ctx, scene, ob, NULL, surface->effector_weights, true);
/* allocate memory for force data (dir vector + strength) */
*force = MEM_mallocN(sData->total_points * 4 * sizeof(float), "PaintEffectForces");
@@ -5884,7 +5882,7 @@ static void dynamic_paint_generate_bake_data_cb(
}
}
-static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, const Scene *scene, Object *ob)
+static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, const ViewLayer *view_layer, Object *ob)
{
PaintSurfaceData *sData = surface->data;
PaintBakeData *bData = sData->bData;
@@ -5892,7 +5890,7 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, const Sce
int index;
bool new_bdata = false;
const bool do_velocity_data = ((surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) ||
- (surface_getBrushFlags(surface, scene) & BRUSH_USES_VELOCITY));
+ (surface_getBrushFlags(surface, view_layer) & BRUSH_USES_VELOCITY));
const bool do_accel_data = (surface->effect & MOD_DPAINT_EFFECT_DO_DRIP) != 0;
int canvasNumOfVerts = dm->getNumVerts(dm);
@@ -6009,7 +6007,7 @@ static int dynamicPaint_generateBakeData(DynamicPaintSurface *surface, const Sce
/*
* Do Dynamic Paint step. Paints scene brush objects of current state/frame to the surface.
*/
-static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *surface, float timescale, float subframe)
+static int dynamicPaint_doStep(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, DynamicPaintSurface *surface, float timescale, float subframe)
{
PaintSurfaceData *sData = surface->data;
PaintBakeData *bData = sData->bData;
@@ -6035,9 +6033,9 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
*/
{
Base *base = NULL;
- GroupObject *go = NULL;
Object *brushObj = NULL;
ModifierData *md = NULL;
+ ViewLayer *view_layer = eval_ctx->view_layer;
/* backup current scene frame */
int scene_frame = scene->r.cfra;
@@ -6045,25 +6043,17 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
/* either from group or from all objects */
if (surface->brush_group)
- go = surface->brush_group->gobject.first;
+ base = FIRSTBASE(surface->brush_group->view_layer);
else
- base = scene->base.first;
+ base = FIRSTBASE(view_layer);
- while (base || go) {
+ while (base) {
brushObj = NULL;
/* select object */
- if (surface->brush_group) {
- if (go->ob)
- brushObj = go->ob;
- }
- else
- brushObj = base->object;
+ brushObj = base->object;
/* next item */
- if (surface->brush_group)
- go = go->next;
- else
- base = base->next;
+ base = base->next;
if (!brushObj) {
/* skip item */
@@ -6092,7 +6082,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
/* update object data on this subframe */
if (subframe) {
scene_setSubframe(scene, subframe);
- BKE_object_modifier_update_subframe(scene, brushObj, true, SUBFRAME_RECURSION,
+ BKE_object_modifier_update_subframe(eval_ctx, scene, brushObj, true, SUBFRAME_RECURSION,
BKE_scene_frame_get(scene), eModifierType_DynamicPaint);
}
/* Prepare materials if required */
@@ -6100,8 +6090,6 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
dynamicPaint_updateBrushMaterials(brushObj, brush->mat, scene, &bMats);
/* Apply brush on the surface depending on it's collision type */
- /* Particle brush: */
- if (brush->collision == MOD_DPAINT_COL_PSYS) {
if (brush->psys && brush->psys->part &&
ELEM(brush->psys->part->type, PART_EMITTER, PART_FLUID) &&
psys_check_enabled(brushObj, brush->psys, G.is_rendering))
@@ -6111,14 +6099,13 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
BKE_scene_frame_get(scene), ADT_RECALC_ANIM);
dynamicPaint_paintParticles(surface, brush->psys, brush, timescale);
}
- }
/* Object center distance: */
- else if (brush->collision == MOD_DPAINT_COL_POINT && brushObj != ob) {
- dynamicPaint_paintSinglePoint(surface, brushObj->loc, brush, brushObj, &bMats, scene, timescale);
+ if (brush->collision == MOD_DPAINT_COL_POINT && brushObj != ob) {
+ dynamicPaint_paintSinglePoint(eval_ctx, surface, brushObj->loc, brush, brushObj, &bMats, scene, timescale);
}
/* Mesh volume/proximity: */
else if (brushObj != ob) {
- dynamicPaint_paintMesh(surface, brush, brushObj, &bMats, scene, timescale);
+ dynamicPaint_paintMesh(eval_ctx, surface, brush, brushObj, &bMats, scene, timescale);
}
/* free temp material data */
@@ -6128,7 +6115,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
if (subframe) {
scene->r.cfra = scene_frame;
scene->r.subframe = scene_subframe;
- BKE_object_modifier_update_subframe(scene, brushObj, true, SUBFRAME_RECURSION,
+ BKE_object_modifier_update_subframe(eval_ctx, scene, brushObj, true, SUBFRAME_RECURSION,
BKE_scene_frame_get(scene), eModifierType_DynamicPaint);
}
@@ -6163,7 +6150,7 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
return setError(canvas, N_("Not enough free memory"));
/* Prepare effects and get number of required steps */
- steps = dynamicPaint_prepareEffectStep(surface, scene, ob, &force, timescale);
+ steps = dynamicPaint_prepareEffectStep(eval_ctx, surface, scene, ob, &force, timescale);
for (s = 0; s < steps; s++) {
dynamicPaint_doEffectStep(surface, force, prevPoint, timescale, (float)steps);
}
@@ -6187,7 +6174,9 @@ static int dynamicPaint_doStep(Scene *scene, Object *ob, DynamicPaintSurface *su
/*
* Calculate a single frame and included subframes for surface
*/
-int dynamicPaint_calculateFrame(DynamicPaintSurface *surface, Scene *scene, Object *cObject, int frame)
+int dynamicPaint_calculateFrame(
+ DynamicPaintSurface *surface, const struct EvaluationContext *eval_ctx,
+ Scene *scene, Object *cObject, int frame)
{
float timescale = 1.0f;
@@ -6196,7 +6185,7 @@ int dynamicPaint_calculateFrame(DynamicPaintSurface *surface, Scene *scene, Obje
dynamicPaint_applySurfaceDisplace(surface, surface->canvas->dm);
/* update bake data */
- dynamicPaint_generateBakeData(surface, scene, cObject);
+ dynamicPaint_generateBakeData(surface, eval_ctx->view_layer, cObject);
/* don't do substeps for first frame */
if (surface->substeps && (frame != surface->start_frame)) {
@@ -6205,10 +6194,10 @@ int dynamicPaint_calculateFrame(DynamicPaintSurface *surface, Scene *scene, Obje
for (st = 1; st <= surface->substeps; st++) {
float subframe = ((float) st) / (surface->substeps + 1);
- if (!dynamicPaint_doStep(scene, cObject, surface, timescale, subframe))
+ if (!dynamicPaint_doStep(eval_ctx, scene, cObject, surface, timescale, subframe))
return 0;
}
}
- return dynamicPaint_doStep(scene, cObject, surface, timescale, 0.0f);
+ return dynamicPaint_doStep(eval_ctx, scene, cObject, surface, timescale, 0.0f);
}
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index be8fcaa6863..0491cbd21f0 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -52,6 +52,7 @@
#include "BKE_mesh.h"
#include "BKE_editmesh.h"
#include "BKE_editmesh_bvh.h"
+#include "BKE_editmesh_tangent.h"
#include "DNA_scene_types.h"
#include "DNA_object_types.h"
@@ -242,392 +243,29 @@ static void emDM_calcLoopNormalsSpaceArray(
#endif
}
-
-/** \name Tangent Space Calculation
- * \{ */
-
-/* Necessary complexity to handle looptri's as quads for correct tangents */
-#define USE_LOOPTRI_DETECT_QUADS
-
-typedef struct {
- const float (*precomputedFaceNormals)[3];
- const float (*precomputedLoopNormals)[3];
- const BMLoop *(*looptris)[3];
- int cd_loop_uv_offset; /* texture coordinates */
- const float (*orco)[3];
- float (*tangent)[4]; /* destination */
- int numTessFaces;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- /* map from 'fake' face index to looptri,
- * quads will point to the first looptri of the quad */
- const int *face_as_quad_map;
- int num_face_as_quad_map;
-#endif
-
-} SGLSLEditMeshToTangent;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
-/* seems weak but only used on quads */
-static const BMLoop *bm_loop_at_face_index(const BMFace *f, int vert_index)
-{
- const BMLoop *l = BM_FACE_FIRST_LOOP(f);
- while (vert_index--) {
- l = l->next;
- }
- return l;
-}
-#endif
-
-/* interface */
-#include "mikktspace.h"
-
-static int emdm_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
-{
- SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- return pMesh->num_face_as_quad_map;
-#else
- return pMesh->numTessFaces;
-#endif
-}
-
-static int emdm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
-{
-#ifdef USE_LOOPTRI_DETECT_QUADS
- SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
- if (pMesh->face_as_quad_map) {
- const BMLoop **lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
- if (lt[0]->f->len == 4) {
- return 4;
- }
- }
- return 3;
-#else
- UNUSED_VARS(pContext, face_num);
- return 3;
-#endif
-}
-
-static void emdm_ts_GetPosition(
- const SMikkTSpaceContext *pContext, float r_co[3],
- const int face_num, const int vert_index)
-{
- //assert(vert_index >= 0 && vert_index < 4);
- SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
- const BMLoop **lt;
- const BMLoop *l;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- if (pMesh->face_as_quad_map) {
- lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
- if (lt[0]->f->len == 4) {
- l = bm_loop_at_face_index(lt[0]->f, vert_index);
- goto finally;
- }
- /* fall through to regular triangle */
- }
- else {
- lt = pMesh->looptris[face_num];
- }
-#else
- lt = pMesh->looptris[face_num];
-#endif
- l = lt[vert_index];
-
- const float *co;
-
-finally:
- co = l->v->co;
- copy_v3_v3(r_co, co);
-}
-
-static void emdm_ts_GetTextureCoordinate(
- const SMikkTSpaceContext *pContext, float r_uv[2],
- const int face_num, const int vert_index)
-{
- //assert(vert_index >= 0 && vert_index < 4);
- SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
- const BMLoop **lt;
- const BMLoop *l;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- if (pMesh->face_as_quad_map) {
- lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
- if (lt[0]->f->len == 4) {
- l = bm_loop_at_face_index(lt[0]->f, vert_index);
- goto finally;
- }
- /* fall through to regular triangle */
- }
- else {
- lt = pMesh->looptris[face_num];
- }
-#else
- lt = pMesh->looptris[face_num];
-#endif
- l = lt[vert_index];
-
-finally:
- if (pMesh->cd_loop_uv_offset != -1) {
- const float *uv = BM_ELEM_CD_GET_VOID_P(l, pMesh->cd_loop_uv_offset);
- copy_v2_v2(r_uv, uv);
- }
- else {
- const float *orco = pMesh->orco[BM_elem_index_get(l->v)];
- map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]);
- }
-}
-
-static void emdm_ts_GetNormal(
- const SMikkTSpaceContext *pContext, float r_no[3],
- const int face_num, const int vert_index)
-{
- //assert(vert_index >= 0 && vert_index < 4);
- SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
- const BMLoop **lt;
- const BMLoop *l;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- if (pMesh->face_as_quad_map) {
- lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
- if (lt[0]->f->len == 4) {
- l = bm_loop_at_face_index(lt[0]->f, vert_index);
- goto finally;
- }
- /* fall through to regular triangle */
- }
- else {
- lt = pMesh->looptris[face_num];
- }
-#else
- lt = pMesh->looptris[face_num];
-#endif
- l = lt[vert_index];
-
-finally:
- if (pMesh->precomputedLoopNormals) {
- copy_v3_v3(r_no, pMesh->precomputedLoopNormals[BM_elem_index_get(l)]);
- }
- else if (BM_elem_flag_test(l->f, BM_ELEM_SMOOTH) == 0) { /* flat */
- if (pMesh->precomputedFaceNormals) {
- copy_v3_v3(r_no, pMesh->precomputedFaceNormals[BM_elem_index_get(l->f)]);
- }
- else {
- copy_v3_v3(r_no, l->f->no);
- }
- }
- else {
- copy_v3_v3(r_no, l->v->no);
- }
-}
-
-static void emdm_ts_SetTSpace(
- const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign,
- const int face_num, const int vert_index)
-{
- //assert(vert_index >= 0 && vert_index < 4);
- SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
- const BMLoop **lt;
- const BMLoop *l;
-
-#ifdef USE_LOOPTRI_DETECT_QUADS
- if (pMesh->face_as_quad_map) {
- lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
- if (lt[0]->f->len == 4) {
- l = bm_loop_at_face_index(lt[0]->f, vert_index);
- goto finally;
- }
- /* fall through to regular triangle */
- }
- else {
- lt = pMesh->looptris[face_num];
- }
-#else
- lt = pMesh->looptris[face_num];
-#endif
- l = lt[vert_index];
-
- float *pRes;
-
-finally:
- pRes = pMesh->tangent[BM_elem_index_get(l)];
- copy_v3_v3(pRes, fvTangent);
- pRes[3] = fSign;
-}
-
-static void emDM_calc_loop_tangents_thread(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
-{
- struct SGLSLEditMeshToTangent *mesh2tangent = taskdata;
- /* new computation method */
- {
- SMikkTSpaceContext sContext = {NULL};
- SMikkTSpaceInterface sInterface = {NULL};
- sContext.m_pUserData = mesh2tangent;
- sContext.m_pInterface = &sInterface;
- sInterface.m_getNumFaces = emdm_ts_GetNumFaces;
- sInterface.m_getNumVerticesOfFace = emdm_ts_GetNumVertsOfFace;
- sInterface.m_getPosition = emdm_ts_GetPosition;
- sInterface.m_getTexCoord = emdm_ts_GetTextureCoordinate;
- sInterface.m_getNormal = emdm_ts_GetNormal;
- sInterface.m_setTSpaceBasic = emdm_ts_SetTSpace;
- /* 0 if failed */
- genTangSpaceDefault(&sContext);
- }
-}
-
-/**
- * \see #DM_calc_loop_tangents, same logic but used arrays instead of #BMesh data.
- *
- * \note This function is not so normal, its using `bm->ldata` as input, but output's to `dm->loopData`.
- * This is done because #CD_TANGENT is cache data used only for drawing.
- */
-
static void emDM_calc_loop_tangents(
DerivedMesh *dm, bool calc_active_tangent,
- const char (*tangent_names)[MAX_NAME], int tangent_names_count)
+ const char (*tangent_names)[MAX_NAME], int tangent_names_len)
{
EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
BMEditMesh *em = bmdm->em;
- BMesh *bm = bmdm->em->bm;
-
- int act_uv_n = -1;
- int ren_uv_n = -1;
- bool calc_act = false;
- bool calc_ren = false;
- char act_uv_name[MAX_NAME];
- char ren_uv_name[MAX_NAME];
- short tangent_mask = 0;
-
- DM_calc_loop_tangents_step_0(
- &bm->ldata, calc_active_tangent, tangent_names, tangent_names_count,
- &calc_act, &calc_ren, &act_uv_n, &ren_uv_n, act_uv_name, ren_uv_name, &tangent_mask);
-
- if ((dm->tangent_mask | tangent_mask) != dm->tangent_mask) {
- for (int i = 0; i < tangent_names_count; i++)
- if (tangent_names[i][0])
- DM_add_named_tangent_layer_for_uv(&bm->ldata, &dm->loopData, dm->numLoopData, tangent_names[i]);
- if ((tangent_mask & DM_TANGENT_MASK_ORCO) && CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, "") == -1)
- CustomData_add_layer_named(&dm->loopData, CD_TANGENT, CD_CALLOC, NULL, dm->numLoopData, "");
- if (calc_act && act_uv_name[0])
- DM_add_named_tangent_layer_for_uv(&bm->ldata, &dm->loopData, dm->numLoopData, act_uv_name);
- if (calc_ren && ren_uv_name[0])
- DM_add_named_tangent_layer_for_uv(&bm->ldata, &dm->loopData, dm->numLoopData, ren_uv_name);
- int totface = em->tottri;
-#ifdef USE_LOOPTRI_DETECT_QUADS
- int num_face_as_quad_map;
- int *face_as_quad_map = NULL;
-
- /* map faces to quads */
- if (bmdm->em->tottri != bm->totface) {
- /* over alloc, since we dont know how many ngon or quads we have */
-
- /* map fake face index to looptri */
- face_as_quad_map = MEM_mallocN(sizeof(int) * totface, __func__);
- int i, j;
- for (i = 0, j = 0; j < totface; i++, j++) {
- face_as_quad_map[i] = j;
- /* step over all quads */
- if (em->looptris[j][0]->f->len == 4) {
- j++; /* skips the nest looptri */
- }
- }
- num_face_as_quad_map = i;
- }
- else {
- num_face_as_quad_map = totface;
- }
-#endif
- /* Calculation */
- {
- TaskScheduler *scheduler = BLI_task_scheduler_get();
- TaskPool *task_pool;
- task_pool = BLI_task_pool_create(scheduler, NULL);
-
- dm->tangent_mask = 0;
- /* Calculate tangent layers */
- SGLSLEditMeshToTangent data_array[MAX_MTFACE];
- int index = 0;
- int n = 0;
- CustomData_update_typemap(&dm->loopData);
- const int tangent_layer_num = CustomData_number_of_layers(&dm->loopData, CD_TANGENT);
- for (n = 0; n < tangent_layer_num; n++) {
- index = CustomData_get_layer_index_n(&dm->loopData, CD_TANGENT, n);
- BLI_assert(n < MAX_MTFACE);
- SGLSLEditMeshToTangent *mesh2tangent = &data_array[n];
- mesh2tangent->numTessFaces = em->tottri;
-#ifdef USE_LOOPTRI_DETECT_QUADS
- mesh2tangent->face_as_quad_map = face_as_quad_map;
- mesh2tangent->num_face_as_quad_map = num_face_as_quad_map;
-#endif
- mesh2tangent->precomputedFaceNormals = bmdm->polyNos; /* dm->getPolyDataArray(dm, CD_NORMAL) */
- /* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled),
- * have to check this is valid...
- */
- mesh2tangent->precomputedLoopNormals = CustomData_get_layer(&dm->loopData, CD_NORMAL);
- mesh2tangent->cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, n);
-
- /* needed for indexing loop-tangents */
- int htype_index = BM_LOOP;
- if (mesh2tangent->cd_loop_uv_offset == -1) {
- mesh2tangent->orco = dm->getVertDataArray(dm, CD_ORCO);
- if (!mesh2tangent->orco)
- continue;
- /* needed for orco lookups */
- htype_index |= BM_VERT;
- dm->tangent_mask |= DM_TANGENT_MASK_ORCO;
- }
- else {
- /* Fill the resulting tangent_mask */
- int uv_ind = CustomData_get_named_layer_index(&bm->ldata, CD_MLOOPUV, dm->loopData.layers[index].name);
- int uv_start = CustomData_get_layer_index(&bm->ldata, CD_MLOOPUV);
- BLI_assert(uv_ind != -1 && uv_start != -1);
- BLI_assert(uv_ind - uv_start < MAX_MTFACE);
- dm->tangent_mask |= 1 << (uv_ind - uv_start);
- }
-
- if (mesh2tangent->precomputedFaceNormals) {
- /* needed for face normal lookups */
- htype_index |= BM_FACE;
- }
- BM_mesh_elem_index_ensure(bm, htype_index);
- mesh2tangent->looptris = (const BMLoop *(*)[3])em->looptris;
- mesh2tangent->tangent = dm->loopData.layers[index].data;
-
- BLI_task_pool_push(task_pool, emDM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW);
- }
-
- BLI_assert(dm->tangent_mask == tangent_mask);
- BLI_task_pool_work_and_wait(task_pool);
- BLI_task_pool_free(task_pool);
- }
-#ifdef USE_LOOPTRI_DETECT_QUADS
- if (face_as_quad_map) {
- MEM_freeN(face_as_quad_map);
- }
-#undef USE_LOOPTRI_DETECT_QUADS
-#endif
+ if (CustomData_number_of_layers(&em->bm->ldata, CD_MLOOPUV) == 0) {
+ return;
}
- /* Update active layer index */
- int act_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, act_uv_n);
- if (act_uv_index >= 0) {
- int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, bm->ldata.layers[act_uv_index].name);
- CustomData_set_layer_active_index(&dm->loopData, CD_TANGENT, tan_index);
- } /* else tangent has been built from orco */
-
- /* Update render layer index */
- int ren_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, ren_uv_n);
- if (ren_uv_index >= 0) {
- int tan_index = CustomData_get_named_layer_index(&dm->loopData, CD_TANGENT, bm->ldata.layers[ren_uv_index].name);
- CustomData_set_layer_render_index(&dm->loopData, CD_TANGENT, tan_index);
- } /* else tangent has been built from orco */
+ const float (*poly_normals)[3] = bmdm->polyNos;
+ const float (*loop_normals)[3] = CustomData_get_layer(&dm->loopData, CD_NORMAL);
+ const float (*vert_orco)[3] = dm->getVertDataArray(dm, CD_ORCO); /* can be NULL */
+ BKE_editmesh_loop_tangent_calc(
+ em, calc_active_tangent,
+ tangent_names, tangent_names_len,
+ poly_normals, loop_normals,
+ vert_orco,
+ &dm->loopData, dm->numLoopData,
+ &dm->tangent_mask);
}
-/** \} */
-
static void emDM_recalcTessellation(DerivedMesh *UNUSED(dm))
{
@@ -816,39 +454,6 @@ static void emDM_drawMappedEdgesInterp(
}
}
-static void emDM_drawUVEdges(DerivedMesh *dm)
-{
- EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
- BMesh *bm = bmdm->em->bm;
- BMFace *efa;
- BMIter iter;
-
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
-
- if (UNLIKELY(cd_loop_uv_offset == -1)) {
- return;
- }
-
- glBegin(GL_LINES);
- BM_ITER_MESH (efa, &iter, bm, BM_FACES_OF_MESH) {
- BMLoop *l_iter, *l_first;
- const float *uv, *uv_prev;
-
- if (BM_elem_flag_test(efa, BM_ELEM_HIDDEN))
- continue;
-
- l_iter = l_first = BM_FACE_FIRST_LOOP(efa);
- uv_prev = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter->prev, cd_loop_uv_offset))->uv;
- do {
- uv = ((MLoopUV *)BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset))->uv;
- glVertex2fv(uv);
- glVertex2fv(uv_prev);
- uv_prev = uv;
- } while ((l_iter = l_iter->next) != l_first);
- }
- glEnd();
-}
-
static void emDM_foreachMappedLoop(
DerivedMesh *dm,
void (*func)(void *userData, int vertex_index, int face_index, const float co[3], const float no[3]),
@@ -1036,11 +641,11 @@ static void emDM_drawMappedFaces(
if (poly_prev != GL_ZERO) glEnd();
glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
}
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
}
else {
@@ -1057,23 +662,23 @@ static void emDM_drawMappedFaces(
if (!drawSmooth) {
glNormal3fv(polyNos[BM_elem_index_get(efa)]);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
}
else {
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]);
else glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]);
else glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]);
else glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
@@ -1138,11 +743,11 @@ static void emDM_drawMappedFaces(
if (poly_prev != GL_ZERO) glEnd();
glBegin((poly_prev = poly_type)); /* BMesh: will always be GL_TRIANGLES */
}
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
glVertex3fv(ltri[0]->v->co);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
glVertex3fv(ltri[1]->v->co);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
glVertex3fv(ltri[2]->v->co);
}
else {
@@ -1159,23 +764,23 @@ static void emDM_drawMappedFaces(
if (!drawSmooth) {
glNormal3fv(efa->no);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
glVertex3fv(ltri[0]->v->co);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
glVertex3fv(ltri[1]->v->co);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
glVertex3fv(ltri[2]->v->co);
}
else {
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[0]->r));
if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]);
else glNormal3fv(ltri[0]->v->no);
glVertex3fv(ltri[0]->v->co);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[1]->r));
if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]);
else glNormal3fv(ltri[1]->v->no);
glVertex3fv(ltri[1]->v->co);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r));
+ if (has_vcol_any) glColor3ubv((const GLubyte *)&(lcol[2]->r));
if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]);
else glNormal3fv(ltri[2]->v->no);
glVertex3fv(ltri[2]->v->co);
@@ -1197,20 +802,6 @@ static void emDM_drawMappedFaces(
}
}
-static void bmdm_get_tri_uv(BMLoop *ltri[3], MLoopUV *luv[3], const int cd_loop_uv_offset)
-{
- luv[0] = BM_ELEM_CD_GET_VOID_P(ltri[0], cd_loop_uv_offset);
- luv[1] = BM_ELEM_CD_GET_VOID_P(ltri[1], cd_loop_uv_offset);
- luv[2] = BM_ELEM_CD_GET_VOID_P(ltri[2], cd_loop_uv_offset);
-}
-
-static void bmdm_get_tri_col(BMLoop *ltri[3], MLoopCol *lcol[3], const int cd_loop_color_offset)
-{
- lcol[0] = BM_ELEM_CD_GET_VOID_P(ltri[0], cd_loop_color_offset);
- lcol[1] = BM_ELEM_CD_GET_VOID_P(ltri[1], cd_loop_color_offset);
- lcol[2] = BM_ELEM_CD_GET_VOID_P(ltri[2], cd_loop_color_offset);
-}
-
static void bmdm_get_tri_colpreview(BMLoop *ls[3], MLoopCol *lcol[3], unsigned char(*color_vert_array)[4])
{
lcol[0] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[0]->v)];
@@ -1218,204 +809,6 @@ static void bmdm_get_tri_colpreview(BMLoop *ls[3], MLoopCol *lcol[3], unsigned c
lcol[2] = (MLoopCol *)color_vert_array[BM_elem_index_get(ls[2]->v)];
}
-static void emDM_drawFacesTex_common(
- DerivedMesh *dm,
- DMSetDrawOptionsTex drawParams,
- DMSetDrawOptionsMappedTex drawParamsMapped,
- DMCompareDrawOptions compareDrawOptions,
- void *userData)
-{
- EditDerivedBMesh *bmdm = (EditDerivedBMesh *)dm;
- BMEditMesh *em = bmdm->em;
- BMesh *bm = em->bm;
- struct BMLoop *(*looptris)[3] = em->looptris;
- BMFace *efa;
- const float (*lnors)[3] = dm->getLoopDataArray(dm, CD_NORMAL);
- MLoopUV *luv[3], dummyluv = {{0}};
- MLoopCol *lcol[3] = {NULL} /* , dummylcol = {0} */;
- const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
- const int cd_loop_color_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPCOL);
- const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
- unsigned char(*color_vert_array)[4] = em->derivedVertColor;
- bool has_uv = (cd_loop_uv_offset != -1);
- bool has_vcol_preview = (color_vert_array != NULL);
- bool has_vcol = (cd_loop_color_offset != -1) && (has_vcol_preview == false);
- bool has_vcol_any = (has_vcol_preview || has_vcol);
- int i;
-
- (void) compareDrawOptions;
-
- luv[0] = luv[1] = luv[2] = &dummyluv;
-
- // dummylcol.r = dummylcol.g = dummylcol.b = dummylcol.a = 255; /* UNUSED */
-
- /* always use smooth shading even for flat faces, else vertex colors wont interpolate */
- BM_mesh_elem_index_ensure(bm, BM_FACE);
-
- /* call again below is ok */
- if (has_vcol_preview) {
- BM_mesh_elem_index_ensure(bm, BM_VERT);
- }
-
- if (bmdm->vertexCos) {
- /* add direct access */
- const float (*vertexCos)[3] = bmdm->vertexCos;
- const float (*vertexNos)[3];
- const float (*polyNos)[3];
-
- emDM_ensureVertNormals(bmdm);
- emDM_ensurePolyNormals(bmdm);
- vertexNos = bmdm->vertexNos;
- polyNos = bmdm->polyNos;
-
- BM_mesh_elem_index_ensure(bm, lnors ? BM_LOOP | BM_VERT : BM_VERT);
-
- for (i = 0; i < em->tottri; i++) {
- BMLoop **ltri = looptris[i];
- MTexPoly *tp = (cd_poly_tex_offset != -1) ? BM_ELEM_CD_GET_VOID_P(ltri[0]->f, cd_poly_tex_offset) : NULL;
- /*unsigned char *cp = NULL;*/ /*UNUSED*/
- int drawSmooth = lnors || BM_elem_flag_test(ltri[0]->f, BM_ELEM_SMOOTH);
- DMDrawOption draw_option;
-
- efa = ltri[0]->f;
-
- if (drawParams) {
- draw_option = drawParams(tp, has_vcol, efa->mat_nr);
- }
- else if (drawParamsMapped)
- draw_option = drawParamsMapped(userData, BM_elem_index_get(efa), efa->mat_nr);
- else
- draw_option = DM_DRAW_OPTION_NORMAL;
-
- if (draw_option != DM_DRAW_OPTION_SKIP) {
-
- if (has_uv) bmdm_get_tri_uv(ltri, luv, cd_loop_uv_offset);
- if (has_vcol) bmdm_get_tri_col(ltri, lcol, cd_loop_color_offset);
- else if (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array);
-
- glBegin(GL_TRIANGLES);
- if (!drawSmooth) {
- glNormal3fv(polyNos[BM_elem_index_get(efa)]);
-
- glTexCoord2fv(luv[0]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r));
- glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
-
- glTexCoord2fv(luv[1]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r));
- glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
-
- glTexCoord2fv(luv[2]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r));
- glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
- }
- else {
- glTexCoord2fv(luv[0]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r));
- if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]);
- else glNormal3fv(vertexNos[BM_elem_index_get(ltri[0]->v)]);
- glVertex3fv(vertexCos[BM_elem_index_get(ltri[0]->v)]);
-
- glTexCoord2fv(luv[1]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r));
- if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]);
- else glNormal3fv(vertexNos[BM_elem_index_get(ltri[1]->v)]);
- glVertex3fv(vertexCos[BM_elem_index_get(ltri[1]->v)]);
-
- glTexCoord2fv(luv[2]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r));
- if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]);
- else glNormal3fv(vertexNos[BM_elem_index_get(ltri[2]->v)]);
- glVertex3fv(vertexCos[BM_elem_index_get(ltri[2]->v)]);
- }
- glEnd();
- }
- }
- }
- else {
- BM_mesh_elem_index_ensure(bm, lnors ? BM_LOOP | BM_VERT : BM_VERT);
-
- for (i = 0; i < em->tottri; i++) {
- BMLoop **ltri = looptris[i];
- MTexPoly *tp = (cd_poly_tex_offset != -1) ? BM_ELEM_CD_GET_VOID_P(ltri[0]->f, cd_poly_tex_offset) : NULL;
- /*unsigned char *cp = NULL;*/ /*UNUSED*/
- int drawSmooth = lnors || BM_elem_flag_test(ltri[0]->f, BM_ELEM_SMOOTH);
- DMDrawOption draw_option;
-
- efa = ltri[0]->f;
-
- if (drawParams)
- draw_option = drawParams(tp, has_vcol, efa->mat_nr);
- else if (drawParamsMapped)
- draw_option = drawParamsMapped(userData, BM_elem_index_get(efa), efa->mat_nr);
- else
- draw_option = DM_DRAW_OPTION_NORMAL;
-
- if (draw_option != DM_DRAW_OPTION_SKIP) {
-
- if (has_uv) bmdm_get_tri_uv(ltri, luv, cd_loop_uv_offset);
- if (has_vcol) bmdm_get_tri_col(ltri, lcol, cd_loop_color_offset);
- else if (has_vcol_preview) bmdm_get_tri_colpreview(ltri, lcol, color_vert_array);
-
- glBegin(GL_TRIANGLES);
- if (!drawSmooth) {
- glNormal3fv(efa->no);
-
- glTexCoord2fv(luv[0]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r));
- glVertex3fv(ltri[0]->v->co);
-
- glTexCoord2fv(luv[1]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r));
- glVertex3fv(ltri[1]->v->co);
-
- glTexCoord2fv(luv[2]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r));
- glVertex3fv(ltri[2]->v->co);
- }
- else {
- glTexCoord2fv(luv[0]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[0]->r));
- if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[0])]);
- else glNormal3fv(ltri[0]->v->no);
- glVertex3fv(ltri[0]->v->co);
-
- glTexCoord2fv(luv[1]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[1]->r));
- if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[1])]);
- else glNormal3fv(ltri[1]->v->no);
- glVertex3fv(ltri[1]->v->co);
-
- glTexCoord2fv(luv[2]->uv);
- if (has_vcol_any) glColor4ubv((const GLubyte *)&(lcol[2]->r));
- if (lnors) glNormal3fv(lnors[BM_elem_index_get(ltri[2])]);
- else glNormal3fv(ltri[2]->v->no);
- glVertex3fv(ltri[2]->v->co);
- }
- glEnd();
- }
- }
- }
-}
-
-static void emDM_drawFacesTex(
- DerivedMesh *dm,
- DMSetDrawOptionsTex setDrawOptions,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag UNUSED(flag))
-{
- emDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData);
-}
-
-static void emDM_drawMappedFacesTex(
- DerivedMesh *dm,
- DMSetDrawOptionsMappedTex setDrawOptions,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag UNUSED(flag))
-{
- emDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData);
-}
-
/**
* \note
*
@@ -2061,14 +1454,8 @@ static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
if (type == CD_MTFACE || type == CD_MCOL) {
const char *bmdata;
char *data;
- bool has_type_source = false;
- if (type == CD_MTFACE) {
- has_type_source = CustomData_has_layer(&bm->pdata, CD_MTEXPOLY);
- }
- else {
- has_type_source = CustomData_has_layer(&bm->ldata, CD_MLOOPCOL);
- }
+ bool has_type_source = CustomData_has_layer(&bm->ldata, (type == CD_MTFACE) ? CD_MLOOPUV : CD_MLOOPCOL);
if (has_type_source) {
/* offset = bm->pdata.layers[index].offset; */ /* UNUSED */
@@ -2084,15 +1471,8 @@ static void *emDM_getTessFaceDataArray(DerivedMesh *dm, int type)
if (type == CD_MTFACE) {
const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
- const int cd_poly_tex_offset = CustomData_get_offset(&bm->pdata, CD_MTEXPOLY);
for (i = 0; i < bmdm->em->tottri; i++, data += size) {
- BMFace *efa = looptris[i][0]->f;
-
- // bmdata = CustomData_bmesh_get(&bm->pdata, efa->head.data, CD_MTEXPOLY);
- bmdata = BM_ELEM_CD_GET_VOID_P(efa, cd_poly_tex_offset);
-
- ME_MTEXFACE_CPY(((MTFace *)data), ((const MTexPoly *)bmdata));
for (j = 0; j < 3; j++) {
// bmdata = CustomData_bmesh_get(&bm->ldata, looptris[i][j]->head.data, CD_MLOOPUV);
bmdata = BM_ELEM_CD_GET_VOID_P(looptris[i][j], cd_loop_uv_offset);
@@ -2284,12 +1664,9 @@ DerivedMesh *getEditDerivedBMesh(
bmdm->dm.drawMappedEdges = emDM_drawMappedEdges;
bmdm->dm.drawMappedEdgesInterp = emDM_drawMappedEdgesInterp;
bmdm->dm.drawMappedFaces = emDM_drawMappedFaces;
- bmdm->dm.drawMappedFacesTex = emDM_drawMappedFacesTex;
bmdm->dm.drawMappedFacesGLSL = emDM_drawMappedFacesGLSL;
bmdm->dm.drawMappedFacesMat = emDM_drawMappedFacesMat;
- bmdm->dm.drawFacesTex = emDM_drawFacesTex;
bmdm->dm.drawFacesGLSL = emDM_drawFacesGLSL;
- bmdm->dm.drawUVEdges = emDM_drawUVEdges;
bmdm->dm.release = emDM_release;
@@ -2799,14 +2176,14 @@ static void cage_mapped_verts_callback(
}
}
-float (*BKE_editmesh_vertexCos_get(BMEditMesh *em, Scene *scene, int *r_numVerts))[3]
+float (*BKE_editmesh_vertexCos_get(const struct EvaluationContext *eval_ctx, BMEditMesh *em, Scene *scene, int *r_numVerts))[3]
{
DerivedMesh *cage, *final;
BLI_bitmap *visit_bitmap;
struct CageUserData data;
float (*cos_cage)[3];
- cage = editbmesh_get_derived_cage_and_final(scene, em->ob, em, CD_MASK_BAREMESH, &final);
+ cage = editbmesh_get_derived_cage_and_final(eval_ctx, scene, em->ob, em, CD_MASK_BAREMESH, &final);
cos_cage = MEM_callocN(sizeof(*cos_cage) * em->bm->totvert, "bmbvh cos_cage");
/* when initializing cage verts, we only want the first cage coordinate for each vertex,
diff --git a/source/blender/blenkernel/intern/editmesh.c b/source/blender/blenkernel/intern/editmesh.c
index fea3c24d322..c95da3b2569 100644
--- a/source/blender/blenkernel/intern/editmesh.c
+++ b/source/blender/blenkernel/intern/editmesh.c
@@ -165,26 +165,6 @@ void BKE_editmesh_tessface_calc(BMEditMesh *em)
#endif
}
-void BKE_editmesh_update_linked_customdata(BMEditMesh *em)
-{
- BMesh *bm = em->bm;
- int act;
-
- if (CustomData_has_layer(&bm->pdata, CD_MTEXPOLY)) {
- act = CustomData_get_active_layer(&bm->pdata, CD_MTEXPOLY);
- CustomData_set_layer_active(&bm->ldata, CD_MLOOPUV, act);
-
- act = CustomData_get_render_layer(&bm->pdata, CD_MTEXPOLY);
- CustomData_set_layer_render(&bm->ldata, CD_MLOOPUV, act);
-
- act = CustomData_get_clone_layer(&bm->pdata, CD_MTEXPOLY);
- CustomData_set_layer_clone(&bm->ldata, CD_MLOOPUV, act);
-
- act = CustomData_get_stencil_layer(&bm->pdata, CD_MTEXPOLY);
- CustomData_set_layer_stencil(&bm->ldata, CD_MLOOPUV, act);
- }
-}
-
void BKE_editmesh_free_derivedmesh(BMEditMesh *em)
{
if (em->derivedCage) {
diff --git a/source/blender/blenkernel/intern/editmesh_tangent.c b/source/blender/blenkernel/intern/editmesh_tangent.c
new file mode 100644
index 00000000000..f725a1793b4
--- /dev/null
+++ b/source/blender/blenkernel/intern/editmesh_tangent.c
@@ -0,0 +1,431 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/editmesh_tangent.c
+ * \ingroup bke
+ */
+
+#include "BLI_math.h"
+#include "BLI_task.h"
+
+#include "BKE_DerivedMesh.h"
+
+#include "BKE_mesh.h"
+#include "BKE_mesh_tangent.h" /* for utility functions */
+#include "BKE_editmesh.h"
+#include "BKE_editmesh_tangent.h"
+
+#include "MEM_guardedalloc.h"
+
+/* interface */
+#include "mikktspace.h"
+
+/** \name Tangent Space Calculation
+ * \{ */
+
+/* Necessary complexity to handle looptri's as quads for correct tangents */
+#define USE_LOOPTRI_DETECT_QUADS
+
+typedef struct {
+ const float (*precomputedFaceNormals)[3];
+ const float (*precomputedLoopNormals)[3];
+ const BMLoop *(*looptris)[3];
+ int cd_loop_uv_offset; /* texture coordinates */
+ const float (*orco)[3];
+ float (*tangent)[4]; /* destination */
+ int numTessFaces;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ /* map from 'fake' face index to looptri,
+ * quads will point to the first looptri of the quad */
+ const int *face_as_quad_map;
+ int num_face_as_quad_map;
+#endif
+
+} SGLSLEditMeshToTangent;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+/* seems weak but only used on quads */
+static const BMLoop *bm_loop_at_face_index(const BMFace *f, int vert_index)
+{
+ const BMLoop *l = BM_FACE_FIRST_LOOP(f);
+ while (vert_index--) {
+ l = l->next;
+ }
+ return l;
+}
+#endif
+
+static int emdm_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
+{
+ SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ return pMesh->num_face_as_quad_map;
+#else
+ return pMesh->numTessFaces;
+#endif
+}
+
+static int emdm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
+{
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
+ if (pMesh->face_as_quad_map) {
+ const BMLoop **lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
+ if (lt[0]->f->len == 4) {
+ return 4;
+ }
+ }
+ return 3;
+#else
+ UNUSED_VARS(pContext, face_num);
+ return 3;
+#endif
+}
+
+static void emdm_ts_GetPosition(
+ const SMikkTSpaceContext *pContext, float r_co[3],
+ const int face_num, const int vert_index)
+{
+ //assert(vert_index >= 0 && vert_index < 4);
+ SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
+ const BMLoop **lt;
+ const BMLoop *l;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ if (pMesh->face_as_quad_map) {
+ lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
+ if (lt[0]->f->len == 4) {
+ l = bm_loop_at_face_index(lt[0]->f, vert_index);
+ goto finally;
+ }
+ /* fall through to regular triangle */
+ }
+ else {
+ lt = pMesh->looptris[face_num];
+ }
+#else
+ lt = pMesh->looptris[face_num];
+#endif
+ l = lt[vert_index];
+
+ const float *co;
+
+finally:
+ co = l->v->co;
+ copy_v3_v3(r_co, co);
+}
+
+static void emdm_ts_GetTextureCoordinate(
+ const SMikkTSpaceContext *pContext, float r_uv[2],
+ const int face_num, const int vert_index)
+{
+ //assert(vert_index >= 0 && vert_index < 4);
+ SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
+ const BMLoop **lt;
+ const BMLoop *l;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ if (pMesh->face_as_quad_map) {
+ lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
+ if (lt[0]->f->len == 4) {
+ l = bm_loop_at_face_index(lt[0]->f, vert_index);
+ goto finally;
+ }
+ /* fall through to regular triangle */
+ }
+ else {
+ lt = pMesh->looptris[face_num];
+ }
+#else
+ lt = pMesh->looptris[face_num];
+#endif
+ l = lt[vert_index];
+
+finally:
+ if (pMesh->cd_loop_uv_offset != -1) {
+ const float *uv = BM_ELEM_CD_GET_VOID_P(l, pMesh->cd_loop_uv_offset);
+ copy_v2_v2(r_uv, uv);
+ }
+ else {
+ const float *orco = pMesh->orco[BM_elem_index_get(l->v)];
+ map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]);
+ }
+}
+
+static void emdm_ts_GetNormal(
+ const SMikkTSpaceContext *pContext, float r_no[3],
+ const int face_num, const int vert_index)
+{
+ //assert(vert_index >= 0 && vert_index < 4);
+ SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
+ const BMLoop **lt;
+ const BMLoop *l;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ if (pMesh->face_as_quad_map) {
+ lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
+ if (lt[0]->f->len == 4) {
+ l = bm_loop_at_face_index(lt[0]->f, vert_index);
+ goto finally;
+ }
+ /* fall through to regular triangle */
+ }
+ else {
+ lt = pMesh->looptris[face_num];
+ }
+#else
+ lt = pMesh->looptris[face_num];
+#endif
+ l = lt[vert_index];
+
+finally:
+ if (pMesh->precomputedLoopNormals) {
+ copy_v3_v3(r_no, pMesh->precomputedLoopNormals[BM_elem_index_get(l)]);
+ }
+ else if (BM_elem_flag_test(l->f, BM_ELEM_SMOOTH) == 0) { /* flat */
+ if (pMesh->precomputedFaceNormals) {
+ copy_v3_v3(r_no, pMesh->precomputedFaceNormals[BM_elem_index_get(l->f)]);
+ }
+ else {
+ copy_v3_v3(r_no, l->f->no);
+ }
+ }
+ else {
+ copy_v3_v3(r_no, l->v->no);
+ }
+}
+
+static void emdm_ts_SetTSpace(
+ const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign,
+ const int face_num, const int vert_index)
+{
+ //assert(vert_index >= 0 && vert_index < 4);
+ SGLSLEditMeshToTangent *pMesh = pContext->m_pUserData;
+ const BMLoop **lt;
+ const BMLoop *l;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ if (pMesh->face_as_quad_map) {
+ lt = pMesh->looptris[pMesh->face_as_quad_map[face_num]];
+ if (lt[0]->f->len == 4) {
+ l = bm_loop_at_face_index(lt[0]->f, vert_index);
+ goto finally;
+ }
+ /* fall through to regular triangle */
+ }
+ else {
+ lt = pMesh->looptris[face_num];
+ }
+#else
+ lt = pMesh->looptris[face_num];
+#endif
+ l = lt[vert_index];
+
+ float *pRes;
+
+finally:
+ pRes = pMesh->tangent[BM_elem_index_get(l)];
+ copy_v3_v3(pRes, fvTangent);
+ pRes[3] = fSign;
+}
+
+static void emDM_calc_loop_tangents_thread(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
+{
+ struct SGLSLEditMeshToTangent *mesh2tangent = taskdata;
+ /* new computation method */
+ {
+ SMikkTSpaceContext sContext = {NULL};
+ SMikkTSpaceInterface sInterface = {NULL};
+ sContext.m_pUserData = mesh2tangent;
+ sContext.m_pInterface = &sInterface;
+ sInterface.m_getNumFaces = emdm_ts_GetNumFaces;
+ sInterface.m_getNumVerticesOfFace = emdm_ts_GetNumVertsOfFace;
+ sInterface.m_getPosition = emdm_ts_GetPosition;
+ sInterface.m_getTexCoord = emdm_ts_GetTextureCoordinate;
+ sInterface.m_getNormal = emdm_ts_GetNormal;
+ sInterface.m_setTSpaceBasic = emdm_ts_SetTSpace;
+ /* 0 if failed */
+ genTangSpaceDefault(&sContext);
+ }
+}
+
+/**
+ * \see #BKE_mesh_calc_loop_tangent, same logic but used arrays instead of #BMesh data.
+ *
+ * \note This function is not so normal, its using `bm->ldata` as input, but output's to `dm->loopData`.
+ * This is done because #CD_TANGENT is cache data used only for drawing.
+ */
+void BKE_editmesh_loop_tangent_calc(
+ BMEditMesh *em, bool calc_active_tangent,
+ const char (*tangent_names)[MAX_NAME], int tangent_names_len,
+ const float (*poly_normals)[3],
+ const float (*loop_normals)[3],
+ const float (*vert_orco)[3],
+ /* result */
+ CustomData *loopdata_out,
+ const uint loopdata_out_len,
+ short *tangent_mask_curr_p)
+{
+ BMesh *bm = em->bm;
+
+ int act_uv_n = -1;
+ int ren_uv_n = -1;
+ bool calc_act = false;
+ bool calc_ren = false;
+ char act_uv_name[MAX_NAME];
+ char ren_uv_name[MAX_NAME];
+ short tangent_mask = 0;
+ short tangent_mask_curr = *tangent_mask_curr_p;
+
+ BKE_mesh_calc_loop_tangent_step_0(
+ &bm->ldata, calc_active_tangent, tangent_names, tangent_names_len,
+ &calc_act, &calc_ren, &act_uv_n, &ren_uv_n, act_uv_name, ren_uv_name, &tangent_mask);
+
+ if ((tangent_mask_curr | tangent_mask) != tangent_mask_curr) {
+ for (int i = 0; i < tangent_names_len; i++) {
+ if (tangent_names[i][0]) {
+ BKE_mesh_add_loop_tangent_named_layer_for_uv(
+ &bm->ldata, loopdata_out, (int)loopdata_out_len, tangent_names[i]);
+ }
+ }
+ if ((tangent_mask & DM_TANGENT_MASK_ORCO) && CustomData_get_named_layer_index(loopdata_out, CD_TANGENT, "") == -1)
+ CustomData_add_layer_named(loopdata_out, CD_TANGENT, CD_CALLOC, NULL, (int)loopdata_out_len, "");
+ if (calc_act && act_uv_name[0])
+ BKE_mesh_add_loop_tangent_named_layer_for_uv(&bm->ldata, loopdata_out, (int)loopdata_out_len, act_uv_name);
+ if (calc_ren && ren_uv_name[0])
+ BKE_mesh_add_loop_tangent_named_layer_for_uv(&bm->ldata, loopdata_out, (int)loopdata_out_len, ren_uv_name);
+ int totface = em->tottri;
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ int num_face_as_quad_map;
+ int *face_as_quad_map = NULL;
+
+ /* map faces to quads */
+ if (em->tottri != bm->totface) {
+ /* over alloc, since we dont know how many ngon or quads we have */
+
+ /* map fake face index to looptri */
+ face_as_quad_map = MEM_mallocN(sizeof(int) * totface, __func__);
+ int i, j;
+ for (i = 0, j = 0; j < totface; i++, j++) {
+ face_as_quad_map[i] = j;
+ /* step over all quads */
+ if (em->looptris[j][0]->f->len == 4) {
+ j++; /* skips the nest looptri */
+ }
+ }
+ num_face_as_quad_map = i;
+ }
+ else {
+ num_face_as_quad_map = totface;
+ }
+#endif
+ /* Calculation */
+ if (em->tottri != 0) {
+ TaskScheduler *scheduler = BLI_task_scheduler_get();
+ TaskPool *task_pool;
+ task_pool = BLI_task_pool_create(scheduler, NULL);
+
+ tangent_mask_curr = 0;
+ /* Calculate tangent layers */
+ SGLSLEditMeshToTangent data_array[MAX_MTFACE];
+ int index = 0;
+ int n = 0;
+ CustomData_update_typemap(loopdata_out);
+ const int tangent_layer_num = CustomData_number_of_layers(loopdata_out, CD_TANGENT);
+ for (n = 0; n < tangent_layer_num; n++) {
+ index = CustomData_get_layer_index_n(loopdata_out, CD_TANGENT, n);
+ BLI_assert(n < MAX_MTFACE);
+ SGLSLEditMeshToTangent *mesh2tangent = &data_array[n];
+ mesh2tangent->numTessFaces = em->tottri;
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ mesh2tangent->face_as_quad_map = face_as_quad_map;
+ mesh2tangent->num_face_as_quad_map = num_face_as_quad_map;
+#endif
+ mesh2tangent->precomputedFaceNormals = poly_normals; /* dm->getPolyDataArray(dm, CD_NORMAL) */
+ /* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled),
+ * have to check this is valid...
+ */
+ mesh2tangent->precomputedLoopNormals = loop_normals;
+ mesh2tangent->cd_loop_uv_offset = CustomData_get_n_offset(&bm->ldata, CD_MLOOPUV, n);
+
+ /* needed for indexing loop-tangents */
+ int htype_index = BM_LOOP;
+ if (mesh2tangent->cd_loop_uv_offset == -1) {
+ mesh2tangent->orco = vert_orco;
+ if (!mesh2tangent->orco)
+ continue;
+ /* needed for orco lookups */
+ htype_index |= BM_VERT;
+ tangent_mask_curr |= DM_TANGENT_MASK_ORCO;
+ }
+ else {
+ /* Fill the resulting tangent_mask */
+ int uv_ind = CustomData_get_named_layer_index(&bm->ldata, CD_MLOOPUV, loopdata_out->layers[index].name);
+ int uv_start = CustomData_get_layer_index(&bm->ldata, CD_MLOOPUV);
+ BLI_assert(uv_ind != -1 && uv_start != -1);
+ BLI_assert(uv_ind - uv_start < MAX_MTFACE);
+ tangent_mask_curr |= 1 << (uv_ind - uv_start);
+ }
+ if (mesh2tangent->precomputedFaceNormals) {
+ /* needed for face normal lookups */
+ htype_index |= BM_FACE;
+ }
+ BM_mesh_elem_index_ensure(bm, htype_index);
+
+ mesh2tangent->looptris = (const BMLoop *(*)[3])em->looptris;
+ mesh2tangent->tangent = loopdata_out->layers[index].data;
+
+ BLI_task_pool_push(task_pool, emDM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW);
+ }
+
+ BLI_assert(tangent_mask_curr == tangent_mask);
+ BLI_task_pool_work_and_wait(task_pool);
+ BLI_task_pool_free(task_pool);
+ }
+ else {
+ tangent_mask_curr = tangent_mask;
+ }
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ if (face_as_quad_map) {
+ MEM_freeN(face_as_quad_map);
+ }
+#undef USE_LOOPTRI_DETECT_QUADS
+#endif
+ }
+
+ *tangent_mask_curr_p = tangent_mask_curr;
+
+ int act_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, act_uv_n);
+ if (act_uv_index >= 0) {
+ int tan_index = CustomData_get_named_layer_index(loopdata_out, CD_TANGENT, bm->ldata.layers[act_uv_index].name);
+ CustomData_set_layer_active_index(loopdata_out, CD_TANGENT, tan_index);
+ } /* else tangent has been built from orco */
+
+ /* Update render layer index */
+ int ren_uv_index = CustomData_get_layer_index_n(&bm->ldata, CD_MLOOPUV, ren_uv_n);
+ if (ren_uv_index >= 0) {
+ int tan_index = CustomData_get_named_layer_index(loopdata_out, CD_TANGENT, bm->ldata.layers[ren_uv_index].name);
+ CustomData_set_layer_render_index(loopdata_out, CD_TANGENT, tan_index);
+ } /* else tangent has been built from orco */
+}
+
+/** \} */ \ No newline at end of file
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 38f5c00941c..16124fb4777 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -64,6 +64,8 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_effect.h"
#include "BKE_global.h"
+#include "BKE_group.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_modifier.h"
#include "BKE_object.h"
@@ -71,6 +73,7 @@
#include "BKE_scene.h"
#include "BKE_smoke.h"
+#include "DEG_depsgraph.h"
#include "RE_render_ext.h"
#include "RE_shader_ext.h"
@@ -145,9 +148,10 @@ void free_partdeflect(PartDeflect *pd)
MEM_freeN(pd);
}
-static EffectorCache *new_effector_cache(Scene *scene, Object *ob, ParticleSystem *psys, PartDeflect *pd)
+static EffectorCache *new_effector_cache(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, ParticleSystem *psys, PartDeflect *pd)
{
EffectorCache *eff = MEM_callocN(sizeof(EffectorCache), "EffectorCache");
+ eff->eval_ctx = eval_ctx;
eff->scene = scene;
eff->ob = ob;
eff->psys = psys;
@@ -155,7 +159,7 @@ static EffectorCache *new_effector_cache(Scene *scene, Object *ob, ParticleSyste
eff->frame = -1;
return eff;
}
-static void add_object_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, Object *ob_src, bool for_simulation)
+static void add_object_to_effectors(ListBase **effectors, const struct EvaluationContext *eval_ctx, Scene *scene, EffectorWeights *weights, Object *ob, Object *ob_src, bool for_simulation)
{
EffectorCache *eff = NULL;
@@ -173,14 +177,14 @@ static void add_object_to_effectors(ListBase **effectors, Scene *scene, Effector
if (*effectors == NULL)
*effectors = MEM_callocN(sizeof(ListBase), "effectors list");
- eff = new_effector_cache(scene, ob, NULL, ob->pd);
+ eff = new_effector_cache(eval_ctx, scene, ob, NULL, ob->pd);
/* make sure imat is up to date */
invert_m4_m4(ob->imat, ob->obmat);
BLI_addtail(*effectors, eff);
}
-static void add_particles_to_effectors(ListBase **effectors, Scene *scene, EffectorWeights *weights, Object *ob, ParticleSystem *psys, ParticleSystem *psys_src, bool for_simulation)
+static void add_particles_to_effectors(ListBase **effectors, const struct EvaluationContext *eval_ctx, Scene *scene, EffectorWeights *weights, Object *ob, ParticleSystem *psys, ParticleSystem *psys_src, bool for_simulation)
{
ParticleSettings *part= psys->part;
@@ -194,61 +198,59 @@ static void add_particles_to_effectors(ListBase **effectors, Scene *scene, Effec
if (*effectors == NULL)
*effectors = MEM_callocN(sizeof(ListBase), "effectors list");
- BLI_addtail(*effectors, new_effector_cache(scene, ob, psys, part->pd));
+ BLI_addtail(*effectors, new_effector_cache(eval_ctx, scene, ob, psys, part->pd));
}
if (part->pd2 && part->pd2->forcefield && (!for_simulation || weights->weight[part->pd2->forcefield] != 0.0f)) {
if (*effectors == NULL)
*effectors = MEM_callocN(sizeof(ListBase), "effectors list");
- BLI_addtail(*effectors, new_effector_cache(scene, ob, psys, part->pd2));
+ BLI_addtail(*effectors, new_effector_cache(eval_ctx, scene, ob, psys, part->pd2));
}
}
/* returns ListBase handle with objects taking part in the effecting */
-ListBase *pdInitEffectors(Scene *scene, Object *ob_src, ParticleSystem *psys_src,
- EffectorWeights *weights, bool for_simulation)
+ListBase *pdInitEffectors(
+ const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob_src, ParticleSystem *psys_src,
+ EffectorWeights *weights, bool for_simulation)
{
+ ViewLayer *view_layer;
Base *base;
- unsigned int layer= ob_src->lay;
ListBase *effectors = NULL;
-
+
if (weights->group) {
- GroupObject *go;
-
- for (go= weights->group->gobject.first; go; go= go->next) {
- if ( (go->ob->lay & layer) ) {
- if ( go->ob->pd && go->ob->pd->forcefield )
- add_object_to_effectors(&effectors, scene, weights, go->ob, ob_src, for_simulation);
+ view_layer = weights->group->view_layer;
+ }
+ else if (eval_ctx) {
+ view_layer = eval_ctx->view_layer;
+ }
+ else {
+ /* eval_ctx is NULL during deg build */
+ view_layer = BKE_view_layer_context_active_PLACEHOLDER(scene);
+ }
- if ( go->ob->particlesystem.first ) {
- ParticleSystem *psys= go->ob->particlesystem.first;
+ for (base = FIRSTBASE(view_layer); base; base = base->next) {
+ if ((base->flag & BASE_VISIBLED) == 0) {
+ continue;
+ }
- for ( ; psys; psys=psys->next )
- add_particles_to_effectors(&effectors, scene, weights, go->ob, psys, psys_src, for_simulation);
- }
- }
+ if (base->object->pd && base->object->pd->forcefield) {
+ add_object_to_effectors(&effectors, eval_ctx, scene, weights, base->object, ob_src, for_simulation);
}
- }
- else {
- for (base = scene->base.first; base; base= base->next) {
- if ( (base->lay & layer) ) {
- if ( base->object->pd && base->object->pd->forcefield )
- add_object_to_effectors(&effectors, scene, weights, base->object, ob_src, for_simulation);
- if ( base->object->particlesystem.first ) {
- ParticleSystem *psys= base->object->particlesystem.first;
+ if (base->object->particlesystem.first) {
+ ParticleSystem *psys= base->object->particlesystem.first;
- for ( ; psys; psys=psys->next )
- add_particles_to_effectors(&effectors, scene, weights, base->object, psys, psys_src, for_simulation);
- }
+ for (; psys; psys=psys->next) {
+ add_particles_to_effectors(&effectors, eval_ctx, scene, weights, base->object, psys, psys_src, for_simulation);
}
}
}
-
- if (for_simulation)
- pdPrecalculateEffectors(effectors);
-
+
+ if (for_simulation) {
+ pdPrecalculateEffectors(eval_ctx, effectors);
+ }
+
return effectors;
}
@@ -268,7 +270,7 @@ void pdEndEffectors(ListBase **effectors)
}
}
-static void precalculate_effector(EffectorCache *eff)
+static void precalculate_effector(const struct EvaluationContext *eval_ctx, EffectorCache *eff)
{
unsigned int cfra = (unsigned int)(eff->scene->r.cfra >= 0 ? eff->scene->r.cfra : -eff->scene->r.cfra);
if (!eff->pd->rng)
@@ -280,7 +282,7 @@ static void precalculate_effector(EffectorCache *eff)
Curve *cu= eff->ob->data;
if (cu->flag & CU_PATH) {
if (eff->ob->curve_cache == NULL || eff->ob->curve_cache->path==NULL || eff->ob->curve_cache->path->data==NULL)
- BKE_displist_make_curveTypes(eff->scene, eff->ob, 0);
+ BKE_displist_make_curveTypes(eval_ctx, eff->scene, eff->ob, 0);
if (eff->ob->curve_cache->path && eff->ob->curve_cache->path->data) {
where_on_path(eff->ob, 0.0, eff->guide_loc, eff->guide_dir, NULL, &eff->guide_radius, NULL);
@@ -301,19 +303,19 @@ static void precalculate_effector(EffectorCache *eff)
if (eff->ob) {
float old_vel[3];
- BKE_object_where_is_calc_time(eff->scene, eff->ob, cfra - 1.0f);
+ BKE_object_where_is_calc_time(eval_ctx, eff->scene, eff->ob, cfra - 1.0f);
copy_v3_v3(old_vel, eff->ob->obmat[3]);
- BKE_object_where_is_calc_time(eff->scene, eff->ob, cfra);
+ BKE_object_where_is_calc_time(eval_ctx, eff->scene, eff->ob, cfra);
sub_v3_v3v3(eff->velocity, eff->ob->obmat[3], old_vel);
}
}
-void pdPrecalculateEffectors(ListBase *effectors)
+void pdPrecalculateEffectors(const struct EvaluationContext *eval_ctx, ListBase *effectors)
{
if (effectors) {
EffectorCache *eff = effectors->first;
for (; eff; eff=eff->next)
- precalculate_effector(eff);
+ precalculate_effector(eval_ctx, eff);
}
}
@@ -612,6 +614,7 @@ int get_effector_data(EffectorCache *eff, EffectorData *efd, EffectedPoint *poin
}
else {
ParticleSimulationData sim= {NULL};
+ sim.eval_ctx = eff->eval_ctx;
sim.scene= eff->scene;
sim.ob= eff->ob;
sim.psys= eff->psys;
diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c
index 8e98a9f672d..12b9abc6d03 100644
--- a/source/blender/blenkernel/intern/fluidsim.c
+++ b/source/blender/blenkernel/intern/fluidsim.c
@@ -65,7 +65,7 @@
// file handling
//-------------------------------------------------------------------------------
-void initElbeemMesh(struct Scene *scene, struct Object *ob,
+void initElbeemMesh(const struct EvaluationContext *eval_ctx, struct Scene *scene, struct Object *ob,
int *numVertices, float **vertices,
int *numTriangles, int **triangles,
int useGlobalCoords, int modifierIndex)
@@ -78,7 +78,7 @@ void initElbeemMesh(struct Scene *scene, struct Object *ob,
float *verts;
int *tris;
- dm = mesh_create_derived_index_render(scene, ob, CD_MASK_BAREMESH, modifierIndex);
+ dm = mesh_create_derived_index_render(eval_ctx, scene, ob, CD_MASK_BAREMESH, modifierIndex);
mvert = dm->getVertArray(dm);
mloop = dm->getLoopArray(dm);
diff --git a/source/blender/blenkernel/intern/freestyle.c b/source/blender/blenkernel/intern/freestyle.c
index 686fe3bda93..b656d2cf7c0 100644
--- a/source/blender/blenkernel/intern/freestyle.c
+++ b/source/blender/blenkernel/intern/freestyle.c
@@ -61,17 +61,21 @@ void BKE_freestyle_config_init(FreestyleConfig *config)
BLI_listbase_clear(&config->linesets);
}
-void BKE_freestyle_config_free(FreestyleConfig *config)
+void BKE_freestyle_config_free(FreestyleConfig *config, const bool do_id_user)
{
FreestyleLineSet *lineset;
for (lineset = (FreestyleLineSet *)config->linesets.first; lineset; lineset = lineset->next) {
if (lineset->group) {
- id_us_min(&lineset->group->id);
+ if (do_id_user) {
+ id_us_min(&lineset->group->id);
+ }
lineset->group = NULL;
}
if (lineset->linestyle) {
- id_us_min(&lineset->linestyle->id);
+ if (do_id_user) {
+ id_us_min(&lineset->linestyle->id);
+ }
lineset->linestyle = NULL;
}
}
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index 6dc8cc5aff1..8295fafba56 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -45,34 +45,51 @@
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
-
-#include "BKE_depsgraph.h"
+#include "BKE_collection.h"
#include "BKE_global.h"
#include "BKE_group.h"
#include "BKE_icons.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_object.h"
-#include "BKE_scene.h" /* BKE_scene_base_find */
+#include "BKE_scene.h"
-static void free_group_object(GroupObject *go)
-{
- MEM_freeN(go);
-}
+#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
/** Free (or release) any data used by this group (does not free the group itself). */
void BKE_group_free(Group *group)
{
- /* don't free group itself */
- GroupObject *go;
-
/* No animdata here. */
+ BKE_previewimg_free(&group->preview);
- while ((go = BLI_pophead(&group->gobject))) {
- free_group_object(go);
+ if (group->view_layer != NULL) {
+ BKE_view_layer_free(group->view_layer);
+ group->view_layer = NULL;
}
- BKE_previewimg_free(&group->preview);
+ if (group->collection != NULL) {
+ BKE_collection_master_free(&group->id, false);
+ MEM_freeN(group->collection);
+ group->collection = NULL;
+ }
+}
+
+/**
+ * Run when adding new groups or during doversion.
+ */
+void BKE_group_init(Group *group)
+{
+ group->collection = MEM_callocN(sizeof(SceneCollection), __func__);
+ BLI_strncpy(group->collection->name, "Master Collection", sizeof(group->collection->name));
+ group->view_layer = BKE_view_layer_group_add(group);
+
+ /* Unlink the master collection. */
+ BKE_collection_unlink(group->view_layer, group->view_layer->layer_collections.first);
+
+ /* Create and link a new default collection. */
+ SceneCollection *defaut_collection = BKE_collection_add(&group->id, NULL, COLLECTION_TYPE_GROUP_INTERNAL, NULL);
+ BKE_collection_link(group->view_layer, defaut_collection);
}
Group *BKE_group_add(Main *bmain, const char *name)
@@ -85,7 +102,7 @@ Group *BKE_group_add(Main *bmain, const char *name)
group->layer = (1 << 20) - 1;
group->preview = NULL;
-
+ BKE_group_init(group);
return group;
}
@@ -99,7 +116,8 @@ Group *BKE_group_add(Main *bmain, const char *name)
*/
void BKE_group_copy_data(Main *UNUSED(bmain), Group *group_dst, const Group *group_src, const int flag)
{
- BLI_duplicatelist(&group_dst->gobject, &group_src->gobject);
+ /* We never handle usercount here for own data. */
+ const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
/* Do not copy group's preview (same behavior as for objects). */
if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO temp hack */
@@ -108,6 +126,19 @@ void BKE_group_copy_data(Main *UNUSED(bmain), Group *group_dst, const Group *gro
else {
group_dst->preview = NULL;
}
+
+ group_dst->collection = MEM_dupallocN(group_src->collection);
+ SceneCollection *master_collection_src = BKE_collection_master(&group_src->id);
+ SceneCollection *master_collection_dst = BKE_collection_master(&group_dst->id);
+
+ /* Recursively creates a new SceneCollection tree. */
+ BKE_collection_copy_data(master_collection_dst, master_collection_src,
+ flag_subdata);
+
+ group_dst->view_layer = MEM_dupallocN(group_src->view_layer);
+ BKE_view_layer_copy_data(group_dst->view_layer, group_src->view_layer,
+ master_collection_dst, master_collection_src,
+ flag_subdata);
}
Group *BKE_group_copy(Main *bmain, const Group *group)
@@ -125,38 +156,27 @@ void BKE_group_make_local(Main *bmain, Group *group, const bool lib_local)
/* external */
static bool group_object_add_internal(Group *group, Object *ob)
{
- GroupObject *go;
-
if (group == NULL || ob == NULL) {
return false;
}
-
- /* check if the object has been added already */
- if (BLI_findptr(&group->gobject, ob, offsetof(GroupObject, ob))) {
+
+ /* For now always add to master collection of the group. */
+ SceneCollection *scene_collection = GROUP_MASTER_COLLECTION(group);
+
+ /* If the object has been added already it returns false. */
+ if (BKE_collection_object_add(&group->id, scene_collection, ob) == false) {
return false;
}
-
- go = MEM_callocN(sizeof(GroupObject), "groupobject");
- BLI_addtail(&group->gobject, go);
-
- go->ob = ob;
- id_us_ensure_real(&go->ob->id);
-
+
+ id_us_ensure_real(&ob->id);
return true;
}
-bool BKE_group_object_add(Group *group, Object *object, Scene *scene, Base *base)
+bool BKE_group_object_add(Group *group, Object *object)
{
if (group_object_add_internal(group, object)) {
if ((object->flag & OB_FROMGROUP) == 0) {
-
- if (scene && base == NULL)
- base = BKE_scene_base_find(scene, object);
-
object->flag |= OB_FROMGROUP;
-
- if (base)
- base->flag |= OB_FROMGROUP;
}
return true;
}
@@ -166,24 +186,17 @@ bool BKE_group_object_add(Group *group, Object *object, Scene *scene, Base *base
}
/* also used for (ob == NULL) */
-static int group_object_unlink_internal(Group *group, Object *ob)
+static bool group_object_unlink_internal(Group *group, Object *ob)
{
- GroupObject *go, *gon;
- int removed = 0;
- if (group == NULL) return 0;
-
- go = group->gobject.first;
- while (go) {
- gon = go->next;
- if (go->ob == ob) {
- BLI_remlink(&group->gobject, go);
- free_group_object(go);
- removed = 1;
- /* should break here since an object being in a group twice cant happen? */
- }
- go = gon;
+ if (group == NULL) {
+ return false;
}
- return removed;
+
+ if (BKE_collections_object_remove(NULL, &group->id, ob, false)) {
+ return true;
+ }
+
+ return false;
}
static bool group_object_cyclic_check_internal(Object *object, Group *group)
@@ -200,12 +213,13 @@ static bool group_object_cyclic_check_internal(Object *object, Group *group)
if (dup_group == group)
return true;
else {
- GroupObject *gob;
- for (gob = dup_group->gobject.first; gob; gob = gob->next) {
- if (group_object_cyclic_check_internal(gob->ob, group)) {
+ FOREACH_GROUP_OBJECT(dup_group, group_object)
+ {
+ if (group_object_cyclic_check_internal(group_object, dup_group)) {
return true;
}
}
+ FOREACH_GROUP_OBJECT_END
}
/* un-flag the object, it's allowed to have the same group multiple times in parallel */
@@ -223,18 +237,12 @@ bool BKE_group_object_cyclic_check(Main *bmain, Object *object, Group *group)
return group_object_cyclic_check_internal(object, group);
}
-bool BKE_group_object_unlink(Group *group, Object *object, Scene *scene, Base *base)
+bool BKE_group_object_unlink(Group *group, Object *object)
{
if (group_object_unlink_internal(group, object)) {
/* object can be NULL */
if (object && BKE_group_object_find(NULL, object) == NULL) {
- if (scene && base == NULL)
- base = BKE_scene_base_find(scene, object);
-
object->flag &= ~OB_FROMGROUP;
-
- if (base)
- base->flag &= ~OB_FROMGROUP;
}
return true;
}
@@ -249,7 +257,7 @@ bool BKE_group_object_exists(Group *group, Object *ob)
return false;
}
else {
- return (BLI_findptr(&group->gobject, ob, offsetof(GroupObject, ob)) != NULL);
+ return (BLI_findptr(&group->view_layer->object_bases, ob, offsetof(Base, object)));
}
}
@@ -270,17 +278,13 @@ Group *BKE_group_object_find(Group *group, Object *ob)
bool BKE_group_is_animated(Group *group, Object *UNUSED(parent))
{
- GroupObject *go;
-
-#if 0 /* XXX OLD ANIMSYS, NLASTRIPS ARE NO LONGER USED */
- if (parent->nlastrips.first)
- return 1;
-#endif
-
- for (go = group->gobject.first; go; go = go->next)
- if (go->ob && go->ob->proxy)
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ if (object->proxy) {
return true;
-
+ }
+ }
+ FOREACH_GROUP_OBJECT_END
return false;
}
@@ -330,10 +334,8 @@ static void group_replaces_nla(Object *parent, Object *target, char mode)
* you can draw everything, leaves tags in objects to signal it needs further updating */
/* note: does not work for derivedmesh and render... it recreates all again in convertblender.c */
-void BKE_group_handle_recalc_and_update(EvaluationContext *eval_ctx, Scene *scene, Object *UNUSED(parent), Group *group)
+void BKE_group_handle_recalc_and_update(const struct EvaluationContext *eval_ctx, Scene *scene, Object *UNUSED(parent), Group *group)
{
- GroupObject *go;
-
#if 0 /* warning, isn't clearing the recalc flag on the object which causes it to run all the time,
* not just on frame change.
* This isn't working because the animation data is only re-evaluated on frame change so commenting for now
@@ -367,12 +369,45 @@ void BKE_group_handle_recalc_and_update(EvaluationContext *eval_ctx, Scene *scen
#endif
{
/* only do existing tags, as set by regular depsgraph */
- for (go = group->gobject.first; go; go = go->next) {
- if (go->ob) {
- if (go->ob->recalc) {
- BKE_object_handle_update(eval_ctx, scene, go->ob);
- }
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ if (object->id.recalc & ID_RECALC_ALL) {
+ BKE_object_handle_update(eval_ctx, scene, object);
}
}
+ FOREACH_GROUP_OBJECT_END
+ }
+}
+
+/* ******** Dependency graph evaluation ******** */
+
+static void group_eval_layer_collections(
+ const struct EvaluationContext *eval_ctx,
+ Group *group,
+ ListBase *layer_collections,
+ LayerCollection *parent_layer_collection)
+{
+ LINKLIST_FOREACH (LayerCollection *, layer_collection, layer_collections) {
+ /* Evaluate layer collection itself. */
+ BKE_layer_eval_layer_collection(eval_ctx,
+ layer_collection,
+ parent_layer_collection);
+ /* Evaluate nested collections. */
+ group_eval_layer_collections(eval_ctx,
+ group,
+ &layer_collection->layer_collections,
+ layer_collection);
}
}
+
+void BKE_group_eval_view_layers(const struct EvaluationContext *eval_ctx,
+ Group *group)
+{
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, group->id.name, group);
+ BKE_layer_eval_layer_collection_pre(eval_ctx, &group->id, group->view_layer);
+ group_eval_layer_collections(eval_ctx,
+ group,
+ &group->view_layer->layer_collections,
+ NULL);
+ BKE_layer_eval_layer_collection_post(eval_ctx, group->view_layer);
+}
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c
index a98a1b13402..a407fd0bae8 100644
--- a/source/blender/blenkernel/intern/icons.c
+++ b/source/blender/blenkernel/intern/icons.c
@@ -42,6 +42,7 @@
#include "DNA_material_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
#include "DNA_texture_types.h"
#include "DNA_world_types.h"
#include "DNA_brush_types.h"
@@ -252,6 +253,7 @@ PreviewImage **BKE_previewimg_id_get_p(const ID *id)
ID_PRV_CASE(ID_OB, Object);
ID_PRV_CASE(ID_GR, Group);
ID_PRV_CASE(ID_SCE, Scene);
+ ID_PRV_CASE(ID_SCR, bScreen);
#undef ID_PRV_CASE
default:
break;
diff --git a/source/blender/blenkernel/intern/idcode.c b/source/blender/blenkernel/intern/idcode.c
index 70d037d85f3..487635f06ad 100644
--- a/source/blender/blenkernel/intern/idcode.c
+++ b/source/blender/blenkernel/intern/idcode.c
@@ -81,8 +81,9 @@ static IDType idtypes[] = {
{ ID_PA, "ParticleSettings", "particles", BLT_I18NCONTEXT_ID_PARTICLESETTINGS, IDTYPE_FLAGS_ISLINKABLE },
{ ID_PAL, "Palettes", "palettes", BLT_I18NCONTEXT_ID_PALETTE, IDTYPE_FLAGS_ISLINKABLE },
{ ID_PC, "PaintCurve", "paint_curves", BLT_I18NCONTEXT_ID_PAINTCURVE, IDTYPE_FLAGS_ISLINKABLE },
+ { ID_LP, "LightProbe", "light_probes", BLT_I18NCONTEXT_ID_LIGHTPROBE, IDTYPE_FLAGS_ISLINKABLE },
{ ID_SCE, "Scene", "scenes", BLT_I18NCONTEXT_ID_SCENE, IDTYPE_FLAGS_ISLINKABLE },
- { ID_SCR, "Screen", "screens", BLT_I18NCONTEXT_ID_SCREEN, 0 },
+ { ID_SCR, "Screen", "screens", BLT_I18NCONTEXT_ID_SCREEN, IDTYPE_FLAGS_ISLINKABLE },
{ ID_SEQ, "Sequence", "sequences", BLT_I18NCONTEXT_ID_SEQUENCE, 0 }, /* not actually ID data */
{ ID_SPK, "Speaker", "speakers", BLT_I18NCONTEXT_ID_SPEAKER, IDTYPE_FLAGS_ISLINKABLE },
{ ID_SO, "Sound", "sounds", BLT_I18NCONTEXT_ID_SOUND, IDTYPE_FLAGS_ISLINKABLE },
@@ -91,6 +92,7 @@ static IDType idtypes[] = {
{ ID_VF, "VFont", "fonts", BLT_I18NCONTEXT_ID_VFONT, IDTYPE_FLAGS_ISLINKABLE },
{ ID_WO, "World", "worlds", BLT_I18NCONTEXT_ID_WORLD, IDTYPE_FLAGS_ISLINKABLE },
{ ID_WM, "WindowManager", "window_managers", BLT_I18NCONTEXT_ID_WINDOWMANAGER, 0 },
+ { ID_WS, "WorkSpace", "workspaces", BLT_I18NCONTEXT_ID_WORKSPACE, IDTYPE_FLAGS_ISLINKABLE },
/** Keep last, not an ID exactly, only include for completeness */
{ ID_ID, "ID", "ids", BLT_I18NCONTEXT_ID_ID, 0 }, /* plural is fake */
@@ -203,6 +205,7 @@ int BKE_idcode_to_idfilter(const short idcode)
CASE_IDFILTER(PA);
CASE_IDFILTER(PAL);
CASE_IDFILTER(PC);
+ CASE_IDFILTER(LP);
CASE_IDFILTER(SCE);
CASE_IDFILTER(SPK);
CASE_IDFILTER(SO);
@@ -210,6 +213,7 @@ int BKE_idcode_to_idfilter(const short idcode)
CASE_IDFILTER(TXT);
CASE_IDFILTER(VF);
CASE_IDFILTER(WO);
+ CASE_IDFILTER(WS);
default:
return 0;
}
@@ -247,6 +251,7 @@ short BKE_idcode_from_idfilter(const int idfilter)
CASE_IDFILTER(PA);
CASE_IDFILTER(PAL);
CASE_IDFILTER(PC);
+ CASE_IDFILTER(LP);
CASE_IDFILTER(SCE);
CASE_IDFILTER(SPK);
CASE_IDFILTER(SO);
@@ -294,6 +299,7 @@ int BKE_idcode_to_index(const short idcode)
CASE_IDINDEX(PA);
CASE_IDINDEX(PAL);
CASE_IDINDEX(PC);
+ CASE_IDINDEX(LP);
CASE_IDINDEX(SCE);
CASE_IDINDEX(SCR);
CASE_IDINDEX(SPK);
@@ -303,6 +309,7 @@ int BKE_idcode_to_index(const short idcode)
CASE_IDINDEX(VF);
CASE_IDINDEX(WM);
CASE_IDINDEX(WO);
+ CASE_IDINDEX(WS);
}
BLI_assert(0);
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index 45b41fa01ed..b00a62a1a87 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.
*
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index e3e403251e1..dbb596b1cd6 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -81,6 +81,7 @@
#include "BKE_scene.h"
#include "BKE_node.h"
#include "BKE_sequencer.h" /* seq_foreground_frame_get() */
+#include "BKE_workspace.h"
#include "BLF_api.h"
@@ -2609,19 +2610,19 @@ void BKE_image_walk_all_users(const Main *mainp, void *customdata,
}
}
+ for (Camera *cam = mainp->camera.first; cam; cam = cam->id.next) {
+ for (CameraBGImage *bgpic = cam->bg_images.first; bgpic; bgpic = bgpic->next) {
+ callback(bgpic->ima, &bgpic->iuser, customdata);
+ }
+ }
+
/* image window, compo node users */
for (wm = mainp->wm.first; wm; wm = wm->id.next) { /* only 1 wm */
for (win = wm->windows.first; win; win = win->next) {
- ScrArea *sa;
- for (sa = win->screen->areabase.first; sa; sa = sa->next) {
- if (sa->spacetype == SPACE_VIEW3D) {
- View3D *v3d = sa->spacedata.first;
- BGpic *bgpic;
- for (bgpic = v3d->bgpicbase.first; bgpic; bgpic = bgpic->next) {
- callback(bgpic->ima, &bgpic->iuser, customdata);
- }
- }
- else if (sa->spacetype == SPACE_IMAGE) {
+ const bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
+
+ for (ScrArea *sa = screen->areabase.first; sa; sa = sa->next) {
+ if (sa->spacetype == SPACE_IMAGE) {
SpaceImage *sima = sa->spacedata.first;
callback(sima->image, &sima->iuser, customdata);
}
diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c
index 3a4c920d8fb..931fc09d235 100644
--- a/source/blender/blenkernel/intern/lamp.c
+++ b/source/blender/blenkernel/intern/lamp.c
@@ -69,6 +69,7 @@ void BKE_lamp_init(Lamp *la)
la->bufsize = 512;
la->clipsta = 0.5f;
la->clipend = 40.0f;
+ la->bleedexp = 2.5f;
la->samp = 3;
la->bias = 1.0f;
la->soft = 3.0f;
@@ -101,6 +102,14 @@ void BKE_lamp_init(Lamp *la)
la->sky_colorspace = BLI_XYZ_CIE;
la->sky_exposure = 1.0f;
la->shadow_frustum_size = 10.0f;
+ la->cascade_max_dist = 1000.0f;
+ la->cascade_count = 4;
+ la->cascade_exponent = 0.8f;
+ la->cascade_fade = 0.1f;
+ la->contact_dist = 1.0f;
+ la->contact_bias = 0.03f;
+ la->contact_spread = 0.2f;
+ la->contact_thickness = 0.5f;
curvemapping_initialize(la->curfalloff);
}
@@ -215,41 +224,3 @@ void BKE_lamp_free(Lamp *la)
BKE_icon_id_delete(&la->id);
la->id.icon_id = 0;
}
-
-/* Calculate all drivers for lamps, see material_drivers_update for why this is a bad hack */
-
-static void lamp_node_drivers_update(Scene *scene, bNodeTree *ntree, float ctime)
-{
- bNode *node;
-
- /* nodetree itself */
- if (ntree->adt && ntree->adt->drivers.first)
- BKE_animsys_evaluate_animdata(scene, &ntree->id, ntree->adt, ctime, ADT_RECALC_DRIVERS);
-
- /* nodes */
- for (node = ntree->nodes.first; node; node = node->next)
- if (node->id && node->type == NODE_GROUP)
- lamp_node_drivers_update(scene, (bNodeTree *)node->id, ctime);
-}
-
-void lamp_drivers_update(Scene *scene, Lamp *la, float ctime)
-{
- /* Prevent infinite recursion by checking (and tagging the lamp) as having been visited already
- * (see BKE_scene_update_tagged()). This assumes la->id.tag & LIB_TAG_DOIT isn't set by anything else
- * in the meantime... [#32017] */
- if (la->id.tag & LIB_TAG_DOIT)
- return;
-
- la->id.tag |= LIB_TAG_DOIT;
-
- /* lamp itself */
- if (la->adt && la->adt->drivers.first)
- BKE_animsys_evaluate_animdata(scene, &la->id, la->adt, ctime, ADT_RECALC_DRIVERS);
-
- /* nodes */
- if (la->nodetree)
- lamp_node_drivers_update(scene, la->nodetree, ctime);
-
- la->id.tag &= ~LIB_TAG_DOIT;
-}
-
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index ea4c3f380ff..d92d0d9edbf 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -53,7 +53,6 @@
#include "BKE_anim.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_displist.h"
#include "BKE_global.h"
#include "BKE_key.h"
@@ -67,11 +66,6 @@
#include "BKE_deform.h"
-/* Workaround for cyclic dependency with curves.
- * In such case curve_cache might not be ready yet,
- */
-#define CYCLIC_DEPENDENCY_WORKAROUND
-
int BKE_lattice_index_from_uvw(Lattice *lt,
const int u, const int v, const int w)
{
@@ -314,6 +308,8 @@ void BKE_lattice_free(Lattice *lt)
{
BKE_animdata_free(&lt->id, false);
+ BKE_lattice_batch_cache_free(lt);
+
MEM_SAFE_FREE(lt->def);
if (lt->dvert) {
BKE_defvert_array_free(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
@@ -602,7 +598,7 @@ static bool where_on_path_deform(Object *ob, float ctime, float vec[4], float di
/* co: local coord, result local too */
/* returns quaternion for rotation, using cd->no_rot_axis */
/* axis is using another define!!! */
-static bool calc_curve_deform(Scene *scene, Object *par, float co[3],
+static bool calc_curve_deform(Object *par, float co[3],
const short axis, CurveDeform *cd, float r_quat[4])
{
Curve *cu = par->data;
@@ -610,12 +606,10 @@ static bool calc_curve_deform(Scene *scene, Object *par, float co[3],
short index;
const bool is_neg_axis = (axis > 2);
- /* to be sure, mostly after file load, also cyclic dependencies */
-#ifdef CYCLIC_DEPENDENCY_WORKAROUND
if (par->curve_cache == NULL) {
- BKE_displist_make_curveTypes(scene, par, false);
+ /* Happens with a cyclic dependencies. */
+ return false;
}
-#endif
if (par->curve_cache->path == NULL) {
return false; /* happens on append, cyclic dependencies and empty curves */
@@ -706,7 +700,7 @@ static bool calc_curve_deform(Scene *scene, Object *par, float co[3],
}
void curve_deform_verts(
- Scene *scene, Object *cuOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3],
+ Object *cuOb, Object *target, DerivedMesh *dm, float (*vertexCos)[3],
int numVerts, const char *vgroup, short defaxis)
{
Curve *cu;
@@ -765,7 +759,7 @@ void curve_deform_verts(
if (weight > 0.0f) {
mul_m4_v3(cd.curvespace, vertexCos[a]);
copy_v3_v3(vec, vertexCos[a]);
- calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL);
+ calc_curve_deform(cuOb, vec, defaxis, &cd, NULL);
interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight);
mul_m4_v3(cd.objectspace, vertexCos[a]);
}
@@ -788,7 +782,7 @@ void curve_deform_verts(
if (weight > 0.0f) {
/* already in 'cd.curvespace', prev for loop */
copy_v3_v3(vec, vertexCos[a]);
- calc_curve_deform(scene, cuOb, vec, defaxis, &cd, NULL);
+ calc_curve_deform(cuOb, vec, defaxis, &cd, NULL);
interp_v3_v3v3(vertexCos[a], vertexCos[a], vec, weight);
mul_m4_v3(cd.objectspace, vertexCos[a]);
}
@@ -799,7 +793,7 @@ void curve_deform_verts(
if (cu->flag & CU_DEFORM_BOUNDS_OFF) {
for (a = 0; a < numVerts; a++) {
mul_m4_v3(cd.curvespace, vertexCos[a]);
- calc_curve_deform(scene, cuOb, vertexCos[a], defaxis, &cd, NULL);
+ calc_curve_deform(cuOb, vertexCos[a], defaxis, &cd, NULL);
mul_m4_v3(cd.objectspace, vertexCos[a]);
}
}
@@ -814,7 +808,7 @@ void curve_deform_verts(
for (a = 0; a < numVerts; a++) {
/* already in 'cd.curvespace', prev for loop */
- calc_curve_deform(scene, cuOb, vertexCos[a], defaxis, &cd, NULL);
+ calc_curve_deform(cuOb, vertexCos[a], defaxis, &cd, NULL);
mul_m4_v3(cd.objectspace, vertexCos[a]);
}
}
@@ -824,7 +818,7 @@ void curve_deform_verts(
/* input vec and orco = local coord in armature space */
/* orco is original not-animated or deformed reference point */
/* result written in vec and mat */
-void curve_deform_vector(Scene *scene, Object *cuOb, Object *target,
+void curve_deform_vector(Object *cuOb, Object *target,
float orco[3], float vec[3], float mat[3][3], int no_rot_axis)
{
CurveDeform cd;
@@ -843,7 +837,7 @@ void curve_deform_vector(Scene *scene, Object *cuOb, Object *target,
mul_m4_v3(cd.curvespace, vec);
- if (calc_curve_deform(scene, cuOb, vec, target->trackflag, &cd, quat)) {
+ if (calc_curve_deform(cuOb, vec, target->trackflag, &cd, quat)) {
float qmat[3][3];
quat_to_mat3(qmat, quat);
@@ -1033,7 +1027,7 @@ void BKE_lattice_vertexcos_apply(struct Object *ob, float (*vertexCos)[3])
}
}
-void BKE_lattice_modifiers_calc(Scene *scene, Object *ob)
+void BKE_lattice_modifiers_calc(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
Lattice *lt = ob->data;
VirtualModifierData virtualModifierData;
@@ -1060,7 +1054,7 @@ void BKE_lattice_modifiers_calc(Scene *scene, Object *ob)
if (mti->type != eModifierTypeType_OnlyDeform) continue;
if (!vertexCos) vertexCos = BKE_lattice_vertexcos_get(ob, &numVerts);
- mti->deformVerts(md, ob, NULL, vertexCos, numVerts, 0);
+ mti->deformVerts(md, eval_ctx, ob, NULL, vertexCos, numVerts, 0);
}
/* always displist to make this work like derivedmesh */
@@ -1234,8 +1228,24 @@ void BKE_lattice_translate(Lattice *lt, float offset[3], bool do_keys)
/* **** Depsgraph evaluation **** */
-void BKE_lattice_eval_geometry(EvaluationContext *UNUSED(eval_ctx),
+void BKE_lattice_eval_geometry(const struct EvaluationContext *UNUSED(eval_ctx),
Lattice *UNUSED(latt))
{
}
+/* Draw Engine */
+void (*BKE_lattice_batch_cache_dirty_cb)(Lattice *lt, int mode) = NULL;
+void (*BKE_lattice_batch_cache_free_cb)(Lattice *lt) = NULL;
+
+void BKE_lattice_batch_cache_dirty(Lattice *lt, int mode)
+{
+ if (lt->batch_cache) {
+ BKE_lattice_batch_cache_dirty_cb(lt, mode);
+ }
+}
+void BKE_lattice_batch_cache_free(Lattice *lt)
+{
+ if (lt->batch_cache) {
+ BKE_lattice_batch_cache_free_cb(lt);
+ }
+}
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
new file mode 100644
index 00000000000..c63cefbcd8c
--- /dev/null
+++ b/source/blender/blenkernel/intern/layer.c
@@ -0,0 +1,2195 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributor(s): Dalai Felinto
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/layer.c
+ * \ingroup bke
+ */
+
+#include <string.h>
+
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_string_utf8.h"
+#include "BLI_string_utils.h"
+#include "BLT_translation.h"
+
+#include "BKE_collection.h"
+#include "BKE_freestyle.h"
+#include "BKE_global.h"
+#include "BKE_group.h"
+#include "BKE_idprop.h"
+#include "BKE_layer.h"
+#include "BKE_main.h"
+#include "BKE_node.h"
+#include "BKE_workspace.h"
+
+#include "DEG_depsgraph.h"
+
+#include "DNA_group_types.h"
+#include "DNA_ID.h"
+#include "DNA_layer_types.h"
+#include "DNA_object_types.h"
+#include "DNA_node_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_windowmanager_types.h"
+#include "DNA_workspace_types.h"
+
+#include "DRW_engine.h"
+
+#include "MEM_guardedalloc.h"
+
+#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
+
+/* prototype */
+struct EngineSettingsCB_Type;
+static void layer_collection_free(ViewLayer *view_layer, LayerCollection *lc);
+static void layer_collection_objects_populate(ViewLayer *view_layer, LayerCollection *lc, ListBase *objects);
+static LayerCollection *layer_collection_add(ViewLayer *view_layer, LayerCollection *parent, SceneCollection *sc);
+static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc);
+static IDProperty *collection_engine_settings_create(struct EngineSettingsCB_Type *ces_type, const bool populate);
+static IDProperty *collection_engine_get(IDProperty *root, const int type, const char *engine_name);
+static void collection_engine_settings_init(IDProperty *root, const bool populate);
+static void layer_engine_settings_init(IDProperty *root, const bool populate);
+static void object_bases_iterator_next(BLI_Iterator *iter, const int flag);
+
+/* RenderLayer */
+
+/**
+ * Returns the ViewLayer to be used for rendering
+ * Most of the time BKE_view_layer_from_workspace_get should be used instead
+ */
+ViewLayer *BKE_view_layer_from_scene_get(const Scene *scene)
+{
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
+ BLI_assert(view_layer);
+ return view_layer;
+}
+
+/**
+ * Returns the ViewLayer to be used for drawing, outliner, and other context related areas.
+ */
+ViewLayer *BKE_view_layer_from_workspace_get(const struct Scene *scene, const struct WorkSpace *workspace)
+{
+ if (BKE_workspace_use_scene_settings_get(workspace)) {
+ return BKE_view_layer_from_scene_get(scene);
+ }
+ else {
+ return BKE_workspace_view_layer_get(workspace, scene);
+ }
+}
+
+/**
+ * This is a placeholder to know which areas of the code need to be addressed for the Workspace changes.
+ * Never use this, you should either use BKE_view_layer_workspace_active or get ViewLayer explicitly.
+ */
+ViewLayer *BKE_view_layer_context_active_PLACEHOLDER(const Scene *scene)
+{
+ return BKE_view_layer_from_scene_get(scene);
+}
+
+static ViewLayer *view_layer_add(const char *name, SceneCollection *master_scene_collection)
+{
+ if (!name) {
+ name = DATA_("View Layer");
+ }
+
+ IDPropertyTemplate val = {0};
+ ViewLayer *view_layer = MEM_callocN(sizeof(ViewLayer), "View Layer");
+ view_layer->flag = VIEW_LAYER_RENDER | VIEW_LAYER_FREESTYLE;
+
+ view_layer->properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ layer_engine_settings_init(view_layer->properties, false);
+ BLI_strncpy_utf8(view_layer->name, name, sizeof(view_layer->name));
+
+ /* Link the master collection by default. */
+ layer_collection_add(view_layer, NULL, master_scene_collection);
+
+ /* Pure rendering pipeline settings. */
+ view_layer->layflag = 0x7FFF; /* solid ztra halo edge strand */
+ view_layer->passflag = SCE_PASS_COMBINED | SCE_PASS_Z;
+ view_layer->pass_alpha_threshold = 0.5f;
+ BKE_freestyle_config_init(&view_layer->freestyle_config);
+
+ return view_layer;
+}
+
+/**
+ * Add a new view layer
+ * by default, a view layer has the master collection
+ */
+ViewLayer *BKE_view_layer_add(Scene *scene, const char *name)
+{
+ SceneCollection *sc = BKE_collection_master(&scene->id);
+ ViewLayer *view_layer = view_layer_add(name, sc);
+
+ BLI_addtail(&scene->view_layers, view_layer);
+
+ /* unique name */
+ BLI_uniquename(
+ &scene->view_layers, view_layer, DATA_("ViewLayer"), '.',
+ offsetof(ViewLayer, name), sizeof(view_layer->name));
+
+ return view_layer;
+}
+
+/**
+ * Add a ViewLayer for a Group
+ * It should be added only once
+ */
+ViewLayer *BKE_view_layer_group_add(Group *group)
+{
+ BLI_assert(group->view_layer == NULL);
+ SceneCollection *sc = BKE_collection_master(&group->id);
+ ViewLayer *view_layer = view_layer_add(group->id.name + 2, sc);
+ return view_layer;
+}
+
+void BKE_view_layer_free(ViewLayer *view_layer)
+{
+ BKE_view_layer_free_ex(view_layer, true);
+}
+
+/**
+ * Free (or release) any data used by this ViewLayer.
+ */
+void BKE_view_layer_free_ex(ViewLayer *view_layer, const bool do_id_user)
+{
+ view_layer->basact = NULL;
+
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->collection_properties) {
+ IDP_FreeProperty(base->collection_properties);
+ MEM_freeN(base->collection_properties);
+ }
+ }
+ BLI_freelistN(&view_layer->object_bases);
+
+ for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) {
+ layer_collection_free(NULL, lc);
+ }
+ BLI_freelistN(&view_layer->layer_collections);
+
+ if (view_layer->properties) {
+ IDP_FreeProperty(view_layer->properties);
+ MEM_freeN(view_layer->properties);
+ }
+
+ if (view_layer->properties_evaluated) {
+ IDP_FreeProperty(view_layer->properties_evaluated);
+ MEM_freeN(view_layer->properties_evaluated);
+ }
+
+ for (ViewLayerEngineData *sled = view_layer->drawdata.first; sled; sled = sled->next) {
+ if (sled->storage) {
+ if (sled->free) {
+ sled->free(sled->storage);
+ }
+ MEM_freeN(sled->storage);
+ }
+ }
+ BLI_freelistN(&view_layer->drawdata);
+
+ MEM_SAFE_FREE(view_layer->stats);
+
+ BKE_freestyle_config_free(&view_layer->freestyle_config, do_id_user);
+
+ if (view_layer->id_properties) {
+ IDP_FreeProperty(view_layer->id_properties);
+ MEM_freeN(view_layer->id_properties);
+ }
+
+ MEM_freeN(view_layer);
+}
+
+/**
+ * Tag all the selected objects of a renderlayer
+ */
+void BKE_view_layer_selected_objects_tag(ViewLayer *view_layer, const int tag)
+{
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_SELECTED) != 0) {
+ base->object->flag |= tag;
+ }
+ else {
+ base->object->flag &= ~tag;
+ }
+ }
+}
+
+/**
+ * Return the first ViewLayer for a given id
+ */
+ViewLayer *BKE_view_layer_first_from_id(const ID *owner_id)
+{
+ switch (GS(owner_id->name)) {
+ case ID_SCE:
+ return ((Scene *)owner_id)->view_layers.first;
+ case ID_GR:
+ return ((Group *)owner_id)->view_layer;
+ default:
+ BLI_assert(!"ID doesn't support view layers");
+ return NULL;
+ }
+}
+
+static bool find_scene_collection_in_scene_collections(ListBase *lb, const LayerCollection *lc)
+{
+ for (LayerCollection *lcn = lb->first; lcn; lcn = lcn->next) {
+ if (lcn == lc) {
+ return true;
+ }
+ if (find_scene_collection_in_scene_collections(&lcn->layer_collections, lc)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Fallback for when a Scene has no camera to use
+ *
+ * \param view_layer: in general you want to use the same ViewLayer that is used
+ * for depsgraph. If rendering you pass the scene active layer, when viewing in the viewport
+ * you want to get ViewLayer from context.
+ */
+Object *BKE_view_layer_camera_find(ViewLayer *view_layer)
+{
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if (base->object->type == OB_CAMERA) {
+ return base->object;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Find the ViewLayer a LayerCollection belongs to
+ */
+ViewLayer *BKE_view_layer_find_from_collection(const ID *owner_id, LayerCollection *lc)
+{
+ switch (GS(owner_id->name)) {
+ case ID_GR:
+ return ((Group *)owner_id)->view_layer;
+ case ID_SCE:
+ {
+ Scene *scene = (Scene *)owner_id;
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ if (find_scene_collection_in_scene_collections(&view_layer->layer_collections, lc)) {
+ return view_layer;
+ }
+ }
+ return NULL;
+ }
+ default:
+ BLI_assert(!"ID doesn't support scene layers");
+ return NULL;
+ }
+}
+
+/* Base */
+
+Base *BKE_view_layer_base_find(ViewLayer *view_layer, Object *ob)
+{
+ return BLI_findptr(&view_layer->object_bases, ob, offsetof(Base, object));
+}
+
+void BKE_view_layer_base_deselect_all(ViewLayer *view_layer)
+{
+ Base *base;
+
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ base->flag &= ~BASE_SELECTED;
+ }
+}
+
+void BKE_view_layer_base_select(struct ViewLayer *view_layer, Base *selbase)
+{
+ view_layer->basact = selbase;
+ if ((selbase->flag & BASE_SELECTABLED) != 0) {
+ selbase->flag |= BASE_SELECTED;
+ }
+}
+
+/****************************************************************************/
+/* Copying functions for datablocks that use ViewLayer/SceneCollection */
+
+/* Find the equivalent SceneCollection in the new tree */
+static SceneCollection *scene_collection_from_new_tree(
+ SceneCollection *sc_reference, SceneCollection *sc_dst, SceneCollection *sc_src)
+{
+ if (sc_src == sc_reference) {
+ return sc_dst;
+ }
+
+ for (SceneCollection *nsc_src = sc_src->scene_collections.first, *nsc_dst = sc_dst->scene_collections.first;
+ nsc_src;
+ nsc_src = nsc_src->next, nsc_dst = nsc_dst->next)
+ {
+ SceneCollection *found = scene_collection_from_new_tree(sc_reference, nsc_dst, nsc_src);
+ if (found != NULL) {
+ return found;
+ }
+ }
+ return NULL;
+}
+
+static void layer_collections_sync_flags(ListBase *layer_collections_dst, const ListBase *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_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);
+
+ layer_collection_dst = layer_collection_dst->next;
+ layer_collection_src = layer_collection_src->next;
+ }
+}
+
+/* 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;
+ }
+ }
+}
+
+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);
+ }
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+/**
+ * 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 - prevent SceneCollection->objects and
+ * SceneCollection->filter_objects to add the same object. */
+
+ 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);
+ layer_collection_objects_populate(view_layer, lc, &sc->filter_objects);
+
+ for (SceneCollection *nsc = sc->scene_collections.first; nsc; nsc = nsc->next) {
+ layer_collection_add(view_layer, lc, nsc);
+ }
+}
+
+static LayerCollection *layer_collection_add(ViewLayer *view_layer, LayerCollection *parent, SceneCollection *sc)
+{
+ IDPropertyTemplate val = {0};
+ LayerCollection *lc = MEM_callocN(sizeof(LayerCollection), "Collection Base");
+
+ lc->scene_collection = sc;
+ lc->flag = COLLECTION_SELECTABLE | COLLECTION_VIEWPORT | COLLECTION_RENDER;
+
+ lc->properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ collection_engine_settings_init(lc->properties, false);
+
+ if (parent != NULL) {
+ BLI_addtail(&parent->layer_collections, lc);
+ }
+ else {
+ BLI_addtail(&view_layer->layer_collections, lc);
+ }
+
+ layer_collection_populate(view_layer, lc, sc);
+
+ return lc;
+}
+
+/* ---------------------------------------------------------------------- */
+
+/**
+ * See if render layer has the scene collection linked directly, or indirectly (nested)
+ */
+bool BKE_view_layer_has_collection(ViewLayer *view_layer, const SceneCollection *sc)
+{
+ for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) {
+ if (find_layer_collection_by_scene_collection(lc, sc) != NULL) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * See if the object is in any of the scene layers of the scene
+ */
+bool BKE_scene_has_object(Scene *scene, Object *ob)
+{
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ Base *base = BKE_view_layer_base_find(view_layer, ob);
+ if (base) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+/* ---------------------------------------------------------------------- */
+/* Syncing */
+
+static LayerCollection *find_layer_collection_by_scene_collection(LayerCollection *lc, const SceneCollection *sc)
+{
+ if (lc->scene_collection == sc) {
+ return lc;
+ }
+
+ for (LayerCollection *nlc = lc->layer_collections.first; nlc; nlc = nlc->next) {
+ LayerCollection *found = find_layer_collection_by_scene_collection(nlc, sc);
+ if (found) {
+ return found;
+ }
+ }
+ return NULL;
+}
+
+/**
+ * Add a new LayerCollection for all the ViewLayers that have sc_parent
+ */
+void BKE_layer_sync_new_scene_collection(ID *owner_id, const SceneCollection *sc_parent, SceneCollection *sc)
+{
+ for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
+ for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) {
+ LayerCollection *lc_parent = find_layer_collection_by_scene_collection(lc, sc_parent);
+ if (lc_parent) {
+ layer_collection_add(view_layer, lc_parent, sc);
+ }
+ }
+ }
+}
+
+/**
+ * Add a corresponding ObjectBase to all the equivalent LayerCollection
+ */
+void BKE_layer_sync_object_link(const ID *owner_id, SceneCollection *sc, Object *ob)
+{
+ for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
+ for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) {
+ LayerCollection *found = find_layer_collection_by_scene_collection(lc, sc);
+ if (found) {
+ layer_collection_object_add(view_layer, found, ob);
+ }
+ }
+ }
+}
+
+/**
+ * Remove the equivalent object base to all layers that have this collection
+ * also remove all reference to ob in the filter_objects
+ */
+void BKE_layer_sync_object_unlink(const ID *owner_id, SceneCollection *sc, Object *ob)
+{
+ for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
+ for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) {
+ LayerCollection *found = find_layer_collection_by_scene_collection(lc, sc);
+ if (found) {
+ layer_collection_object_remove(view_layer, found, ob);
+ }
+ }
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+/* Override */
+
+/**
+ * Add a new datablock override
+ */
+void BKE_override_view_layer_datablock_add(ViewLayer *view_layer, int id_type, const char *data_path, const ID *owner_id)
+{
+ UNUSED_VARS(view_layer, id_type, data_path, owner_id);
+ TODO_LAYER_OVERRIDE;
+}
+
+/**
+ * Add a new int override
+ */
+void BKE_override_view_layer_int_add(ViewLayer *view_layer, int id_type, const char *data_path, const int value)
+{
+ UNUSED_VARS(view_layer, id_type, data_path, value);
+ TODO_LAYER_OVERRIDE;
+}
+
+/**
+ * Add a new boolean override
+ */
+void BKE_override_layer_collection_boolean_add(struct LayerCollection *layer_collection, int id_type, const char *data_path, const bool value)
+{
+ UNUSED_VARS(layer_collection, id_type, data_path, value);
+ TODO_LAYER_OVERRIDE;
+}
+
+/* ---------------------------------------------------------------------- */
+/* Engine Settings */
+
+ListBase R_layer_collection_engines_settings_callbacks = {NULL, NULL};
+ListBase R_view_layer_engines_settings_callbacks = {NULL, NULL};
+
+typedef struct EngineSettingsCB_Type {
+ struct EngineSettingsCB_Type *next, *prev;
+
+ char name[MAX_NAME]; /* engine name */
+
+ EngineSettingsCB callback;
+
+} EngineSettingsCB_Type;
+
+static void create_engine_settings_scene(IDProperty *root, EngineSettingsCB_Type *es_type)
+{
+ if (collection_engine_get(root, COLLECTION_MODE_NONE, es_type->name)) {
+ return;
+ }
+
+ IDProperty *props = collection_engine_settings_create(es_type, true);
+ IDP_AddToGroup(root, props);
+}
+
+static void create_layer_collection_engine_settings_scene(Scene *scene, EngineSettingsCB_Type *es_type)
+{
+ create_engine_settings_scene(scene->collection_properties, es_type);
+}
+
+static void create_view_layer_engine_settings_scene(Scene *scene, EngineSettingsCB_Type *es_type)
+{
+ create_engine_settings_scene(scene->layer_properties, es_type);
+}
+
+static void create_layer_collection_engine_settings_collection(LayerCollection *lc, EngineSettingsCB_Type *es_type)
+{
+ if (BKE_layer_collection_engine_collection_get(lc, COLLECTION_MODE_NONE, es_type->name)) {
+ return;
+ }
+
+ IDProperty *props = collection_engine_settings_create(es_type, false);
+ IDP_AddToGroup(lc->properties, props);
+
+ for (LayerCollection *lcn = lc->layer_collections.first; lcn; lcn = lcn->next) {
+ create_layer_collection_engine_settings_collection(lcn, es_type);
+ }
+}
+
+static void create_layer_collection_engines_settings_scene(Scene *scene, EngineSettingsCB_Type *es_type)
+{
+ /* Populate the scene with the new settings. */
+ create_layer_collection_engine_settings_scene(scene, es_type);
+
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) {
+ create_layer_collection_engine_settings_collection(lc, es_type);
+ }
+ }
+}
+
+static void create_view_layer_engines_settings_scene(Scene *scene, EngineSettingsCB_Type *es_type)
+{
+ /* Populate the scene with the new settings. */
+ create_view_layer_engine_settings_scene(scene, es_type);
+}
+
+static void create_view_layer_engines_settings_layer(ViewLayer *view_layer, EngineSettingsCB_Type *es_type)
+{
+ if (BKE_view_layer_engine_layer_get(view_layer, COLLECTION_MODE_NONE, es_type->name)) {
+ return;
+ }
+
+ IDProperty *props = collection_engine_settings_create(es_type, false);
+ IDP_AddToGroup(view_layer->properties, props);
+}
+
+static EngineSettingsCB_Type *engine_settings_callback_register(const char *engine_name, EngineSettingsCB func, ListBase *lb)
+{
+ EngineSettingsCB_Type *es_type;
+
+ /* Cleanup in case it existed. */
+ es_type = BLI_findstring(lb, engine_name, offsetof(EngineSettingsCB_Type, name));
+
+ if (es_type) {
+ BLI_remlink(lb, es_type);
+ MEM_freeN(es_type);
+ }
+
+ es_type = MEM_callocN(sizeof(EngineSettingsCB_Type), __func__);
+ BLI_strncpy_utf8(es_type->name, engine_name, sizeof(es_type->name));
+ es_type->callback = func;
+ BLI_addtail(lb, es_type);
+
+ return es_type;
+}
+
+void BKE_layer_collection_engine_settings_callback_register(
+ Main *bmain, const char *engine_name, EngineSettingsCB func)
+{
+ EngineSettingsCB_Type *es_type =
+ engine_settings_callback_register(engine_name, func, &R_layer_collection_engines_settings_callbacks);
+
+ if (bmain) {
+ /* Populate all of the collections of the scene with those settings. */
+ for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+ create_layer_collection_engines_settings_scene(scene, es_type);
+ }
+ }
+}
+
+void BKE_view_layer_engine_settings_callback_register(
+ Main *bmain, const char *engine_name, EngineSettingsCB func)
+{
+ EngineSettingsCB_Type *es_type =
+ engine_settings_callback_register(engine_name, func, &R_view_layer_engines_settings_callbacks);
+
+ if (bmain) {
+ /* Populate all of the collections of the scene with those settings. */
+ for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+ create_view_layer_engines_settings_scene(scene, es_type);
+
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ create_view_layer_engines_settings_layer(view_layer, es_type);
+ }
+ }
+ }
+}
+
+void BKE_layer_collection_engine_settings_callback_free(void)
+{
+ BLI_freelistN(&R_layer_collection_engines_settings_callbacks);
+}
+
+void BKE_view_layer_engine_settings_callback_free(void)
+{
+ BLI_freelistN(&R_view_layer_engines_settings_callbacks);
+}
+
+/**
+ * Create a root IDProperty for this engine
+ *
+ * \param populate whether we want to pre-fill the collection with the default properties
+ */
+static IDProperty *collection_engine_settings_create(EngineSettingsCB_Type *es_type, const bool populate)
+{
+ IDProperty *props;
+ IDPropertyTemplate val = {0};
+
+ props = IDP_New(IDP_GROUP, &val, es_type->name);
+ props->subtype = IDP_GROUP_SUB_ENGINE_RENDER;
+
+ /* properties */
+ if (populate) {
+ es_type->callback(NULL, props);
+ }
+
+ return props;
+}
+
+static void layer_collection_create_mode_settings_object(IDProperty *root, const bool populate)
+{
+ IDProperty *props;
+ IDPropertyTemplate val = {0};
+
+ props = IDP_New(IDP_GROUP, &val, "ObjectMode");
+ props->subtype = IDP_GROUP_SUB_MODE_OBJECT;
+
+ /* properties */
+ if (populate) {
+ OBJECT_collection_settings_create(props);
+ }
+
+ IDP_AddToGroup(root, props);
+}
+
+static void layer_collection_create_mode_settings_edit(IDProperty *root, const bool populate)
+{
+ IDProperty *props;
+ IDPropertyTemplate val = {0};
+
+ props = IDP_New(IDP_GROUP, &val, "EditMode");
+ props->subtype = IDP_GROUP_SUB_MODE_EDIT;
+
+ /* properties */
+ if (populate) {
+ EDIT_MESH_collection_settings_create(props);
+ }
+
+ IDP_AddToGroup(root, props);
+}
+
+static void layer_collection_create_mode_settings_paint_weight(IDProperty *root, const bool populate)
+{
+ IDProperty *props;
+ IDPropertyTemplate val = {0};
+
+ props = IDP_New(IDP_GROUP, &val, "WeightPaintMode");
+ props->subtype = IDP_GROUP_SUB_MODE_PAINT_WEIGHT;
+
+ /* properties */
+ if (populate) {
+ PAINT_WEIGHT_collection_settings_create(props);
+ }
+
+ IDP_AddToGroup(root, props);
+}
+
+static void layer_collection_create_mode_settings_paint_vertex(IDProperty *root, const bool populate)
+{
+ IDProperty *props;
+ IDPropertyTemplate val = {0};
+
+ props = IDP_New(IDP_GROUP, &val, "VertexPaintMode");
+ props->subtype = IDP_GROUP_SUB_MODE_PAINT_VERTEX;
+
+ /* properties */
+ if (populate) {
+ PAINT_VERTEX_collection_settings_create(props);
+ }
+
+ IDP_AddToGroup(root, props);
+}
+
+static void layer_collection_create_render_settings(IDProperty *root, const bool populate)
+{
+ EngineSettingsCB_Type *es_type;
+ for (es_type = R_layer_collection_engines_settings_callbacks.first; es_type; es_type = es_type->next) {
+ IDProperty *props = collection_engine_settings_create(es_type, populate);
+ IDP_AddToGroup(root, props);
+ }
+}
+
+static void view_layer_create_render_settings(IDProperty *root, const bool populate)
+{
+ EngineSettingsCB_Type *es_type;
+ for (es_type = R_view_layer_engines_settings_callbacks.first; es_type; es_type = es_type->next) {
+ IDProperty *props = collection_engine_settings_create(es_type, populate);
+ IDP_AddToGroup(root, props);
+ }
+}
+
+static void collection_create_mode_settings(IDProperty *root, const bool populate)
+{
+ /* XXX TODO: put all those engines in the R_engines_settings_callbacks
+ * and have IDP_AddToGroup outside the callbacks */
+ layer_collection_create_mode_settings_object(root, populate);
+ layer_collection_create_mode_settings_edit(root, populate);
+ layer_collection_create_mode_settings_paint_weight(root, populate);
+ layer_collection_create_mode_settings_paint_vertex(root, populate);
+}
+
+static void layer_create_mode_settings(IDProperty *root, const bool populate)
+{
+ TODO_LAYER; /* XXX like collection_create_mode_settings */
+ UNUSED_VARS(root, populate);
+}
+
+static int idproperty_group_subtype(const int mode_type)
+{
+ int idgroup_type;
+
+ switch (mode_type) {
+ case COLLECTION_MODE_OBJECT:
+ idgroup_type = IDP_GROUP_SUB_MODE_OBJECT;
+ break;
+ case COLLECTION_MODE_EDIT:
+ idgroup_type = IDP_GROUP_SUB_MODE_EDIT;
+ break;
+ case COLLECTION_MODE_PAINT_WEIGHT:
+ idgroup_type = IDP_GROUP_SUB_MODE_PAINT_WEIGHT;
+ break;
+ case COLLECTION_MODE_PAINT_VERTEX:
+ idgroup_type = IDP_GROUP_SUB_MODE_PAINT_VERTEX;
+ break;
+ default:
+ case COLLECTION_MODE_NONE:
+ return IDP_GROUP_SUB_ENGINE_RENDER;
+ break;
+ }
+
+ return idgroup_type;
+}
+
+/**
+ * Return collection enginne settings for either Object s of LayerCollection s
+ */
+static IDProperty *collection_engine_get(
+ IDProperty *root, const int type, const char *engine_name)
+{
+ const int subtype = idproperty_group_subtype(type);
+
+ if (subtype == IDP_GROUP_SUB_ENGINE_RENDER) {
+ return IDP_GetPropertyFromGroup(root, engine_name);
+ }
+ else {
+ IDProperty *prop;
+ for (prop = root->data.group.first; prop; prop = prop->next) {
+ if (prop->subtype == subtype) {
+ return prop;
+ }
+ }
+ }
+
+ BLI_assert(false);
+ return NULL;
+}
+
+/**
+ * Return collection engine settings from Object for specified engine of mode
+ */
+IDProperty *BKE_layer_collection_engine_evaluated_get(Object *ob, const int type, const char *engine_name)
+{
+ return collection_engine_get(ob->base_collection_properties, type, engine_name);
+}
+/**
+ * Return layer collection engine settings for specified engine
+ */
+IDProperty *BKE_layer_collection_engine_collection_get(LayerCollection *lc, const int type, const char *engine_name)
+{
+ return collection_engine_get(lc->properties, type, engine_name);
+}
+
+/**
+ * Return layer collection engine settings for specified engine in the scene
+ */
+IDProperty *BKE_layer_collection_engine_scene_get(Scene *scene, const int type, const char *engine_name)
+{
+ return collection_engine_get(scene->collection_properties, type, engine_name);
+}
+
+/**
+ * Return scene layer engine settings for specified engine in the scene
+ */
+IDProperty *BKE_view_layer_engine_scene_get(Scene *scene, const int type, const char *engine_name)
+{
+ return collection_engine_get(scene->layer_properties, type, engine_name);
+}
+
+/**
+ * Return scene layer engine settings for specified engine
+ */
+IDProperty *BKE_view_layer_engine_layer_get(ViewLayer *view_layer, const int type, const char *engine_name)
+{
+ return collection_engine_get(view_layer->properties, type, engine_name);
+}
+
+/**
+ * Return scene layer evaluated engine settings for specified engine
+ */
+IDProperty *BKE_view_layer_engine_evaluated_get(ViewLayer *view_layer, const int type, const char *engine_name)
+{
+ return collection_engine_get(view_layer->properties_evaluated, type, engine_name);
+}
+
+/* ---------------------------------------------------------------------- */
+/* Engine Settings Properties */
+
+void BKE_collection_engine_property_add_float(IDProperty *props, const char *name, float value)
+{
+ IDPropertyTemplate val = {0};
+ val.f = value;
+ IDP_AddToGroup(props, IDP_New(IDP_FLOAT, &val, name));
+}
+
+void BKE_collection_engine_property_add_float_array(
+ IDProperty *props, const char *name, const float *values, const int array_length)
+{
+ IDPropertyTemplate val = {0};
+ val.array.len = array_length;
+ val.array.type = IDP_FLOAT;
+
+ IDProperty *idprop = IDP_New(IDP_ARRAY, &val, name);
+ memcpy(IDP_Array(idprop), values, sizeof(float) * idprop->len);
+ IDP_AddToGroup(props, idprop);
+}
+
+void BKE_collection_engine_property_add_int(IDProperty *props, const char *name, int value)
+{
+ IDPropertyTemplate val = {0};
+ val.i = value;
+ IDP_AddToGroup(props, IDP_New(IDP_INT, &val, name));
+}
+
+void BKE_collection_engine_property_add_bool(IDProperty *props, const char *name, bool value)
+{
+ IDPropertyTemplate val = {0};
+ val.i = value;
+ IDP_AddToGroup(props, IDP_New(IDP_INT, &val, name));
+}
+
+int BKE_collection_engine_property_value_get_int(IDProperty *props, const char *name)
+{
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, name);
+ return idprop ? IDP_Int(idprop) : 0;
+}
+
+float BKE_collection_engine_property_value_get_float(IDProperty *props, const char *name)
+{
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, name);
+ return idprop ? IDP_Float(idprop) : 0.0f;
+}
+
+const float *BKE_collection_engine_property_value_get_float_array(IDProperty *props, const char *name)
+{
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, name);
+ return idprop ? IDP_Array(idprop) : NULL;
+}
+
+bool BKE_collection_engine_property_value_get_bool(IDProperty *props, const char *name)
+{
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, name);
+ return idprop ? IDP_Int(idprop) : 0;
+}
+
+void BKE_collection_engine_property_value_set_int(IDProperty *props, const char *name, int value)
+{
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, name);
+ IDP_Int(idprop) = value;
+}
+
+void BKE_collection_engine_property_value_set_float(IDProperty *props, const char *name, float value)
+{
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, name);
+ IDP_Float(idprop) = value;
+}
+
+void BKE_collection_engine_property_value_set_float_array(IDProperty *props, const char *name, const float *values)
+{
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, name);
+ memcpy(IDP_Array(idprop), values, sizeof(float) * idprop->len);
+}
+
+void BKE_collection_engine_property_value_set_bool(IDProperty *props, const char *name, bool value)
+{
+ IDProperty *idprop = IDP_GetPropertyFromGroup(props, name);
+ IDP_Int(idprop) = value;
+}
+
+/* Engine Settings recalculate */
+
+/* get all the default settings defined in scene and merge them here */
+static void collection_engine_settings_init(IDProperty *root, const bool populate)
+{
+ /* render engines */
+ layer_collection_create_render_settings(root, populate);
+
+ /* mode engines */
+ collection_create_mode_settings(root, populate);
+}
+
+/* get all the default settings defined in scene and merge them here */
+static void layer_engine_settings_init(IDProperty *root, const bool populate)
+{
+ /* render engines */
+ view_layer_create_render_settings(root, populate);
+
+ /* mode engines */
+ layer_create_mode_settings(root, populate);
+}
+
+/**
+ * Initialize the layer collection render setings
+ * It's used mainly for scenes
+ */
+void BKE_layer_collection_engine_settings_create(IDProperty *root)
+{
+ collection_engine_settings_init(root, true);
+}
+
+/**
+ * Initialize the render setings
+ * It's used mainly for scenes
+ */
+void BKE_view_layer_engine_settings_create(IDProperty *root)
+{
+ layer_engine_settings_init(root, true);
+}
+
+/**
+ * Reference of IDProperty group scene collection settings
+ * Used when reading blendfiles, to see if there is any missing settings.
+ */
+static struct {
+ struct {
+ IDProperty *collection_properties;
+ IDProperty *render_settings;
+ } scene;
+ IDProperty *view_layer;
+ IDProperty *layer_collection;
+} root_reference = {
+ .scene = {NULL, NULL},
+ .view_layer = NULL,
+ .layer_collection = NULL,
+};
+
+/**
+ * Free the reference scene collection settings IDProperty group.
+ */
+static void engine_settings_validate_init(void)
+{
+ IDPropertyTemplate val = {0};
+
+ /* LayerCollection engine settings. */
+ if (root_reference.scene.collection_properties == NULL) {
+ root_reference.scene.collection_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ collection_engine_settings_init(root_reference.scene.collection_properties, true);
+ }
+
+ if (root_reference.layer_collection == NULL) {
+ root_reference.layer_collection = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ collection_engine_settings_init(root_reference.layer_collection, false);
+ }
+
+ /* Render engine setting. */
+ if (root_reference.scene.render_settings == NULL) {
+ root_reference.scene.render_settings = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ layer_engine_settings_init(root_reference.scene.render_settings, true);
+ }
+
+ if (root_reference.view_layer == NULL) {
+ root_reference.view_layer = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ layer_engine_settings_init(root_reference.view_layer, false);
+ }
+}
+
+/**
+ * Free the reference scene collection settings IDProperty group.
+ */
+static void layer_collection_engine_settings_validate_free(void)
+{
+ IDProperty *idprops[] = {
+ root_reference.scene.render_settings,
+ root_reference.scene.collection_properties,
+ root_reference.view_layer,
+ root_reference.layer_collection,
+ NULL,
+ };
+
+ IDProperty **idprop = &idprops[0];
+ while (*idprop) {
+ if (*idprop) {
+ IDP_FreeProperty(*idprop);
+ MEM_freeN(*idprop);
+ *idprop = NULL;
+ idprop++;
+ }
+ }
+}
+
+/**
+ * Make sure Scene has all required collection settings.
+ */
+void BKE_layer_collection_engine_settings_validate_scene(Scene *scene)
+{
+ if (root_reference.scene.collection_properties == NULL) {
+ engine_settings_validate_init();
+ }
+
+ if (scene->collection_properties == NULL) {
+ IDPropertyTemplate val = {0};
+ scene->collection_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ BKE_layer_collection_engine_settings_create(scene->collection_properties);
+ }
+ else {
+ IDP_MergeGroup(scene->collection_properties, root_reference.scene.collection_properties, false);
+ }
+}
+
+/**
+ * Maker sure LayerCollection has all required collection settings.
+ */
+void BKE_layer_collection_engine_settings_validate_collection(LayerCollection *lc)
+{
+ if (root_reference.layer_collection == NULL) {
+ engine_settings_validate_init();
+ }
+
+ BLI_assert(lc->properties != NULL);
+ IDP_MergeGroup(lc->properties, root_reference.layer_collection, false);
+}
+
+/**
+ * Make sure Scene has all required collection settings.
+ */
+void BKE_view_layer_engine_settings_validate_scene(Scene *scene)
+{
+ if (root_reference.scene.render_settings == NULL) {
+ engine_settings_validate_init();
+ }
+
+ if (scene->layer_properties == NULL) {
+ IDPropertyTemplate val = {0};
+ scene->layer_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ BKE_view_layer_engine_settings_create(scene->layer_properties);
+ }
+ else {
+ IDP_MergeGroup(scene->layer_properties, root_reference.scene.render_settings, false);
+ }
+}
+
+/**
+ * Make sure Scene has all required collection settings.
+ */
+void BKE_view_layer_engine_settings_validate_layer(ViewLayer *view_layer)
+{
+ if (root_reference.view_layer == NULL) {
+ engine_settings_validate_init();
+ }
+
+ IDP_MergeGroup(view_layer->properties, root_reference.view_layer, false);
+}
+
+/* ---------------------------------------------------------------------- */
+/* Iterators */
+
+static void object_bases_iterator_begin(BLI_Iterator *iter, void *data_in, const int flag)
+{
+ ViewLayer *view_layer = data_in;
+ Base *base = view_layer->object_bases.first;
+
+ /* when there are no objects */
+ if (base == NULL) {
+ iter->valid = false;
+ return;
+ }
+
+ iter->data = base;
+
+ if ((base->flag & flag) == 0) {
+ object_bases_iterator_next(iter, flag);
+ }
+ else {
+ iter->current = base;
+ }
+}
+
+static void object_bases_iterator_next(BLI_Iterator *iter, const int flag)
+{
+ Base *base = ((Base *)iter->data)->next;
+
+ while (base) {
+ if ((base->flag & flag) != 0) {
+ iter->current = base;
+ iter->data = base;
+ return;
+ }
+ base = base->next;
+ }
+
+ iter->valid = false;
+}
+
+static void objects_iterator_begin(BLI_Iterator *iter, void *data_in, const int flag)
+{
+ object_bases_iterator_begin(iter, data_in, flag);
+
+ if (iter->valid) {
+ iter->current = ((Base *)iter->current)->object;
+ }
+}
+
+static void objects_iterator_next(BLI_Iterator *iter, const int flag)
+{
+ object_bases_iterator_next(iter, flag);
+
+ if (iter->valid) {
+ iter->current = ((Base *)iter->current)->object;
+ }
+}
+
+void BKE_selected_objects_iterator_begin(BLI_Iterator *iter, void *data_in)
+{
+ objects_iterator_begin(iter, data_in, BASE_SELECTED);
+}
+
+void BKE_selected_objects_iterator_next(BLI_Iterator *iter)
+{
+ objects_iterator_next(iter, BASE_SELECTED);
+}
+
+void BKE_selected_objects_iterator_end(BLI_Iterator *UNUSED(iter))
+{
+ /* do nothing */
+}
+
+void BKE_visible_objects_iterator_begin(BLI_Iterator *iter, void *data_in)
+{
+ objects_iterator_begin(iter, data_in, BASE_VISIBLED);
+}
+
+void BKE_visible_objects_iterator_next(BLI_Iterator *iter)
+{
+ objects_iterator_next(iter, BASE_VISIBLED);
+}
+
+void BKE_visible_objects_iterator_end(BLI_Iterator *UNUSED(iter))
+{
+ /* do nothing */
+}
+
+void BKE_selected_bases_iterator_begin(BLI_Iterator *iter, void *data_in)
+{
+ object_bases_iterator_begin(iter, data_in, BASE_SELECTED);
+}
+
+void BKE_selected_bases_iterator_next(BLI_Iterator *iter)
+{
+ object_bases_iterator_next(iter, BASE_SELECTED);
+}
+
+void BKE_selected_bases_iterator_end(BLI_Iterator *UNUSED(iter))
+{
+ /* do nothing */
+}
+
+void BKE_visible_bases_iterator_begin(BLI_Iterator *iter, void *data_in)
+{
+ object_bases_iterator_begin(iter, data_in, BASE_VISIBLED);
+}
+
+void BKE_visible_bases_iterator_next(BLI_Iterator *iter)
+{
+ object_bases_iterator_next(iter, BASE_VISIBLED);
+}
+
+void BKE_visible_bases_iterator_end(BLI_Iterator *UNUSED(iter))
+{
+ /* do nothing */
+}
+
+void BKE_renderable_objects_iterator_begin(BLI_Iterator *iter, void *data_in)
+{
+ ObjectsRenderableIteratorData *data = data_in;
+
+ 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;
+
+ Base base = {(Base *)view_layer->object_bases.first, NULL};
+ data->iter.base = &base;
+
+ data->iter.set = NULL;
+
+ iter->data = data_in;
+ BKE_renderable_objects_iterator_next(iter);
+}
+
+void BKE_renderable_objects_iterator_next(BLI_Iterator *iter)
+{
+ 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;
+
+ iter->current = ob;
+ data->iter.base = base;
+
+ if ((base->flag & BASE_VISIBLED) == 0) {
+ BKE_renderable_objects_iterator_next(iter);
+ }
+ 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) {
+
+ Base base_iter = {(Base *)view_layer->object_bases.first, NULL};
+ data->iter.base = &base_iter;
+
+ BKE_renderable_objects_iterator_next(iter);
+ return;
+ }
+ }
+
+ /* Setup the "set" for the next iteration. */
+ Scene scene = {.set = data->scene};
+ data->iter.set = &scene;
+ BKE_renderable_objects_iterator_next(iter);
+ return;
+ }
+
+ /* Look for an object in the next set. */
+ while ((data->iter.set = data->iter.set->set)) {
+ ViewLayer *view_layer = BKE_view_layer_from_scene_get(data->iter.set);
+
+ Base base_iter = {(Base *)view_layer->object_bases.first, NULL};
+ data->iter.base = &base_iter;
+
+ BKE_renderable_objects_iterator_next(iter);
+ return;
+ }
+
+ iter->valid = false;
+}
+
+void BKE_renderable_objects_iterator_end(BLI_Iterator *UNUSED(iter))
+{
+ /* Do nothing - iter->data was static allocated, we can't free it. */
+}
+
+/* Evaluation */
+
+/**
+ * Reset props
+ *
+ * If props_ref is pasted, copy props from it
+ */
+static void idproperty_reset(IDProperty **props, IDProperty *props_ref)
+{
+ IDPropertyTemplate val = {0};
+
+ if (*props) {
+ IDP_FreeProperty(*props);
+ MEM_freeN(*props);
+ }
+ *props = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+
+ if (props_ref) {
+ IDP_MergeGroup(*props, props_ref, true);
+ }
+}
+
+void BKE_layer_eval_layer_collection_pre(const struct EvaluationContext *UNUSED(eval_ctx),
+ ID *owner_id, ViewLayer *view_layer)
+{
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, view_layer->name, view_layer);
+ Scene *scene = (GS(owner_id->name) == ID_SCE) ? (Scene *)owner_id : NULL;
+
+ for (Base *base = view_layer->object_bases.first; base != NULL; base = base->next) {
+ base->flag &= ~(BASE_VISIBLED | BASE_SELECTABLED);
+ idproperty_reset(&base->collection_properties, scene ? scene->collection_properties : NULL);
+ }
+
+ /* Sync properties from scene to scene layer. */
+ idproperty_reset(&view_layer->properties_evaluated, scene ? scene->layer_properties : NULL);
+ IDP_MergeGroup(view_layer->properties_evaluated, view_layer->properties, true);
+
+ /* TODO(sergey): Is it always required? */
+ view_layer->flag |= VIEW_LAYER_ENGINE_DIRTY;
+}
+
+static const char *collection_type_lookup[] =
+{
+ "None", /* COLLECTION_TYPE_NONE */
+ "Group Internal", /* COLLECTION_TYPE_GROUP_INTERNAL */
+};
+
+/**
+ * \note We can't use layer_collection->flag because of 3 level nesting (where parent is visible, but not grand-parent)
+ * So layer_collection->flag_evaluated is expected to be up to date with layer_collection->flag.
+ */
+static bool layer_collection_visible_get(const EvaluationContext *eval_ctx, LayerCollection *layer_collection)
+{
+ if (layer_collection->flag_evaluated & COLLECTION_DISABLED) {
+ return false;
+ }
+
+ if (eval_ctx->mode == DAG_EVAL_VIEWPORT) {
+ return (layer_collection->flag_evaluated & COLLECTION_VIEWPORT) != 0;
+ }
+ else {
+ return (layer_collection->flag_evaluated & COLLECTION_RENDER) != 0;
+ }
+}
+
+void BKE_layer_eval_layer_collection(const EvaluationContext *eval_ctx,
+ LayerCollection *layer_collection,
+ LayerCollection *parent_layer_collection)
+{
+ DEBUG_PRINT("%s on %s (%p) [%s], parent %s (%p) [%s]\n",
+ __func__,
+ layer_collection->scene_collection->name,
+ layer_collection->scene_collection,
+ collection_type_lookup[layer_collection->scene_collection->type],
+ (parent_layer_collection != NULL) ? parent_layer_collection->scene_collection->name : "NONE",
+ (parent_layer_collection != NULL) ? parent_layer_collection->scene_collection : NULL,
+ (parent_layer_collection != NULL) ? collection_type_lookup[parent_layer_collection->scene_collection->type] : "");
+ BLI_assert(layer_collection != parent_layer_collection);
+
+ /* visibility */
+ layer_collection->flag_evaluated = layer_collection->flag;
+
+ if (parent_layer_collection != NULL) {
+ if (layer_collection_visible_get(eval_ctx, parent_layer_collection) == false) {
+ layer_collection->flag_evaluated |= COLLECTION_DISABLED;
+ }
+
+ if ((parent_layer_collection->flag_evaluated & COLLECTION_DISABLED) ||
+ (parent_layer_collection->flag_evaluated & COLLECTION_SELECTABLE) == 0)
+ {
+ layer_collection->flag_evaluated &= ~COLLECTION_SELECTABLE;
+ }
+ }
+
+ const bool is_visible = layer_collection_visible_get(eval_ctx, layer_collection);
+ const bool is_selectable = is_visible && ((layer_collection->flag_evaluated & COLLECTION_SELECTABLE) != 0);
+
+ /* overrides */
+ if (is_visible) {
+ if (parent_layer_collection == NULL) {
+ idproperty_reset(&layer_collection->properties_evaluated, layer_collection->properties);
+ }
+ else {
+ idproperty_reset(&layer_collection->properties_evaluated, parent_layer_collection->properties_evaluated);
+ IDP_MergeGroup(layer_collection->properties_evaluated, layer_collection->properties, true);
+ }
+ }
+
+ for (LinkData *link = layer_collection->object_bases.first; link != NULL; link = link->next) {
+ Base *base = link->data;
+
+ if (is_visible) {
+ IDP_MergeGroup(base->collection_properties, layer_collection->properties_evaluated, true);
+ base->flag |= BASE_VISIBLED;
+ }
+
+ if (is_selectable) {
+ base->flag |= BASE_SELECTABLED;
+ }
+ }
+}
+
+void BKE_layer_eval_layer_collection_post(const struct EvaluationContext *UNUSED(eval_ctx),
+ ViewLayer *view_layer)
+{
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, view_layer->name, view_layer);
+ /* if base is not selectabled, clear select */
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ if ((base->flag & BASE_SELECTABLED) == 0) {
+ base->flag &= ~BASE_SELECTED;
+ }
+ }
+}
+
+/**
+ * Free any static allocated memory.
+ */
+void BKE_layer_exit(void)
+{
+ layer_collection_engine_settings_validate_free();
+}
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 46f8e637cf8..066b3e34b0d 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -62,6 +62,7 @@
#include "DNA_mask_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
+#include "DNA_lightprobe_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_speaker_types.h"
@@ -70,6 +71,7 @@
#include "DNA_vfont_types.h"
#include "DNA_windowmanager_types.h"
#include "DNA_world_types.h"
+#include "DNA_workspace_types.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
@@ -91,7 +93,6 @@
#include "BKE_cachefile.h"
#include "BKE_context.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_font.h"
#include "BKE_global.h"
#include "BKE_group.h"
@@ -103,6 +104,7 @@
#include "BKE_lamp.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
+#include "BKE_library_override.h"
#include "BKE_library_query.h"
#include "BKE_library_remap.h"
#include "BKE_linestyle.h"
@@ -117,6 +119,7 @@
#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_packedFile.h"
+#include "BKE_lightprobe.h"
#include "BKE_sound.h"
#include "BKE_speaker.h"
#include "BKE_scene.h"
@@ -418,6 +421,9 @@ bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local)
case ID_SPK:
if (!test) BKE_speaker_make_local(bmain, (Speaker *)id, lib_local);
return true;
+ case ID_LP:
+ if (!test) BKE_lightprobe_make_local(bmain, (LightProbe *)id, lib_local);
+ return true;
case ID_WO:
if (!test) BKE_world_make_local(bmain, (World *)id, lib_local);
return true;
@@ -469,7 +475,11 @@ bool id_make_local(Main *bmain, ID *id, const bool test, const bool lib_local)
case ID_CF:
if (!test) BKE_cachefile_make_local(bmain, (CacheFile *)id, lib_local);
return true;
+ case ID_WS:
case ID_SCR:
+ /* A bit special: can be appended but not linked. Return false
+ * since supporting make-local doesn't make much sense. */
+ return false;
case ID_LI:
case ID_KE:
case ID_WM:
@@ -589,6 +599,9 @@ bool BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag, con
case ID_SPK:
BKE_speaker_copy_data(bmain, (Speaker *)*r_newid, (Speaker *)id, flag);
break;
+ case ID_LP:
+ BKE_lightprobe_copy_data(bmain, (LightProbe *)*r_newid, (LightProbe *)id, flag);
+ break;
case ID_CA:
BKE_camera_copy_data(bmain, (Camera *)*r_newid, (Camera *)id, flag);
break;
@@ -649,6 +662,7 @@ bool BKE_id_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int flag, con
case ID_LI:
case ID_SCR:
case ID_WM:
+ case ID_WS:
case ID_IP:
BLI_assert(0); /* Should have been rejected at start of function! */
break;
@@ -680,6 +694,75 @@ bool id_copy(Main *bmain, const ID *id, ID **newid, bool test)
return BKE_id_copy_ex(bmain, id, newid, 0, test);
}
+/** Does a mere memory swap over the whole IDs data (including type-specific memory).
+ * \note Most internal ID data itself is not swapped (only IDProperties are). */
+void BKE_id_swap(Main *bmain, ID *id_a, ID *id_b)
+{
+ BLI_assert(GS(id_a->name) == GS(id_b->name));
+
+ const ID id_a_back = *id_a;
+ const ID id_b_back = *id_b;
+
+#define CASE_SWAP(_gs, _type) \
+ case _gs: \
+ SWAP(_type, *(_type *)id_a, *(_type *)id_b); \
+ break
+
+ switch ((ID_Type)GS(id_a->name)) {
+ CASE_SWAP(ID_SCE, Scene);
+ CASE_SWAP(ID_LI, Library);
+ CASE_SWAP(ID_OB, Object);
+ CASE_SWAP(ID_ME, Mesh);
+ CASE_SWAP(ID_CU, Curve);
+ CASE_SWAP(ID_MB, MetaBall);
+ CASE_SWAP(ID_MA, Material);
+ CASE_SWAP(ID_TE, Tex);
+ CASE_SWAP(ID_IM, Image);
+ CASE_SWAP(ID_LT, Lattice);
+ CASE_SWAP(ID_LA, Lamp);
+ CASE_SWAP(ID_LP, LightProbe);
+ CASE_SWAP(ID_CA, Camera);
+ CASE_SWAP(ID_KE, Key);
+ CASE_SWAP(ID_WO, World);
+ CASE_SWAP(ID_SCR, bScreen);
+ CASE_SWAP(ID_VF, VFont);
+ CASE_SWAP(ID_TXT, Text);
+ CASE_SWAP(ID_SPK, Speaker);
+ CASE_SWAP(ID_SO, bSound);
+ CASE_SWAP(ID_GR, Group);
+ CASE_SWAP(ID_AR, bArmature);
+ CASE_SWAP(ID_AC, bAction);
+ CASE_SWAP(ID_NT, bNodeTree);
+ CASE_SWAP(ID_BR, Brush);
+ CASE_SWAP(ID_PA, ParticleSettings);
+ CASE_SWAP(ID_WM, wmWindowManager);
+ CASE_SWAP(ID_WS, WorkSpace);
+ CASE_SWAP(ID_GD, bGPdata);
+ CASE_SWAP(ID_MC, MovieClip);
+ CASE_SWAP(ID_MSK, Mask);
+ CASE_SWAP(ID_LS, FreestyleLineStyle);
+ CASE_SWAP(ID_PAL, Palette);
+ CASE_SWAP(ID_PC, PaintCurve);
+ CASE_SWAP(ID_CF, CacheFile);
+ case ID_IP:
+ break; /* Deprecated. */
+ }
+
+#undef CASE_SWAP
+
+ /* Restore original ID's internal data. */
+ *id_a = id_a_back;
+ *id_b = id_b_back;
+
+ /* Exception: IDProperties. */
+ id_a->properties = id_b_back.properties;
+ id_b->properties = id_a_back.properties;
+
+ /* Swap will have broken internal references to itself, restore them. */
+ BKE_libblock_relink_ex(bmain, id_a, id_b, id_a, false);
+ BKE_libblock_relink_ex(bmain, id_b, id_a, id_b, false);
+}
+
/** Does *not* set ID->newid pointer. */
bool id_single_user(bContext *C, ID *id, PointerRNA *ptr, PropertyRNA *prop)
{
@@ -845,6 +928,8 @@ ListBase *which_libbase(Main *mainlib, short type)
return &(mainlib->text);
case ID_SPK:
return &(mainlib->speaker);
+ case ID_LP:
+ return &(mainlib->lightprobe);
case ID_SO:
return &(mainlib->sound);
case ID_GR:
@@ -875,6 +960,8 @@ ListBase *which_libbase(Main *mainlib, short type)
return &(mainlib->paintcurves);
case ID_CF:
return &(mainlib->cachefiles);
+ case ID_WS:
+ return &(mainlib->workspaces);
}
return NULL;
}
@@ -960,11 +1047,11 @@ void BKE_main_lib_objects_recalc_all(Main *bmain)
/* flag for full recalc */
for (ob = bmain->object.first; ob; ob = ob->id.next) {
if (ID_IS_LINKED(ob)) {
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
}
}
- DAG_id_type_tag(bmain, ID_OB);
+ DEG_id_type_tag(bmain, ID_OB);
}
/**
@@ -1013,6 +1100,7 @@ int set_listbasepointers(Main *main, ListBase **lb)
lb[INDEX_ID_BR] = &(main->brush);
lb[INDEX_ID_PA] = &(main->particle);
lb[INDEX_ID_SPK] = &(main->speaker);
+ lb[INDEX_ID_LP] = &(main->lightprobe);
lb[INDEX_ID_WO] = &(main->world);
lb[INDEX_ID_MC] = &(main->movieclip);
@@ -1020,6 +1108,7 @@ int set_listbasepointers(Main *main, ListBase **lb)
lb[INDEX_ID_OB] = &(main->object);
lb[INDEX_ID_LS] = &(main->linestyle); /* referenced by scenes */
lb[INDEX_ID_SCE] = &(main->scene);
+ lb[INDEX_ID_WS] = &(main->workspaces); /* before wm, so it's freed after it! */
lb[INDEX_ID_WM] = &(main->wm);
lb[INDEX_ID_MSK] = &(main->mask);
@@ -1072,6 +1161,7 @@ size_t BKE_libblock_get_alloc_info(short type, const char **name)
CASE_RETURN(ID_VF, VFont);
CASE_RETURN(ID_TXT, Text);
CASE_RETURN(ID_SPK, Speaker);
+ CASE_RETURN(ID_LP, LightProbe);
CASE_RETURN(ID_SO, bSound);
CASE_RETURN(ID_GR, Group);
CASE_RETURN(ID_AR, bArmature);
@@ -1087,6 +1177,7 @@ size_t BKE_libblock_get_alloc_info(short type, const char **name)
CASE_RETURN(ID_PAL, Palette);
CASE_RETURN(ID_PC, PaintCurve);
CASE_RETURN(ID_CF, CacheFile);
+ CASE_RETURN(ID_WS, WorkSpace);
}
return 0;
#undef CASE_RETURN
@@ -1143,7 +1234,7 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int fl
/* TODO to be removed from here! */
if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0) {
- DAG_id_type_tag(bmain, type);
+ DEG_id_type_tag(bmain, type);
}
}
else {
@@ -1202,6 +1293,9 @@ void BKE_libblock_init_empty(ID *id)
case ID_SPK:
BKE_speaker_init((Speaker *)id);
break;
+ case ID_LP:
+ BKE_lightprobe_init((LightProbe *)id);
+ break;
case ID_CA:
BKE_camera_init((Camera *)id);
break;
@@ -1322,11 +1416,20 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int fla
new_id->properties = IDP_CopyProperty_ex(id->properties, flag);
}
+ /* XXX Again... We need a way to control what we copy in a much more refined way.
+ * We cannot always copy this, some internal copying will die on it! */
+ /* For now, upper level code will have to do that itself when required. */
+#if 0
+ if (id->override != NULL) {
+ BKE_override_copy(new_id, id);
+ }
+#endif
+
/* the duplicate should get a copy of the animdata */
id_copy_animdata(bmain, new_id, (flag & LIB_ID_COPY_ACTIONS) != 0 && (flag & LIB_ID_CREATE_NO_MAIN) == 0);
if ((flag & LIB_ID_CREATE_NO_DEG_TAG) == 0 && (flag & LIB_ID_CREATE_NO_MAIN) == 0) {
- DAG_id_type_tag(bmain, GS(new_id->name));
+ DEG_id_type_tag(bmain, GS(new_id->name));
}
*r_newid = new_id;
diff --git a/source/blender/blenkernel/intern/library_override.c b/source/blender/blenkernel/intern/library_override.c
new file mode 100644
index 00000000000..8b8658921b5
--- /dev/null
+++ b/source/blender/blenkernel/intern/library_override.c
@@ -0,0 +1,752 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 by Blender Foundation.
+ * All rights reserved.
+ *
+ * Contributor(s): Bastien Montagne.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/library_override.c
+ * \ingroup bke
+ */
+
+#include <stdlib.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_ID.h"
+#include "DNA_object_types.h"
+
+#include "DEG_depsgraph.h"
+#include "BKE_library.h"
+#include "BKE_library_override.h"
+#include "BKE_library_remap.h"
+#include "BKE_main.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+
+#include "RNA_access.h"
+#include "RNA_types.h"
+
+#include "PIL_time.h"
+#include "PIL_time_utildefines.h"
+
+#define OVERRIDE_AUTO_CHECK_DELAY 0.2 /* 200ms between auto-override checks. */
+
+static void bke_override_property_copy(IDOverrideStaticProperty *op_dst, IDOverrideStaticProperty *op_src);
+static void bke_override_property_operation_copy(IDOverrideStaticPropertyOperation *opop_dst, IDOverrideStaticPropertyOperation *opop_src);
+
+static void bke_override_property_clear(IDOverrideStaticProperty *op);
+static void bke_override_property_operation_clear(IDOverrideStaticPropertyOperation *opop);
+
+/** Initialize empty overriding of \a reference_id by \a local_id. */
+IDOverrideStatic *BKE_override_static_init(ID *local_id, ID *reference_id)
+{
+ /* If reference_id is NULL, we are creating an override template for purely local data.
+ * Else, reference *must* be linked data. */
+ BLI_assert(reference_id == NULL || reference_id->lib != NULL);
+ BLI_assert(local_id->override_static == NULL);
+
+ ID *ancestor_id;
+ for (ancestor_id = reference_id;
+ ancestor_id != NULL && ancestor_id->override_static != NULL && ancestor_id->override_static->reference != NULL;
+ ancestor_id = ancestor_id->override_static->reference);
+
+ if (ancestor_id != NULL && ancestor_id->override_static != NULL) {
+ /* Original ID has a template, use it! */
+ BKE_override_static_copy(local_id, ancestor_id);
+ if (local_id->override_static->reference != reference_id) {
+ id_us_min(local_id->override_static->reference);
+ local_id->override_static->reference = reference_id;
+ id_us_plus(local_id->override_static->reference);
+ }
+ return local_id->override_static;
+ }
+
+ /* Else, generate new empty override. */
+ local_id->override_static = MEM_callocN(sizeof(*local_id->override_static), __func__);
+ local_id->override_static->reference = reference_id;
+ id_us_plus(local_id->override_static->reference);
+ local_id->tag &= ~LIB_TAG_OVERRIDESTATIC_OK;
+ /* TODO do we want to add tag or flag to referee to mark it as such? */
+ return local_id->override_static;
+}
+
+/** Deep copy of a whole override from \a src_id to \a dst_id. */
+void BKE_override_static_copy(ID *dst_id, const ID *src_id)
+{
+ BLI_assert(src_id->override_static != NULL);
+
+ if (dst_id->override_static != NULL) {
+ if (src_id->override_static == NULL) {
+ BKE_override_static_free(&dst_id->override_static);
+ return;
+ }
+ else {
+ BKE_override_static_clear(dst_id->override_static);
+ }
+ }
+ else if (src_id->override_static == NULL) {
+ return;
+ }
+ else {
+ BKE_override_static_init(dst_id, NULL);
+ }
+
+ /* Source is already overriding data, we copy it but reuse its reference for dest ID.
+ * otherwise, source is only an override template, it then becomes reference of dest ID. */
+ dst_id->override_static->reference = src_id->override_static->reference ? src_id->override_static->reference : (ID *)src_id;
+ id_us_plus(dst_id->override_static->reference);
+
+ BLI_duplicatelist(&dst_id->override_static->properties, &src_id->override_static->properties);
+ for (IDOverrideStaticProperty *op_dst = dst_id->override_static->properties.first, *op_src = src_id->override_static->properties.first;
+ op_dst;
+ op_dst = op_dst->next, op_src = op_src->next)
+ {
+ bke_override_property_copy(op_dst, op_src);
+ }
+
+ dst_id->tag &= ~LIB_TAG_OVERRIDESTATIC_OK;
+}
+
+/** Clear any overriding data from given \a override. */
+void BKE_override_static_clear(IDOverrideStatic *override)
+{
+ BLI_assert(override != NULL);
+
+ for (IDOverrideStaticProperty *op = override->properties.first; op; op = op->next) {
+ bke_override_property_clear(op);
+ }
+ BLI_freelistN(&override->properties);
+
+ id_us_min(override->reference);
+ /* override->storage should never be refcounted... */
+}
+
+/** Free given \a override. */
+void BKE_override_static_free(struct IDOverrideStatic **override)
+{
+ BLI_assert(*override != NULL);
+
+ BKE_override_static_clear(*override);
+ MEM_freeN(*override);
+ *override = NULL;
+}
+
+static ID *override_static_create_from(Main *bmain, ID *reference_id)
+{
+ ID *local_id;
+
+ if (!id_copy(bmain, reference_id, (ID **)&local_id, false)) {
+ return NULL;
+ }
+ id_us_min(local_id);
+
+ BKE_override_static_init(local_id, reference_id);
+ local_id->flag |= LIB_OVERRIDE_STATIC_AUTO;
+
+ return local_id;
+}
+
+
+/** Create an overriden local copy of linked reference. */
+ID *BKE_override_static_create_from_id(Main *bmain, ID *reference_id)
+{
+ BLI_assert(reference_id != NULL);
+ BLI_assert(reference_id->lib != NULL);
+
+ ID *local_id = override_static_create_from(bmain, reference_id);
+
+ /* Remapping, we obviously only want to affect local data (and not our own reference pointer to overriden ID). */
+ BKE_libblock_remap(bmain, reference_id, local_id, ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_STATIC_OVERRIDE);
+
+ return local_id;
+}
+
+/** Create overriden local copies of all tagged data-blocks in given Main.
+ *
+ * \note Set id->newid of overridden libs with newly created overrides, caller is responsible to clean those pointers
+ * before/after usage as needed.
+ *
+ * \return \a true on success, \a false otherwise.
+ */
+bool BKE_override_static_create_from_tag(Main *bmain)
+{
+ ListBase *lbarray[MAX_LIBARRAY];
+ int a;
+ bool ret = true;
+
+ const int num_types = a = set_listbasepointers(bmain, lbarray);
+ while (a--) {
+ for (ID *reference_id = lbarray[a]->first; reference_id != NULL; reference_id = reference_id->next) {
+ if ((reference_id->tag & LIB_TAG_DOIT) != 0 && reference_id->lib != NULL) {
+ if ((reference_id->newid = override_static_create_from(bmain, reference_id)) == NULL) {
+ ret = false;
+ }
+ }
+ }
+ }
+
+ /* Remapping, we obviously only want to affect local data (and not our own reference pointer to overriden ID). */
+ a = num_types;
+ while (a--) {
+ for (ID *reference_id = lbarray[a]->first; reference_id != NULL; reference_id = reference_id->next) {
+ if ((reference_id->tag & LIB_TAG_DOIT) != 0 && reference_id->lib != NULL && reference_id->newid != NULL) {
+ ID *local_id = reference_id->newid;
+ BKE_libblock_remap(bmain, reference_id, local_id,
+ ID_REMAP_SKIP_INDIRECT_USAGE | ID_REMAP_SKIP_STATIC_OVERRIDE);
+ }
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * Find override property from given RNA path, if it exists.
+ */
+IDOverrideStaticProperty *BKE_override_static_property_find(IDOverrideStatic *override, const char *rna_path)
+{
+ /* XXX TODO we'll most likely want a runtime ghash to store that mapping at some point. */
+ return BLI_findstring_ptr(&override->properties, rna_path, offsetof(IDOverrideStaticProperty, rna_path));
+}
+
+/**
+ * Find override property from given RNA path, or create it if it does not exist.
+ */
+IDOverrideStaticProperty *BKE_override_static_property_get(IDOverrideStatic *override, const char *rna_path, bool *r_created)
+{
+ /* XXX TODO we'll most likely want a runtime ghash to store taht mapping at some point. */
+ IDOverrideStaticProperty *op = BKE_override_static_property_find(override, rna_path);
+
+ if (op == NULL) {
+ op = MEM_callocN(sizeof(IDOverrideStaticProperty), __func__);
+ op->rna_path = BLI_strdup(rna_path);
+ BLI_addtail(&override->properties, op);
+
+ if (r_created) {
+ *r_created = true;
+ }
+ }
+ else if (r_created) {
+ *r_created = false;
+ }
+
+ return op;
+}
+
+void bke_override_property_copy(IDOverrideStaticProperty *op_dst, IDOverrideStaticProperty *op_src)
+{
+ op_dst->rna_path = BLI_strdup(op_src->rna_path);
+ BLI_duplicatelist(&op_dst->operations, &op_src->operations);
+
+ for (IDOverrideStaticPropertyOperation *opop_dst = op_dst->operations.first, *opop_src = op_src->operations.first;
+ opop_dst;
+ opop_dst = opop_dst->next, opop_src = opop_src->next)
+ {
+ bke_override_property_operation_copy(opop_dst, opop_src);
+ }
+}
+
+void bke_override_property_clear(IDOverrideStaticProperty *op)
+{
+ BLI_assert(op->rna_path != NULL);
+
+ MEM_freeN(op->rna_path);
+
+ for (IDOverrideStaticPropertyOperation *opop = op->operations.first; opop; opop = opop->next) {
+ bke_override_property_operation_clear(opop);
+ }
+ BLI_freelistN(&op->operations);
+}
+
+/**
+ * Remove and free given \a override_property from given ID \a override.
+ */
+void BKE_override_static_property_delete(IDOverrideStatic *override, IDOverrideStaticProperty *override_property)
+{
+ bke_override_property_clear(override_property);
+ BLI_freelinkN(&override->properties, override_property);
+}
+
+/**
+ * Find override property operation from given sub-item(s), if it exists.
+ */
+IDOverrideStaticPropertyOperation *BKE_override_static_property_operation_find(
+ IDOverrideStaticProperty *override_property,
+ const char *subitem_refname, const char *subitem_locname,
+ const int subitem_refindex, const int subitem_locindex, const bool strict, bool *r_strict)
+{
+ IDOverrideStaticPropertyOperation *opop;
+ const int subitem_defindex = -1;
+
+ if (r_strict) {
+ *r_strict = true;
+ }
+
+ if (subitem_locname &&
+ (opop = BLI_findstring_ptr(&override_property->operations, subitem_locname,
+ offsetof(IDOverrideStaticPropertyOperation, subitem_local_name))))
+ {
+ return opop;
+ }
+
+ if (subitem_refname &&
+ (opop = BLI_findstring_ptr(&override_property->operations, subitem_refname,
+ offsetof(IDOverrideStaticPropertyOperation, subitem_reference_name))))
+ {
+ return opop;
+ }
+
+ if ((opop = BLI_listbase_bytes_find(&override_property->operations, &subitem_locindex, sizeof(subitem_locindex),
+ offsetof(IDOverrideStaticPropertyOperation, subitem_local_index))))
+ {
+ return opop;
+ }
+
+ if ((opop = BLI_listbase_bytes_find(&override_property->operations, &subitem_refindex, sizeof(subitem_refindex),
+ offsetof(IDOverrideStaticPropertyOperation, subitem_reference_index))))
+ {
+ return opop;
+ }
+
+ /* index == -1 means all indices, that is valid fallback in case we requested specific index. */
+ if (!strict && (subitem_locindex != subitem_defindex) &&
+ (opop = BLI_listbase_bytes_find(&override_property->operations, &subitem_defindex, sizeof(subitem_defindex),
+ offsetof(IDOverrideStaticPropertyOperation, subitem_local_index))))
+ {
+ if (r_strict) {
+ *r_strict = false;
+ }
+ return opop;
+ }
+
+ return NULL;
+}
+
+/**
+ * Find override property operation from given sub-item(s), or create it if it does not exist.
+ */
+IDOverrideStaticPropertyOperation *BKE_override_static_property_operation_get(
+ IDOverrideStaticProperty *override_property, const short operation,
+ const char *subitem_refname, const char *subitem_locname,
+ const int subitem_refindex, const int subitem_locindex,
+ const bool strict, bool *r_strict, bool *r_created)
+{
+ IDOverrideStaticPropertyOperation *opop = BKE_override_static_property_operation_find(override_property,
+ subitem_refname, subitem_locname,
+ subitem_refindex, subitem_locindex,
+ strict, r_strict);
+
+ if (opop == NULL) {
+ opop = MEM_callocN(sizeof(IDOverrideStaticPropertyOperation), __func__);
+ opop->operation = operation;
+ if (subitem_locname) {
+ opop->subitem_local_name = BLI_strdup(subitem_locname);
+ }
+ if (subitem_refname) {
+ opop->subitem_reference_name = BLI_strdup(subitem_refname);
+ }
+ opop->subitem_local_index = subitem_locindex;
+ opop->subitem_reference_index = subitem_refindex;
+
+ BLI_addtail(&override_property->operations, opop);
+
+ if (r_created) {
+ *r_created = true;
+ }
+ }
+ else if (r_created) {
+ *r_created = false;
+ }
+
+ return opop;
+}
+
+void bke_override_property_operation_copy(IDOverrideStaticPropertyOperation *opop_dst, IDOverrideStaticPropertyOperation *opop_src)
+{
+ if (opop_src->subitem_reference_name) {
+ opop_dst->subitem_reference_name = BLI_strdup(opop_src->subitem_reference_name);
+ }
+ if (opop_src->subitem_local_name) {
+ opop_dst->subitem_local_name = BLI_strdup(opop_src->subitem_local_name);
+ }
+}
+
+void bke_override_property_operation_clear(IDOverrideStaticPropertyOperation *opop)
+{
+ if (opop->subitem_reference_name) {
+ MEM_freeN(opop->subitem_reference_name);
+ }
+ if (opop->subitem_local_name) {
+ MEM_freeN(opop->subitem_local_name);
+ }
+}
+
+/**
+ * Remove and free given \a override_property_operation from given ID \a override_property.
+ */
+void BKE_override_static_property_operation_delete(
+ IDOverrideStaticProperty *override_property, IDOverrideStaticPropertyOperation *override_property_operation)
+{
+ bke_override_property_operation_clear(override_property_operation);
+ BLI_freelinkN(&override_property->operations, override_property_operation);
+}
+
+/**
+ * Check that status of local data-block is still valid against current reference one.
+ *
+ * It means that all overridable, but not overridden, properties' local values must be equal to reference ones.
+ * Clears LIB_TAG_OVERRIDE_OK if they do not.
+ *
+ * This is typically used to detect whether some property has been changed in local and a new IDOverrideProperty
+ * (of IDOverridePropertyOperation) has to be added.
+ *
+ * \return true if status is OK, false otherwise. */
+bool BKE_override_static_status_check_local(ID *local)
+{
+ BLI_assert(local->override_static != NULL);
+
+ ID *reference = local->override_static->reference;
+
+ if (reference == NULL) {
+ /* This is an override template, local status is always OK! */
+ return true;
+ }
+
+ BLI_assert(GS(local->name) == GS(reference->name));
+
+ /* Note that reference is assumed always valid, caller has to ensure that itself. */
+
+ PointerRNA rnaptr_local, rnaptr_reference;
+ RNA_id_pointer_create(local, &rnaptr_local);
+ RNA_id_pointer_create(reference, &rnaptr_reference);
+
+ if (!RNA_struct_override_matches(
+ &rnaptr_local, &rnaptr_reference, NULL, local->override_static,
+ RNA_OVERRIDE_COMPARE_IGNORE_NON_OVERRIDABLE | RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN, NULL))
+ {
+ local->tag &= ~LIB_TAG_OVERRIDESTATIC_OK;
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Check that status of reference data-block is still valid against current local one.
+ *
+ * It means that all non-overridden properties' local values must be equal to reference ones.
+ * Clears LIB_TAG_OVERRIDE_OK if they do not.
+ *
+ * This is typically used to detect whether some reference has changed and local needs to be updated against it.
+ *
+ * \return true if status is OK, false otherwise. */
+bool BKE_override_static_status_check_reference(ID *local)
+{
+ BLI_assert(local->override_static != NULL);
+
+ ID *reference = local->override_static->reference;
+
+ if (reference == NULL) {
+ /* This is an override template, reference is virtual, so its status is always OK! */
+ return true;
+ }
+
+ BLI_assert(GS(local->name) == GS(reference->name));
+
+ if (reference->override_static && (reference->tag & LIB_TAG_OVERRIDESTATIC_OK) == 0) {
+ if (!BKE_override_static_status_check_reference(reference)) {
+ /* If reference is also override of another data-block, and its status is not OK,
+ * then this override is not OK either.
+ * Note that this should only happen when reloading libraries... */
+ local->tag &= ~LIB_TAG_OVERRIDESTATIC_OK;
+ return false;
+ }
+ }
+
+ PointerRNA rnaptr_local, rnaptr_reference;
+ RNA_id_pointer_create(local, &rnaptr_local);
+ RNA_id_pointer_create(reference, &rnaptr_reference);
+
+ if (!RNA_struct_override_matches(
+ &rnaptr_local, &rnaptr_reference, NULL, local->override_static,
+ RNA_OVERRIDE_COMPARE_IGNORE_OVERRIDDEN, NULL))
+ {
+ local->tag &= ~LIB_TAG_OVERRIDESTATIC_OK;
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * Compares local and reference data-blocks and create new override operations as needed,
+ * or reset to reference values if overriding is not allowed.
+ *
+ * \note Defining override operations is only mandatory before saving a .blend file on disk (not for undo!).
+ * Knowing that info at runtime is only useful for UI/UX feedback.
+ *
+ * \note This is by far the biggest operation (the more time-consuming) of the three so far, since it has to go over
+ * all properties in depth (all overridable ones at least). Generating diff values and applying overrides
+ * are much cheaper.
+ *
+ * \return true is new overriding op was created, or some local data was reset. */
+bool BKE_override_static_operations_create(ID *local)
+{
+ BLI_assert(local->override_static != NULL);
+ const bool is_template = (local->override_static->reference == NULL);
+ bool ret = false;
+
+ if (!is_template && local->flag & LIB_OVERRIDE_STATIC_AUTO) {
+ PointerRNA rnaptr_local, rnaptr_reference;
+ RNA_id_pointer_create(local, &rnaptr_local);
+ RNA_id_pointer_create(local->override_static->reference, &rnaptr_reference);
+
+ eRNAOverrideMatchResult report_flags = 0;
+ RNA_struct_override_matches(
+ &rnaptr_local, &rnaptr_reference, NULL, local->override_static,
+ RNA_OVERRIDE_COMPARE_CREATE | RNA_OVERRIDE_COMPARE_RESTORE, &report_flags);
+ if (report_flags & RNA_OVERRIDE_MATCH_RESULT_CREATED) {
+ ret = true;
+ }
+#ifndef NDEBUG
+ if (report_flags & RNA_OVERRIDE_MATCH_RESULT_RESTORED) {
+ printf("We did restore some properties of %s from its reference.\n", local->name);
+ }
+ if (ret) {
+ printf("We did generate static override rules for %s\n", local->name);
+ }
+ else {
+ printf("No new static override rules for %s\n", local->name);
+ }
+#endif
+ }
+ return ret;
+}
+
+/** Check all overrides from given \a bmain and create/update overriding operations as needed. */
+void BKE_main_override_static_operations_create(Main *bmain)
+{
+ ListBase *lbarray[MAX_LIBARRAY];
+ int base_count, i;
+
+ base_count = set_listbasepointers(bmain, lbarray);
+
+ for (i = 0; i < base_count; i++) {
+ ListBase *lb = lbarray[i];
+ ID *id;
+
+ for (id = lb->first; id; id = id->next) {
+ /* TODO Maybe we could also add an 'override update' tag e.g. when tagging for DEG update? */
+ if (id->lib == NULL && id->override_static != NULL && id->override_static->reference != NULL && (id->flag & LIB_OVERRIDE_STATIC_AUTO)) {
+ BKE_override_static_operations_create(id);
+ }
+ }
+ }
+}
+
+/** Update given override from its reference (re-applying overriden properties). */
+void BKE_override_static_update(Main *bmain, ID *local)
+{
+ if (local->override_static == NULL || local->override_static->reference == NULL) {
+ return;
+ }
+
+ /* Recursively do 'ancestors' overrides first, if any. */
+ if (local->override_static->reference->override_static && (local->override_static->reference->tag & LIB_TAG_OVERRIDESTATIC_OK) == 0) {
+ BKE_override_static_update(bmain, local->override_static->reference);
+ }
+
+ /* We want to avoid having to remap here, however creating up-to-date override is much simpler if based
+ * on reference than on current override.
+ * So we work on temp copy of reference, and 'swap' its content with local. */
+
+ /* XXX We need a way to get off-Main copies of IDs (similar to localized mats/texts/ etc.)!
+ * However, this is whole bunch of code work in itself, so for now plain stupid ID copy will do,
+ * as innefficient as it is. :/
+ * Actually, maybe not! Since we are swapping with original ID's local content, we want to keep
+ * usercount in correct state when freeing tmp_id (and that usercounts of IDs used by 'new' local data
+ * also remain correct). */
+ /* This would imply change in handling of usercout all over RNA (and possibly all over Blender code).
+ * Not impossible to do, but would rather see first if extra useless usual user handling is actually
+ * a (performances) issue here. */
+
+ ID *tmp_id;
+ id_copy(bmain, local->override_static->reference, &tmp_id, false);
+
+ if (tmp_id == NULL) {
+ return;
+ }
+
+ PointerRNA rnaptr_src, rnaptr_dst, rnaptr_storage_stack, *rnaptr_storage = NULL;
+ RNA_id_pointer_create(local, &rnaptr_src);
+ RNA_id_pointer_create(tmp_id, &rnaptr_dst);
+ if (local->override_static->storage) {
+ rnaptr_storage = &rnaptr_storage_stack;
+ RNA_id_pointer_create(local->override_static->storage, rnaptr_storage);
+ }
+
+ RNA_struct_override_apply(&rnaptr_dst, &rnaptr_src, rnaptr_storage, local->override_static);
+
+ /* This also transfers all pointers (memory) owned by local to tmp_id, and vice-versa. So when we'll free tmp_id,
+ * we'll actually free old, outdated data from local. */
+ BKE_id_swap(bmain, local, tmp_id);
+
+ /* Again, horribly innefficient in our case, we need something off-Main (aka moar generic nolib copy/free stuff)! */
+ /* XXX And crashing in complex cases (e.g. because depsgraph uses same data...). */
+ BKE_libblock_free_ex(bmain, tmp_id, true, false);
+
+ if (local->override_static->storage) {
+ /* We know this datablock is not used anywhere besides local->override->storage. */
+ /* XXX For until we get fully shadow copies, we still need to ensure storage releases
+ * its usage of any ID pointers it may have. */
+ BKE_libblock_free_ex(bmain, local->override_static->storage, true, false);
+ local->override_static->storage = NULL;
+ }
+
+ local->tag |= LIB_TAG_OVERRIDESTATIC_OK;
+
+ /* Full rebuild of Depsgraph! */
+ DEG_on_visible_update(bmain, true); /* XXX Is this actual valid replacement for old DAG_relations_tag_update(bmain) ? */
+}
+
+/** Update all overrides from given \a bmain. */
+void BKE_main_override_static_update(Main *bmain)
+{
+ ListBase *lbarray[MAX_LIBARRAY];
+ int base_count, i;
+
+ base_count = set_listbasepointers(bmain, lbarray);
+
+ for (i = 0; i < base_count; i++) {
+ ListBase *lb = lbarray[i];
+ ID *id;
+
+ for (id = lb->first; id; id = id->next) {
+ if (id->override_static != NULL && id->lib == NULL) {
+ BKE_override_static_update(bmain, id);
+ }
+ }
+ }
+}
+
+/***********************************************************************************************************************
+ * Storage (how to wtore overriding data into .blend files).
+ *
+ * Basically:
+ * I) Only 'differential' storage needs special handling here. All others (replacing values or
+ * inserting/removing items from a collection) can be handled with simply storing current content of local data-block.
+ * II) We store the differential value into a second 'ghost' data-block, which is an empty ID of same type as local one,
+ * where we only define values that need differential data.
+ *
+ * This avoids us having to modify 'real' data-block at write time (and retoring it afterwards), which is inneficient,
+ * and potentially dangerous (in case of concurrent access...), while not using much extra memory in typical cases.
+ * It also ensures stored data-block always contains exact same data as "desired" ones (kind of "baked" data-blocks).
+ */
+
+/** Initialize an override storage. */
+OverrideStaticStorage *BKE_override_static_operations_store_initialize(void)
+{
+ return BKE_main_new();
+}
+
+/**
+ * Generate suitable 'write' data (this only affects differential override operations).
+ *
+ * Note that \a local ID is no more modified by this call, all extra data are stored in its temp \a storage_id copy. */
+ID *BKE_override_static_operations_store_start(OverrideStaticStorage *override_storage, ID *local)
+{
+ BLI_assert(local->override_static != NULL);
+ BLI_assert(override_storage != NULL);
+ const bool is_template = (local->override_static->reference == NULL);
+
+ if (is_template) {
+ /* This is actually purely local data with an override template, nothing to do here! */
+ return NULL;
+ }
+
+ /* Forcefully ensure we know about all needed override operations. */
+ BKE_override_static_operations_create(local);
+
+ ID *storage_id;
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ TIMEIT_START_AVERAGED(BKE_override_operations_store_start);
+#endif
+
+ /* XXX TODO We may also want a specialized handling of things here too, to avoid copying heavy never-overridable
+ * data (like Mesh geometry etc.)? And also maybe avoid lib refcounting completely (shallow copy...). */
+ /* This would imply change in handling of usercout all over RNA (and possibly all over Blender code).
+ * Not impossible to do, but would rather see first is extra useless usual user handling is actually
+ * a (performances) issue here, before doing it. */
+ id_copy((Main *)override_storage, local, &storage_id, false);
+
+ if (storage_id != NULL) {
+ PointerRNA rnaptr_reference, rnaptr_final, rnaptr_storage;
+ RNA_id_pointer_create(local->override_static->reference, &rnaptr_reference);
+ RNA_id_pointer_create(local, &rnaptr_final);
+ RNA_id_pointer_create(storage_id, &rnaptr_storage);
+
+ if (!RNA_struct_override_store(&rnaptr_final, &rnaptr_reference, &rnaptr_storage, local->override_static)) {
+ BKE_libblock_free_ex(override_storage, storage_id, true, false);
+ storage_id = NULL;
+ }
+ }
+
+ local->override_static->storage = storage_id;
+
+#ifdef DEBUG_OVERRIDE_TIMEIT
+ TIMEIT_END_AVERAGED(BKE_override_operations_store_start);
+#endif
+ return storage_id;
+}
+
+/** Restore given ID modified by \a BKE_override_operations_store_start, to its original state. */
+void BKE_override_static_operations_store_end(OverrideStaticStorage *UNUSED(override_storage), ID *local)
+{
+ BLI_assert(local->override_static != NULL);
+
+ /* Nothing else to do here really, we need to keep all temp override storage data-blocks in memory until
+ * whole file is written anyway (otherwise we'd get mem pointers overlap...). */
+ local->override_static->storage = NULL;
+}
+
+void BKE_override_static_operations_store_finalize(OverrideStaticStorage *override_storage)
+{
+ /* We cannot just call BKE_main_free(override_storage), not until we have option to make 'ghost' copies of IDs
+ * without increasing usercount of used data-blocks... */
+ ListBase *lbarray[MAX_LIBARRAY];
+ int base_count, i;
+
+ base_count = set_listbasepointers(override_storage, lbarray);
+
+ for (i = 0; i < base_count; i++) {
+ ListBase *lb = lbarray[i];
+ ID *id;
+
+ while ((id = lb->first)) {
+ BKE_libblock_free_ex(override_storage, id, true, false);
+ }
+ }
+
+ BKE_main_free(override_storage);
+}
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index 0dda3d3c7d6..317f743acf1 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -52,6 +52,7 @@
#include "DNA_mask_types.h"
#include "DNA_node_types.h"
#include "DNA_object_force.h"
+#include "DNA_lightprobe_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
#include "DNA_sensor_types.h"
@@ -61,6 +62,8 @@
#include "DNA_sound_types.h"
#include "DNA_text_types.h"
#include "DNA_vfont_types.h"
+#include "DNA_windowmanager_types.h"
+#include "DNA_workspace_types.h"
#include "DNA_world_types.h"
#include "BLI_utildefines.h"
@@ -69,8 +72,10 @@
#include "BLI_linklist_stack.h"
#include "BKE_animsys.h"
+#include "BKE_collection.h"
#include "BKE_constraint.h"
#include "BKE_fcurve.h"
+#include "BKE_group.h"
#include "BKE_idprop.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
@@ -82,6 +87,7 @@
#include "BKE_sca.h"
#include "BKE_sequencer.h"
#include "BKE_tracking.h"
+#include "BKE_workspace.h"
#define FOREACH_FINALIZE _finalize
@@ -368,6 +374,10 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
#define CALLBACK_INVOKE(check_id_super, cb_flag) \
FOREACH_CALLBACK_INVOKE(&data, check_id_super, cb_flag)
+ if (id->override_static != NULL) {
+ CALLBACK_INVOKE_ID(id->override_static->reference, IDWALK_CB_USER | IDWALK_CB_STATIC_OVERRIDE_REFERENCE);
+ }
+
for (; id != NULL; id = (flag & IDWALK_RECURSE) ? BLI_LINKSTACK_POP(data.ids_todo) : NULL) {
data.self_id = id;
data.cb_flag = ID_IS_LINKED(id) ? IDWALK_CB_INDIRECT_USAGE : 0;
@@ -402,8 +412,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
{
Scene *scene = (Scene *) id;
ToolSettings *toolsett = scene->toolsettings;
- SceneRenderLayer *srl;
- Base *base;
CALLBACK_INVOKE(scene->camera, IDWALK_CB_NOP);
CALLBACK_INVOKE(scene->world, IDWALK_CB_USER);
@@ -417,31 +425,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
* since basact is just a pointer to one of those items. */
CALLBACK_INVOKE(scene->obedit, IDWALK_CB_NOP);
- for (srl = scene->r.layers.first; srl; srl = srl->next) {
- FreestyleModuleConfig *fmc;
- FreestyleLineSet *fls;
-
- if (srl->mat_override) {
- CALLBACK_INVOKE(srl->mat_override, IDWALK_CB_USER);
- }
- if (srl->light_override) {
- CALLBACK_INVOKE(srl->light_override, IDWALK_CB_USER);
- }
- for (fmc = srl->freestyleConfig.modules.first; fmc; fmc = fmc->next) {
- if (fmc->script) {
- CALLBACK_INVOKE(fmc->script, IDWALK_CB_NOP);
- }
- }
- for (fls = srl->freestyleConfig.linesets.first; fls; fls = fls->next) {
- if (fls->group) {
- CALLBACK_INVOKE(fls->group, IDWALK_CB_USER);
- }
- if (fls->linestyle) {
- CALLBACK_INVOKE(fls->linestyle, IDWALK_CB_USER);
- }
- }
- }
-
if (scene->ed) {
Sequence *seq;
SEQP_BEGIN(scene->ed, seq)
@@ -461,8 +444,39 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
CALLBACK_INVOKE(scene->gpd, IDWALK_CB_USER);
- for (base = scene->base.first; base; base = base->next) {
- CALLBACK_INVOKE(base->object, IDWALK_CB_USER);
+ FOREACH_SCENE_COLLECTION(scene, sc)
+ {
+ for (LinkData *link = sc->objects.first; link; link = link->next) {
+ CALLBACK_INVOKE_ID(link->data, IDWALK_CB_USER);
+ }
+
+ for (LinkData *link = sc->filter_objects.first; link; link = link->next) {
+ CALLBACK_INVOKE_ID(link->data, IDWALK_CB_USER);
+ }
+ }
+ FOREACH_SCENE_COLLECTION_END
+
+ ViewLayer *view_layer;
+ for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ CALLBACK_INVOKE(base->object, IDWALK_NOP);
+ }
+
+ for (FreestyleModuleConfig *fmc = view_layer->freestyle_config.modules.first; fmc; fmc = fmc->next) {
+ if (fmc->script) {
+ CALLBACK_INVOKE(fmc->script, IDWALK_CB_NOP);
+ }
+ }
+
+ for (FreestyleLineSet *fls = view_layer->freestyle_config.linesets.first; fls; fls = fls->next) {
+ if (fls->group) {
+ CALLBACK_INVOKE(fls->group, IDWALK_CB_USER);
+ }
+
+ if (fls->linestyle) {
+ CALLBACK_INVOKE(fls->linestyle, IDWALK_CB_USER);
+ }
+ }
}
for (TimeMarker *marker = scene->markers.first; marker; marker = marker->next) {
@@ -624,31 +638,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
for (i = 0; i < mesh->totcol; i++) {
CALLBACK_INVOKE(mesh->mat[i], IDWALK_CB_USER);
}
-
- /* XXX Really not happy with this - probably texface should rather use some kind of
- * 'texture slots' and just set indices in each poly/face item - would also save some memory.
- * Maybe a nice TODO for blender2.8? */
- if (mesh->mtface || mesh->mtpoly) {
- for (i = 0; i < mesh->pdata.totlayer; i++) {
- if (mesh->pdata.layers[i].type == CD_MTEXPOLY) {
- MTexPoly *txface = (MTexPoly *)mesh->pdata.layers[i].data;
-
- for (int j = 0; j < mesh->totpoly; j++, txface++) {
- CALLBACK_INVOKE(txface->tpage, IDWALK_CB_USER_ONE);
- }
- }
- }
-
- for (i = 0; i < mesh->fdata.totlayer; i++) {
- if (mesh->fdata.layers[i].type == CD_MTFACE) {
- MTFace *tface = (MTFace *)mesh->fdata.layers[i].data;
-
- for (int j = 0; j < mesh->totface; j++, tface++) {
- CALLBACK_INVOKE(tface->tpage, IDWALK_CB_USER_ONE);
- }
- }
- }
- }
break;
}
@@ -691,6 +680,7 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
library_foreach_ID_as_subdata_link((ID **)&material->nodetree, callback, user_data, flag, &data);
}
CALLBACK_INVOKE(material->group, IDWALK_CB_USER);
+ CALLBACK_INVOKE(material->edit_image, IDWALK_CB_USER);
break;
}
@@ -751,13 +741,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
break;
}
- case ID_SCR:
- {
- bScreen *screen = (bScreen *) id;
- CALLBACK_INVOKE(screen->scene, IDWALK_CB_USER_ONE);
- break;
- }
-
case ID_WO:
{
World *world = (World *) id;
@@ -780,13 +763,21 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
break;
}
+ case ID_LP:
+ {
+ LightProbe *probe = (LightProbe *) id;
+ CALLBACK_INVOKE(probe->image, IDWALK_CB_USER);
+ break;
+ }
+
case ID_GR:
{
Group *group = (Group *) id;
- GroupObject *gob;
- for (gob = group->gobject.first; gob; gob = gob->next) {
- CALLBACK_INVOKE(gob->ob, IDWALK_CB_USER_ONE);
+ FOREACH_GROUP_BASE(group, base)
+ {
+ CALLBACK_INVOKE(base->object, IDWALK_CB_USER_ONE);
}
+ FOREACH_GROUP_BASE_END
break;
}
@@ -968,6 +959,40 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
}
break;
}
+
+ case ID_WM:
+ {
+ wmWindowManager *wm = (wmWindowManager *)id;
+
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ ID *workspace = (ID *)BKE_workspace_active_get(win->workspace_hook);
+
+ CALLBACK_INVOKE(win->scene, IDWALK_CB_USER_ONE);
+
+ CALLBACK_INVOKE_ID(workspace, IDWALK_CB_NOP);
+ /* allow callback to set a different workspace */
+ BKE_workspace_active_set(win->workspace_hook, (WorkSpace *)workspace);
+ }
+ break;
+ }
+
+ case ID_WS:
+ {
+ WorkSpace *workspace = (WorkSpace *)id;
+ ListBase *layouts = BKE_workspace_layouts_get(workspace);
+
+ for (WorkSpaceLayout *layout = layouts->first; layout; layout = layout->next) {
+ bScreen *screen = BKE_workspace_layout_screen_get(layout);
+
+ /* CALLBACK_INVOKE expects an actual pointer, not a variable holding the pointer.
+ * However we can't acess layout->screen here since we are outside the workspace project. */
+ CALLBACK_INVOKE(screen, IDWALK_CB_NOP);
+ /* allow callback to set a different screen */
+ BKE_workspace_layout_screen_set(layout, screen);
+ }
+
+ break;
+ }
case ID_GD:
{
bGPdata *gpencil = (bGPdata *) id;
@@ -979,11 +1004,11 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
}
/* Nothing needed for those... */
+ case ID_SCR:
case ID_IM:
case ID_VF:
case ID_TXT:
case ID_SO:
- case ID_WM:
case ID_PAL:
case ID_PC:
case ID_CF:
@@ -1111,6 +1136,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 49effd033e3..fb672cb8b9f 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -53,6 +53,7 @@
#include "DNA_mask_types.h"
#include "DNA_node_types.h"
#include "DNA_object_types.h"
+#include "DNA_lightprobe_types.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_speaker_types.h"
@@ -60,6 +61,7 @@
#include "DNA_text_types.h"
#include "DNA_vfont_types.h"
#include "DNA_windowmanager_types.h"
+#include "DNA_workspace_types.h"
#include "DNA_world_types.h"
#include "BLI_blenlib.h"
@@ -71,8 +73,8 @@
#include "BKE_brush.h"
#include "BKE_camera.h"
#include "BKE_cachefile.h"
+#include "BKE_collection.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_font.h"
#include "BKE_group.h"
@@ -83,7 +85,9 @@
#include "BKE_key.h"
#include "BKE_lamp.h"
#include "BKE_lattice.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
+#include "BKE_library_override.h"
#include "BKE_library_query.h"
#include "BKE_library_remap.h"
#include "BKE_linestyle.h"
@@ -99,6 +103,7 @@
#include "BKE_object.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
+#include "BKE_lightprobe.h"
#include "BKE_sca.h"
#include "BKE_speaker.h"
#include "BKE_sound.h"
@@ -106,8 +111,12 @@
#include "BKE_scene.h"
#include "BKE_text.h"
#include "BKE_texture.h"
+#include "BKE_workspace.h"
#include "BKE_world.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#ifdef WITH_PYTHON
#include "BPY_extern.h"
#endif
@@ -173,6 +182,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
}
if (*id_p && (*id_p == old_id)) {
+ const bool is_reference = (cb_flag & IDWALK_CB_STATIC_OVERRIDE_REFERENCE) != 0;
const bool is_indirect = (cb_flag & IDWALK_CB_INDIRECT_USAGE) != 0;
const bool skip_indirect = (id_remap_data->flag & ID_REMAP_SKIP_INDIRECT_USAGE) != 0;
/* Note: proxy usage implies LIB_TAG_EXTERN, so on this aspect it is direct,
@@ -183,6 +193,7 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
const bool is_obj_editmode = (is_obj && BKE_object_is_in_editmode((Object *)id));
const bool is_never_null = ((cb_flag & IDWALK_CB_NEVER_NULL) && (new_id == NULL) &&
(id_remap_data->flag & ID_REMAP_FORCE_NEVER_NULL_USAGE) == 0);
+ const bool skip_reference = (id_remap_data->flag & ID_REMAP_SKIP_STATIC_OVERRIDE) != 0;
const bool skip_never_null = (id_remap_data->flag & ID_REMAP_SKIP_NEVER_NULL_USAGE) != 0;
#ifdef DEBUG_PRINT
@@ -197,7 +208,8 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
/* Special hack in case it's Object->data and we are in edit mode (skipped_direct too). */
if ((is_never_null && skip_never_null) ||
(is_obj_editmode && (((Object *)id)->data == *id_p)) ||
- (skip_indirect && is_indirect))
+ (skip_indirect && is_indirect) ||
+ (is_reference && skip_reference))
{
if (is_indirect) {
id_remap_data->skipped_indirect++;
@@ -210,7 +222,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 {
@@ -227,7 +239,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);
@@ -250,17 +262,15 @@ static int foreach_libblock_remap_callback(void *user_data, ID *id_self, ID **id
}
/* Some remapping unfortunately require extra and/or specific handling, tackle those here. */
-static void libblock_remap_data_preprocess_scene_base_unlink(
- IDRemap *r_id_remap_data, Scene *sce, Base *base, const bool skip_indirect, const bool is_indirect)
+static void libblock_remap_data_preprocess_scene_object_unlink(
+ IDRemap *r_id_remap_data, Scene *sce, Object *ob, const bool skip_indirect, const bool is_indirect)
{
if (skip_indirect && is_indirect) {
r_id_remap_data->skipped_indirect++;
r_id_remap_data->skipped_refcounted++;
}
else {
- id_us_min((ID *)base->object);
- BKE_scene_base_unlink(sce, base);
- MEM_freeN(base);
+ BKE_collections_object_remove(r_id_remap_data->bmain, &sce->id, ob, false);
if (!is_indirect) {
r_id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT;
}
@@ -281,22 +291,18 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
/* In case we are unlinking... */
if (!r_id_remap_data->old_id) {
/* ... everything from scene. */
- Base *base, *base_next;
- for (base = sce->base.first; base; base = base_next) {
- base_next = base->next;
- libblock_remap_data_preprocess_scene_base_unlink(
- r_id_remap_data, sce, base, skip_indirect, is_indirect);
+ FOREACH_SCENE_OBJECT(sce, ob_iter)
+ {
+ libblock_remap_data_preprocess_scene_object_unlink(
+ r_id_remap_data, sce, ob_iter, skip_indirect, is_indirect);
}
+ FOREACH_SCENE_OBJECT_END
}
else if (GS(r_id_remap_data->old_id->name) == ID_OB) {
/* ... a specific object from scene. */
Object *old_ob = (Object *)r_id_remap_data->old_id;
- Base *base = BKE_scene_base_find(sce, old_ob);
-
- if (base) {
- libblock_remap_data_preprocess_scene_base_unlink(
- r_id_remap_data, sce, base, skip_indirect, is_indirect);
- }
+ libblock_remap_data_preprocess_scene_object_unlink(
+ r_id_remap_data, sce, old_ob, skip_indirect, is_indirect);
}
}
break;
@@ -338,7 +344,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 {
@@ -348,7 +354,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);
}
}
}
@@ -358,26 +364,21 @@ static void libblock_remap_data_postprocess_group_scene_unlink(Main *UNUSED(bmai
{
/* Note that here we assume no object has no base (i.e. all objects are assumed instanced
* in one scene...). */
- for (Base *base = sce->base.first; base; base = base->next) {
- if (base->flag & OB_FROMGROUP) {
- Object *ob = base->object;
-
- if (ob->flag & OB_FROMGROUP) {
- Group *grp = BKE_group_object_find(NULL, ob);
-
- /* Unlinked group (old_id) is still in bmain... */
- if (grp && (&grp->id == old_id || grp->id.us == 0)) {
- grp = BKE_group_object_find(grp, ob);
- }
- if (!grp) {
- ob->flag &= ~OB_FROMGROUP;
- }
+ FOREACH_SCENE_OBJECT(sce, ob)
+ {
+ if (ob->flag & OB_FROMGROUP) {
+ Group *grp = BKE_group_object_find(NULL, ob);
+
+ /* Unlinked group (old_id) is still in bmain... */
+ if (grp && (&grp->id == old_id || grp->id.us == 0)) {
+ grp = BKE_group_object_find(grp, ob);
}
- if (!(ob->flag & OB_FROMGROUP)) {
- base->flag &= ~OB_FROMGROUP;
+ if (!grp) {
+ ob->flag &= ~OB_FROMGROUP;
}
}
}
+ FOREACH_SCENE_OBJECT_END
}
static void libblock_remap_data_postprocess_obdata_relink(Main *UNUSED(bmain), Object *ob, ID *new_id)
@@ -592,8 +593,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)
@@ -745,6 +746,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! */
}
@@ -809,6 +814,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;
@@ -855,6 +863,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;
}
}
@@ -893,7 +904,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
@@ -956,7 +967,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..d5dbbe873a2
--- /dev/null
+++ b/source/blender/blenkernel/intern/lightprobe.c
@@ -0,0 +1,100 @@
+/*
+ * ***** 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->data_draw_size = 1.0f;
+
+ probe->flag = LIGHTPROBE_FLAG_SHOW_INFLUENCE | LIGHTPROBE_FLAG_SHOW_DATA;
+}
+
+void *BKE_lightprobe_add(Main *bmain, const char *name)
+{
+ LightProbe *probe;
+
+ probe = BKE_libblock_alloc(bmain, ID_LP, name, 0);
+
+ BKE_lightprobe_init(probe);
+
+ return probe;
+}
+
+/**
+ * Only copy internal data of LightProbe ID from source to already allocated/initialized destination.
+ * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
+ *
+ * WARNING! This function will not handle ID user count!
+ *
+ * \param flag Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
+ */
+void BKE_lightprobe_copy_data(
+ Main *UNUSED(bmain), LightProbe *UNUSED(probe_dst), const LightProbe *UNUSED(probe_src), const int UNUSED(flag))
+{
+ /* Nothing to do here. */
+}
+
+LightProbe *BKE_lightprobe_copy(Main *bmain, const LightProbe *probe)
+{
+ LightProbe *probe_copy;
+ BKE_id_copy_ex(bmain, &probe->id, (ID **)&probe_copy, 0, false);
+ return probe_copy;
+}
+
+void BKE_lightprobe_make_local(Main *bmain, LightProbe *probe, const bool lib_local)
+{
+ BKE_id_make_local_generic(bmain, &probe->id, true, lib_local);
+}
+
+void BKE_lightprobe_free(LightProbe *probe)
+{
+ BKE_animdata_free((ID *)probe, false);
+}
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index 0465c5d54f7..2fc4c81cb0b 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -215,12 +215,13 @@ void BKE_linestyle_make_local(struct Main *bmain, FreestyleLineStyle *linestyle,
FreestyleLineStyle *BKE_linestyle_active_from_scene(Scene *scene)
{
- SceneRenderLayer *actsrl = BLI_findlink(&scene->r.layers, scene->r.actlay);
- FreestyleConfig *config = &actsrl->freestyleConfig;
- FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config);
-
- if (lineset) {
- return lineset->linestyle;
+ ViewLayer *active_render_layer = BLI_findlink(&scene->view_layers, scene->active_view_layer);
+ if (active_render_layer) {
+ FreestyleConfig *config = &active_render_layer->freestyle_config;
+ FreestyleLineSet *lineset = BKE_freestyle_lineset_get_active(config);
+ if (lineset) {
+ return lineset->linestyle;
+ }
}
return NULL;
}
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index ff4e7f36018..3256c16e2f6 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -51,7 +51,6 @@
#include "BKE_animsys.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
@@ -62,6 +61,8 @@
#include "BKE_movieclip.h"
#include "BKE_image.h"
+#include "DEG_depsgraph_build.h"
+
static struct {
ListBase splines;
struct GHash *id_hash;
@@ -818,7 +819,7 @@ Mask *BKE_mask_new(Main *bmain, const char *name)
mask->sfra = 1;
mask->efra = 100;
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
return mask;
}
@@ -1458,18 +1459,6 @@ void BKE_mask_evaluate_all_masks(Main *bmain, float ctime, const bool do_newfram
}
}
-void BKE_mask_update_scene(Main *bmain, Scene *scene)
-{
- Mask *mask;
-
- for (mask = bmain->mask.first; mask; mask = mask->id.next) {
- if (mask->id.recalc & ID_RECALC_ALL) {
- bool do_new_frame = (mask->id.recalc & ID_RECALC_DATA) != 0;
- BKE_mask_evaluate_all_masks(bmain, CFRA, do_new_frame);
- }
- }
-}
-
void BKE_mask_parent_init(MaskParent *parent)
{
parent->id_type = ID_MC;
diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c
index 0d71cc548c7..f60d87f2464 100644
--- a/source/blender/blenkernel/intern/mask_evaluate.c
+++ b/source/blender/blenkernel/intern/mask_evaluate.c
@@ -42,10 +42,11 @@
#include "DNA_mask_types.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_mask.h"
+#include "DEG_depsgraph.h"
+
unsigned int BKE_mask_spline_resolution(MaskSpline *spline, int width, int height)
{
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 0dd7047a376..7235aa0aaf6 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -58,7 +58,6 @@
#include "BKE_animsys.h"
#include "BKE_displist.h"
#include "BKE_global.h"
-#include "BKE_depsgraph.h"
#include "BKE_icons.h"
#include "BKE_image.h"
#include "BKE_library.h"
@@ -73,6 +72,8 @@
#include "BKE_editmesh.h"
#include "BKE_font.h"
+#include "DEG_depsgraph_build.h"
+
#include "GPU_material.h"
/* used in UI and render */
@@ -206,6 +207,8 @@ void BKE_material_init(Material *ma)
ma->mode2 = MA_CASTSHADOW;
ma->shade_flag = MA_APPROX_OCCLUSION;
ma->preview = NULL;
+
+ ma->alpha_threshold = 0.5f;
}
Material *BKE_material_add(Main *bmain, const char *name)
@@ -257,6 +260,8 @@ void BKE_material_copy_data(Main *bmain, Material *ma_dst, const Material *ma_sr
}
BLI_listbase_clear(&ma_dst->gpumaterial);
+
+ /* TODO Duplicate Engine Settings and set runtime to NULL */
}
Material *BKE_material_copy(Main *bmain, const Material *ma)
@@ -299,6 +304,8 @@ Material *BKE_material_localize(Material *ma)
man->nodetree = ntreeLocalize(ma->nodetree);
BLI_listbase_clear(&man->gpumaterial);
+
+ /* TODO Duplicate Engine Settings and set runtime to NULL */
return man;
}
@@ -454,7 +461,7 @@ void BKE_material_resize_id(Main *bmain, ID *id, short totcol, bool do_id_user)
}
*totcolp = totcol;
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
void BKE_material_append_id(Main *bmain, ID *id, Material *ma)
@@ -471,7 +478,7 @@ void BKE_material_append_id(Main *bmain, ID *id, Material *ma)
id_us_plus((ID *)ma);
test_all_objects_materials(bmain, id);
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
}
@@ -505,7 +512,7 @@ Material *BKE_material_pop_id(Main *bmain, ID *id, int index_i, bool update_data
material_data_index_remove_id(id, index);
}
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
}
@@ -532,7 +539,7 @@ void BKE_material_clear_id(Main *bmain, ID *id, bool update_data)
material_data_index_clear_id(id);
}
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
}
@@ -627,7 +634,7 @@ void BKE_material_resize_object(Main *bmain, Object *ob, const short totcol, boo
if (ob->totcol && ob->actcol == 0) ob->actcol = 1;
if (ob->actcol > ob->totcol) ob->actcol = ob->totcol;
- DAG_relations_tag_update(bmain);
+ DEG_relations_tag_update(bmain);
}
void test_object_materials(Object *ob, ID *id)
@@ -967,7 +974,7 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb)
if (needtang) ma->mode |= MA_NORMAP_TANG;
else ma->mode &= ~MA_NORMAP_TANG;
- if (ma->mode & (MA_VERTEXCOL | MA_VERTEXCOLP | MA_FACETEXTURE)) {
+ if (ma->mode & (MA_VERTEXCOL | MA_VERTEXCOLP)) {
needuv = 1;
if (r_mode & R_OSA) ma->texco |= TEXCO_OSA; /* for texfaces */
}
@@ -1149,61 +1156,6 @@ bool material_in_material(Material *parmat, Material *mat)
/* ****************** */
-/* Update drivers for materials in a nodetree */
-static void material_node_drivers_update(Scene *scene, bNodeTree *ntree, float ctime)
-{
- bNode *node;
-
- /* nodetree itself */
- if (ntree->adt && ntree->adt->drivers.first) {
- BKE_animsys_evaluate_animdata(scene, &ntree->id, ntree->adt, ctime, ADT_RECALC_DRIVERS);
- }
-
- /* nodes */
- for (node = ntree->nodes.first; node; node = node->next) {
- if (node->id) {
- if (GS(node->id->name) == ID_MA) {
- material_drivers_update(scene, (Material *)node->id, ctime);
- }
- else if (node->type == NODE_GROUP) {
- material_node_drivers_update(scene, (bNodeTree *)node->id, ctime);
- }
- }
- }
-}
-
-/* Calculate all drivers for materials
- * FIXME: this is really a terrible method which may result in some things being calculated
- * multiple times. However, without proper despgraph support for these things, we are forced
- * into this sort of thing...
- */
-void material_drivers_update(Scene *scene, Material *ma, float ctime)
-{
- //if (G.f & G_DEBUG)
- // printf("material_drivers_update(%s, %s)\n", scene->id.name, ma->id.name);
-
- /* Prevent infinite recursion by checking (and tagging the material) as having been visited already
- * (see BKE_scene_update_tagged()). This assumes ma->id.tag & LIB_TAG_DOIT isn't set by anything else
- * in the meantime... [#32017]
- */
- if (ma->id.tag & LIB_TAG_DOIT)
- return;
-
- ma->id.tag |= LIB_TAG_DOIT;
-
- /* material itself */
- if (ma->adt && ma->adt->drivers.first) {
- BKE_animsys_evaluate_animdata(scene, &ma->id, ma->adt, ctime, ADT_RECALC_DRIVERS);
- }
-
- /* nodes */
- if (ma->nodetree) {
- material_node_drivers_update(scene, ma->nodetree, ctime);
- }
-
- ma->id.tag &= ~LIB_TAG_DOIT;
-}
-
bool BKE_object_material_slot_remove(Object *ob)
{
Material *mao, ***matarar;
@@ -1328,6 +1280,14 @@ void BKE_texpaint_slot_refresh_cache(Scene *scene, Material *ma)
bool use_nodes = BKE_scene_use_new_shading_nodes(scene);
bool is_bi = BKE_scene_uses_blender_internal(scene) || BKE_scene_uses_blender_game(scene);
+
+ /* XXX, for 2.8 testing & development its useful to have non Cycles/BI engines use material nodes
+ * In the future we may have some way to check this which each engine can define.
+ * For now use material slots for Clay/Eevee.
+ * - Campbell */
+ if (!(use_nodes || is_bi)) {
+ is_bi = true;
+ }
if (!ma)
return;
@@ -1726,6 +1686,7 @@ void copy_matcopybuf(Material *ma)
matcopybuf.nodetree = ntreeCopyTree_ex(ma->nodetree, G.main, false);
matcopybuf.preview = NULL;
BLI_listbase_clear(&matcopybuf.gpumaterial);
+ /* TODO Duplicate Engine Settings and set runtime to NULL */
matcopied = 1;
}
@@ -1781,501 +1742,40 @@ void paste_matcopybuf(Material *ma)
ma->nodetree = ntreeCopyTree_ex(matcopybuf.nodetree, G.main, false);
}
-
-/*********************** texface to material convert functions **********************/
-/* encode all the TF information into a single int */
-static int encode_tfaceflag(MTFace *tf, int convertall)
+struct Image *BKE_object_material_edit_image_get(Object *ob, short mat_nr)
{
- /* calculate the flag */
- int flag = tf->mode;
-
- /* options that change the material offline render */
- if (!convertall) {
- flag &= ~TF_OBCOL;
- }
-
- /* clean flags that are not being converted */
- flag &= ~TF_TEX;
- flag &= ~TF_SHAREDVERT;
- flag &= ~TF_SHAREDCOL;
- flag &= ~TF_CONVERTED;
-
- /* light tface flag is ignored in GLSL mode */
- flag &= ~TF_LIGHT;
-
- /* 15 is how big the flag can be - hardcoded here and in decode_tfaceflag() */
- flag |= tf->transp << 15;
-
- /* increase 1 so flag 0 is different than no flag yet */
- return flag + 1;
+ Material *ma = give_current_material(ob, mat_nr + 1);
+ return ma ? ma->edit_image : NULL;
}
-/* set the material options based in the tface flag */
-static void decode_tfaceflag(Material *ma, int flag, int convertall)
+struct Image **BKE_object_material_edit_image_get_array(Object *ob)
{
- int alphablend;
- GameSettings *game = &ma->game;
-
- /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */
- flag -= 1;
-
- alphablend = flag >> 15; /* encoded in the encode_tfaceflag function */
- (*game).flag = 0;
-
- /* General Material Options */
- if ((flag & TF_DYNAMIC) == 0) (*game).flag |= GEMAT_NOPHYSICS;
-
- /* Material Offline Rendering Properties */
- if (convertall) {
- if (flag & TF_OBCOL) ma->shade_flag |= MA_OBCOLOR;
+ Image **image_array = MEM_mallocN(sizeof(Material *) * ob->totcol, __func__);
+ for (int i = 0; i < ob->totcol; i++) {
+ image_array[i] = BKE_object_material_edit_image_get(ob, i);
}
-
- /* Special Face Properties */
- if ((flag & TF_TWOSIDE) == 0) (*game).flag |= GEMAT_BACKCULL;
- if (flag & TF_INVISIBLE) (*game).flag |= GEMAT_INVISIBLE;
- if (flag & TF_BMFONT) (*game).flag |= GEMAT_TEXT;
-
- /* Face Orientation */
- if (flag & TF_BILLBOARD) (*game).face_orientation |= GEMAT_HALO;
- else if (flag & TF_BILLBOARD2) (*game).face_orientation |= GEMAT_BILLBOARD;
- else if (flag & TF_SHADOW) (*game).face_orientation |= GEMAT_SHADOW;
-
- /* Alpha Blend */
- if (flag & TF_ALPHASORT && ELEM(alphablend, TF_ALPHA, TF_ADD)) (*game).alpha_blend = GEMAT_ALPHA_SORT;
- else if (alphablend & TF_ALPHA) (*game).alpha_blend = GEMAT_ALPHA;
- else if (alphablend & TF_ADD) (*game).alpha_blend = GEMAT_ADD;
- else if (alphablend & TF_CLIP) (*game).alpha_blend = GEMAT_CLIP;
-}
-
-/* boolean check to see if the mesh needs a material */
-static int check_tfaceneedmaterial(int flag)
-{
- /* check if the flags we have are not deprecated != than default material options
- * also if only flags are visible and collision see if all objects using this mesh have this option in physics */
-
- /* flag is shifted in 1 to make 0 != no flag yet (see encode_tfaceflag) */
- flag -= 1;
-
- /* deprecated flags */
- flag &= ~TF_OBCOL;
- flag &= ~TF_SHAREDVERT;
- flag &= ~TF_SHAREDCOL;
-
- /* light tface flag is ignored in GLSL mode */
- flag &= ~TF_LIGHT;
-
- /* automatic detected if tex image has alpha */
- flag &= ~(TF_ALPHA << 15);
- /* automatic detected if using texture */
- flag &= ~TF_TEX;
-
- /* settings for the default NoMaterial */
- if (flag == TF_DYNAMIC)
- return 0;
-
- else
- return 1;
-}
-
-/* return number of digits of an integer */
-/* XXX to be optmized or replaced by an equivalent blender internal function */
-static int integer_getdigits(int number)
-{
- int i = 0;
- if (number == 0) return 1;
-
- while (number != 0) {
- number = (int)(number / 10);
- i++;
- }
- return i;
-}
-
-static void calculate_tface_materialname(char *matname, char *newname, int flag)
-{
- /* if flag has only light and collision and material matches those values
- * you can do strcpy(name, mat_name);
- * otherwise do: */
- int digits = integer_getdigits(flag);
- /* clamp the old name, remove the MA prefix and add the .TF.flag suffix
- * e.g. matname = "MALoooooooooooooongName"; newname = "Loooooooooooooon.TF.2" */
- BLI_snprintf(newname, MAX_ID_NAME, "%.*s.TF.%0*d", MAX_ID_NAME - (digits + 5), matname, digits, flag);
-}
-
-/* returns -1 if no match */
-static short mesh_getmaterialnumber(Mesh *me, Material *ma)
-{
- short a;
-
- for (a = 0; a < me->totcol; a++) {
- if (me->mat[a] == ma) {
- return a;
- }
- }
-
- return -1;
-}
-
-/* append material */
-static short mesh_addmaterial(Mesh *me, Material *ma)
-{
- BKE_material_append_id(G.main, &me->id, NULL);
- me->mat[me->totcol - 1] = ma;
-
- id_us_plus(&ma->id);
-
- return me->totcol - 1;
+ return image_array;
}
-static void set_facetexture_flags(Material *ma, Image *image)
+bool BKE_object_material_edit_image_set(Object *ob, short mat_nr, Image *image)
{
- if (image) {
- ma->mode |= MA_FACETEXTURE;
- /* we could check if the texture has alpha, but then more meshes sharing the same
- * material may need it. Let's make it simple. */
- if (BKE_image_has_alpha(image))
- ma->mode |= MA_FACETEXTURE_ALPHA;
- }
-}
-
-/* returns material number */
-static short convert_tfacenomaterial(Main *main, Mesh *me, MTFace *tf, int flag)
-{
- Material *ma;
- char idname[MAX_ID_NAME];
- short mat_nr = -1;
-
- /* new material, the name uses the flag*/
- BLI_snprintf(idname, sizeof(idname), "MAMaterial.TF.%0*d", integer_getdigits(flag), flag);
-
- if ((ma = BLI_findstring(&main->mat, idname + 2, offsetof(ID, name) + 2))) {
- mat_nr = mesh_getmaterialnumber(me, ma);
- /* assign the material to the mesh */
- if (mat_nr == -1) mat_nr = mesh_addmaterial(me, ma);
-
- /* if needed set "Face Textures [Alpha]" Material options */
- set_facetexture_flags(ma, tf->tpage);
- }
- /* create a new material */
- else {
- ma = BKE_material_add(main, idname + 2);
-
- if (ma) {
- printf("TexFace Convert: Material \"%s\" created.\n", idname + 2);
- mat_nr = mesh_addmaterial(me, ma);
-
- /* if needed set "Face Textures [Alpha]" Material options */
- set_facetexture_flags(ma, tf->tpage);
-
- decode_tfaceflag(ma, flag, 1);
- /* the final decoding will happen after, outside the main loop
- * for now store the flag into the material and change light/tex/collision
- * store the flag as a negative number */
- ma->game.flag = -flag;
- id_us_min((ID *)ma);
- }
- else {
- printf("Error: Unable to create Material \"%s\" for Mesh \"%s\".", idname + 2, me->id.name + 2);
- }
- }
-
- /* set as converted, no need to go bad to this face */
- tf->mode |= TF_CONVERTED;
- return mat_nr;
-}
-
-/* Function to fully convert materials */
-static void convert_tfacematerial(Main *main, Material *ma)
-{
- Mesh *me;
- Material *mat_new;
- MFace *mf;
- MTFace *tf;
- int flag, index;
- int a;
- short mat_nr;
- CustomDataLayer *cdl;
- char idname[MAX_ID_NAME];
-
- for (me = main->mesh.first; me; me = me->id.next) {
- /* check if this mesh uses this material */
- for (a = 0; a < me->totcol; a++)
- if (me->mat[a] == ma) break;
-
- /* no material found */
- if (a == me->totcol) continue;
-
- /* get the active tface layer */
- index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
- cdl = (index == -1) ? NULL : &me->fdata.layers[index];
- if (!cdl) continue;
-
- /* loop over all the faces and stop at the ones that use the material*/
- for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
- if (me->mat[mf->mat_nr] != ma) continue;
-
- /* texface data for this face */
- tf = ((MTFace *)cdl->data) + a;
- flag = encode_tfaceflag(tf, 1);
-
- /* the name of the new material */
- calculate_tface_materialname(ma->id.name, (char *)&idname, flag);
-
- if ((mat_new = BLI_findstring(&main->mat, idname + 2, offsetof(ID, name) + 2))) {
- /* material already existent, see if the mesh has it */
- mat_nr = mesh_getmaterialnumber(me, mat_new);
- /* material is not in the mesh, add it */
- if (mat_nr == -1) mat_nr = mesh_addmaterial(me, mat_new);
- }
- /* create a new material */
- else {
- mat_new = BKE_material_copy(main, ma);
- if (mat_new) {
- /* rename the material*/
- BLI_strncpy(mat_new->id.name, idname, sizeof(mat_new->id.name));
- id_us_min((ID *)mat_new);
-
- mat_nr = mesh_addmaterial(me, mat_new);
- decode_tfaceflag(mat_new, flag, 1);
- }
- else {
- printf("Error: Unable to create Material \"%s\" for Mesh \"%s.", idname + 2, me->id.name + 2);
- mat_nr = mf->mat_nr;
- continue;
- }
- }
-
- /* if the material has a texture but no texture channel
- * set "Face Textures [Alpha]" Material options
- * actually we need to run it always, because of old behavior
- * of using face texture if any texture channel was present (multitex) */
- //if ((!mat_new->mtex[0]) && (!mat_new->mtex[0]->tex))
- set_facetexture_flags(mat_new, tf->tpage);
-
- /* set the material number to the face*/
- mf->mat_nr = mat_nr;
- }
- /* remove material from mesh */
- for (a = 0; a < me->totcol; ) {
- if (me->mat[a] == ma) {
- BKE_material_pop_id(main, &me->id, a, true);
- }
- else {
- a++;
- }
- }
+ Material *ma = give_current_material(ob, mat_nr + 1);
+ if (ma) {
+ /* both may be NULL */
+ id_us_min((ID *)ma->edit_image);
+ ma->edit_image = image;
+ id_us_plus((ID *)ma->edit_image);
+ return true;
}
+ return false;
}
-
-#define MAT_BGE_DISPUTED -99999
-
-int do_version_tface(Main *main)
+void BKE_material_eval(const struct EvaluationContext *UNUSED(eval_ctx), Material *material)
{
- Mesh *me;
- Material *ma;
- MFace *mf;
- MTFace *tf;
- CustomDataLayer *cdl;
- int a;
- int flag;
- int index;
-
- /* Operator in help menu has been removed for 2.7x */
- int fileload = 1;
-
- /* sometimes mesh has no materials but will need a new one. In those
- * cases we need to ignore the mf->mat_nr and only look at the face
- * mode because it can be zero as uninitialized or the 1st created material
- */
- int nomaterialslots;
-
- /* alert to user to check the console */
- int nowarning = 1;
-
- /* mark all the materials to conversion with a flag
- * if there is tface create a complete flag for that storing in flag
- * if there is tface and flag > 0: creates a new flag based on this face
- * if flags are different set flag to -1
- */
-
- /* 1st part: marking mesh materials to update */
- for (me = main->mesh.first; me; me = me->id.next) {
- if (ID_IS_LINKED(me)) continue;
-
- /* get the active tface layer */
- index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
- cdl = (index == -1) ? NULL : &me->fdata.layers[index];
- if (!cdl) continue;
-
- nomaterialslots = (me->totcol == 0 ? 1 : 0);
-
- /* loop over all the faces*/
- for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
- /* texface data for this face */
- tf = ((MTFace *)cdl->data) + a;
-
- /* conversion should happen only once */
- if (fileload)
- tf->mode &= ~TF_CONVERTED;
- else {
- if ((tf->mode & TF_CONVERTED)) continue;
- else tf->mode |= TF_CONVERTED;
- }
-
- /* no material slots */
- if (nomaterialslots) {
- flag = encode_tfaceflag(tf, 1);
-
- /* create/find a new material and assign to the face */
- if (check_tfaceneedmaterial(flag)) {
- mf->mat_nr = convert_tfacenomaterial(main, me, tf, flag);
- }
- /* else mark them as no-material to be reverted to 0 later */
- else {
- mf->mat_nr = -1;
- }
- }
- else if (mf->mat_nr < me->totcol) {
- ma = me->mat[mf->mat_nr];
-
- /* no material create one if necessary */
- if (!ma) {
- /* find a new material and assign to the face */
- flag = encode_tfaceflag(tf, 1);
-
- /* create/find a new material and assign to the face */
- if (check_tfaceneedmaterial(flag))
- mf->mat_nr = convert_tfacenomaterial(main, me, tf, flag);
-
- continue;
- }
-
- /* we can't read from this if it comes from a library,
- * at doversion time: direct_link might not have happened on it,
- * so ma->mtex is not pointing to valid memory yet.
- * later we could, but it's better not */
- else if (ID_IS_LINKED(ma))
- continue;
-
- /* material already marked as disputed */
- else if (ma->game.flag == MAT_BGE_DISPUTED)
- continue;
-
- /* found a material */
- else {
- flag = encode_tfaceflag(tf, ((fileload) ? 0 : 1));
-
- /* first time changing this material */
- if (ma->game.flag == 0)
- ma->game.flag = -flag;
-
- /* mark material as disputed */
- else if (ma->game.flag != -flag) {
- ma->game.flag = MAT_BGE_DISPUTED;
- continue;
- }
-
- /* material ok so far */
- else {
- ma->game.flag = -flag;
-
- /* some people uses multitexture with TexFace by creating a texture
- * channel which not necessarily the tf->tpage image. But the game engine
- * was enabling it. Now it's required to set "Face Texture [Alpha] in the
- * material settings. */
- if (!fileload)
- set_facetexture_flags(ma, tf->tpage);
- }
- }
- }
- else {
- continue;
- }
- }
-
- /* if we didn't have material slot and now we do, we need to
- * make sure the materials are correct */
- if (nomaterialslots) {
- if (me->totcol > 0) {
- for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
- if (mf->mat_nr == -1) {
- /* texface data for this face */
- tf = ((MTFace *)cdl->data) + a;
- mf->mat_nr = convert_tfacenomaterial(main, me, tf, encode_tfaceflag(tf, 1));
- }
- }
- }
- else {
- for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
- mf->mat_nr = 0;
- }
- }
- }
-
+ if (G.debug & G_DEBUG_DEPSGRAPH) {
+ printf("%s on %s (%p)\n", __func__, material->id.name, material);
}
-
- /* 2nd part - conversion */
- /* skip library files */
-
- /* we shouldn't loop through the materials created in the loop. make the loop stop at its original length) */
- for (ma = main->mat.first, a = 0; ma; ma = ma->id.next, a++) {
- if (ID_IS_LINKED(ma)) continue;
-
- /* disputed material */
- if (ma->game.flag == MAT_BGE_DISPUTED) {
- ma->game.flag = 0;
- if (fileload) {
- printf("Warning: material \"%s\" skipped.\n", ma->id.name + 2);
- nowarning = 0;
- }
- else {
- convert_tfacematerial(main, ma);
- }
- continue;
- }
-
- /* no conflicts in this material - 90% of cases
- * convert from tface system to material */
- else if (ma->game.flag < 0) {
- decode_tfaceflag(ma, -(ma->game.flag), 1);
-
- /* material is good make sure all faces using
- * this material are set to converted */
- if (fileload) {
- for (me = main->mesh.first; me; me = me->id.next) {
- /* check if this mesh uses this material */
- for (a = 0; a < me->totcol; a++)
- if (me->mat[a] == ma) break;
-
- /* no material found */
- if (a == me->totcol) continue;
-
- /* get the active tface layer */
- index = CustomData_get_active_layer_index(&me->fdata, CD_MTFACE);
- cdl = (index == -1) ? NULL : &me->fdata.layers[index];
- if (!cdl) continue;
-
- /* loop over all the faces and stop at the ones that use the material*/
- for (a = 0, mf = me->mface; a < me->totface; a++, mf++) {
- if (me->mat[mf->mat_nr] == ma) {
- /* texface data for this face */
- tf = ((MTFace *)cdl->data) + a;
- tf->mode |= TF_CONVERTED;
- }
- }
- }
- }
- }
- /* material is not used by faces with texface
- * set the default flag - do it only once */
- else {
- if (fileload) {
- ma->game.flag = GEMAT_BACKCULL;
- }
- }
+ if ((BLI_listbase_is_empty(&material->gpumaterial) == false)) {
+ GPU_material_uniform_buffer_tag_dirty(&material->gpumaterial);
}
-
- return nowarning;
}
-
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index dfc49c996b1..5a0ac86823f 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -57,7 +57,6 @@
#include "BKE_animsys.h"
#include "BKE_curve.h"
-#include "BKE_depsgraph.h"
#include "BKE_scene.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
@@ -67,6 +66,8 @@
#include "BKE_object.h"
#include "BKE_material.h"
+//#include "DEG_depsgraph.h"
+
/* Functions */
/** Free (or release) any data used by this mball (does not free the mball itself). */
@@ -74,6 +75,8 @@ void BKE_mball_free(MetaBall *mb)
{
BKE_animdata_free((ID *)mb, false);
+ BKE_mball_batch_cache_free(mb);
+
MEM_SAFE_FREE(mb->mat);
BLI_freelistN(&mb->elems);
@@ -119,6 +122,7 @@ void BKE_mball_copy_data(Main *UNUSED(bmain), MetaBall *mb_dst, const MetaBall *
mb_dst->editelems = NULL;
mb_dst->lastelem = NULL;
+ mb_dst->batch_cache = NULL;
}
MetaBall *BKE_mball_copy(Main *bmain, const MetaBall *mb)
@@ -325,7 +329,7 @@ void BKE_mball_properties_copy(Scene *scene, Object *active_object)
int basisnr, obnr;
char basisname[MAX_ID_NAME], obname[MAX_ID_NAME];
SceneBaseIter iter;
- EvaluationContext *eval_ctx = G.main->eval_ctx;
+ struct EvaluationContext *eval_ctx = G.main->eval_ctx;
BLI_split_name_num(basisname, &basisnr, active_object->id.name + 2, '.');
@@ -362,27 +366,25 @@ void BKE_mball_properties_copy(Scene *scene, Object *active_object)
*/
Object *BKE_mball_basis_find(Scene *scene, Object *basis)
{
- Scene *sce_iter = scene;
- Base *base;
- Object *ob, *bob = basis;
+ Object *bob = basis;
int basisnr, obnr;
char basisname[MAX_ID_NAME], obname[MAX_ID_NAME];
- SceneBaseIter iter;
- EvaluationContext *eval_ctx = G.main->eval_ctx;
BLI_split_name_num(basisname, &basisnr, basis->id.name + 2, '.');
- BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 0, NULL, NULL);
- while (BKE_scene_base_iter_next(eval_ctx, &iter, &sce_iter, 1, &base, &ob)) {
- if ((ob->type == OB_MBALL) && !(base->flag & OB_FROMDUPLI)) {
- if (ob != bob) {
- BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
-
- /* object ob has to be in same "group" ... it means, that it has to have same base of its name */
- if (STREQ(obname, basisname)) {
- if (obnr < basisnr) {
- basis = ob;
- basisnr = obnr;
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ Object *ob = base->object;
+ if ((ob->type == OB_MBALL) && !(base->flag & OB_FROMDUPLI)) {
+ if (ob != bob) {
+ BLI_split_name_num(obname, &obnr, ob->id.name + 2, '.');
+
+ /* object ob has to be in same "group" ... it means, that it has to have same base of its name */
+ if (STREQ(obname, basisname)) {
+ if (obnr < basisnr) {
+ basis = ob;
+ basisnr = obnr;
+ }
}
}
}
@@ -539,7 +541,51 @@ void BKE_mball_select_swap(struct MetaBall *mb)
/* **** Depsgraph evaluation **** */
-void BKE_mball_eval_geometry(EvaluationContext *UNUSED(eval_ctx),
+void BKE_mball_eval_geometry(const struct EvaluationContext *UNUSED(eval_ctx),
MetaBall *UNUSED(mball))
{
}
+
+/* Draw Engine */
+
+/* use for draw-manager only. */
+void BKE_mball_element_calc_display_m3x4(float r_scale_xform[3][4],
+ const float obmat[4][4],
+ const float local_pos[3])
+{
+ float world_pos[3], scamat[3][3];
+ mul_v3_m4v3(world_pos, obmat, local_pos);
+ copy_m3_m4(scamat, obmat);
+ {
+ /* Get the normalized inverse matrix to extract only
+ * the scale of Scamat */
+ float iscamat[3][3];
+ invert_m3_m3(iscamat, scamat);
+ normalize_m3(iscamat);
+ mul_m3_m3_post(scamat, iscamat);
+ }
+
+ copy_v3_v3(r_scale_xform[0], scamat[0]);
+ copy_v3_v3(r_scale_xform[1], scamat[1]);
+ copy_v3_v3(r_scale_xform[2], scamat[2]);
+
+ r_scale_xform[0][3] = world_pos[0];
+ r_scale_xform[1][3] = world_pos[1];
+ r_scale_xform[2][3] = world_pos[2];
+}
+
+void (*BKE_mball_batch_cache_dirty_cb)(MetaBall *mb, int mode) = NULL;
+void (*BKE_mball_batch_cache_free_cb)(MetaBall *mb) = NULL;
+
+void BKE_mball_batch_cache_dirty(MetaBall *mb, int mode)
+{
+ if (mb->batch_cache) {
+ BKE_mball_batch_cache_dirty_cb(mb, mode);
+ }
+}
+void BKE_mball_batch_cache_free(MetaBall *mb)
+{
+ if (mb->batch_cache) {
+ BKE_mball_batch_cache_free_cb(mb);
+ }
+}
diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c
index a1ae3a7f572..5e63b5c1607 100644
--- a/source/blender/blenkernel/intern/mball_tessellate.c
+++ b/source/blender/blenkernel/intern/mball_tessellate.c
@@ -48,11 +48,12 @@
#include "BKE_global.h"
-#include "BKE_depsgraph.h"
#include "BKE_scene.h"
#include "BKE_displist.h"
#include "BKE_mball_tessellate.h" /* own include */
+#include "DEG_depsgraph.h"
+
#include "BLI_strict_flags.h"
/* experimental (faster) normal calculation */
@@ -1055,7 +1056,7 @@ static void polygonize(PROCESS *process)
* Iterates over ALL objects in the scene and all of its sets, including
* making all duplis(not only metas). Copies metas to mainb array.
* Computes bounding boxes for building BVH. */
-static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *ob)
+static void init_meta(const EvaluationContext *eval_ctx, PROCESS *process, Scene *scene, Object *ob)
{
Scene *sce_iter = scene;
Base *base;
@@ -1080,7 +1081,7 @@ static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scen
zero_size = 0;
ml = NULL;
- if (bob == ob && (base->flag & OB_FROMDUPLI) == 0) {
+ if (bob == ob && (base->flag_legacy & OB_FROMDUPLI) == 0) {
mb = ob->data;
if (mb->editelems) ml = mb->editelems->first;
@@ -1232,7 +1233,7 @@ static void init_meta(EvaluationContext *eval_ctx, PROCESS *process, Scene *scen
}
}
-void BKE_mball_polygonize(EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase)
+void BKE_mball_polygonize(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ListBase *dispbase)
{
MetaBall *mb;
DispList *dl;
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index bf937267b83..3217c234718 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -59,7 +59,6 @@
#include "BKE_multires.h"
#include "BKE_key.h"
#include "BKE_mball.h"
-#include "BKE_depsgraph.h"
/* these 2 are only used by conversion functions */
#include "BKE_curve.h"
/* -- */
@@ -127,7 +126,7 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2
for (i = 0; i < c1->totlayer; i++) {
if (ELEM(c1->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY,
- CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT))
{
i1++;
}
@@ -135,7 +134,7 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2
for (i = 0; i < c2->totlayer; i++) {
if (ELEM(c2->layers[i].type, CD_MVERT, CD_MEDGE, CD_MPOLY,
- CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT))
{
i2++;
}
@@ -149,14 +148,14 @@ static int customdata_compare(CustomData *c1, CustomData *c2, Mesh *m1, Mesh *m2
i1 = 0; i2 = 0;
for (i = 0; i < tot; i++) {
while (i1 < c1->totlayer && !ELEM(l1->type, CD_MVERT, CD_MEDGE, CD_MPOLY,
- CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT))
{
i1++;
l1++;
}
while (i2 < c2->totlayer && !ELEM(l2->type, CD_MVERT, CD_MEDGE, CD_MPOLY,
- CD_MLOOPUV, CD_MLOOPCOL, CD_MTEXPOLY, CD_MDEFORMVERT))
+ CD_MLOOPUV, CD_MLOOPCOL, CD_MDEFORMVERT))
{
i2++;
l2++;
@@ -324,7 +323,7 @@ static void mesh_ensure_tessellation_customdata(Mesh *me)
* Callers could also check but safer to do here - campbell */
}
else {
- const int tottex_original = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY);
+ const int tottex_original = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
const int totcol_original = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
const int tottex_tessface = CustomData_number_of_layers(&me->fdata, CD_MTFACE);
@@ -335,7 +334,7 @@ static void mesh_ensure_tessellation_customdata(Mesh *me)
{
BKE_mesh_tessface_clear(me);
- CustomData_from_bmeshpoly(&me->fdata, &me->pdata, &me->ldata, me->totface);
+ CustomData_from_bmeshpoly(&me->fdata, &me->ldata, me->totface);
/* TODO - add some --debug-mesh option */
if (G.debug & G_DEBUG) {
@@ -344,7 +343,7 @@ static void mesh_ensure_tessellation_customdata(Mesh *me)
* and check if there was any data to begin with, for now just print the warning with
* some info to help troubleshoot whats going on - campbell */
printf("%s: warning! Tessellation uvs or vcol data got out of sync, "
- "had to reset!\n CD_MTFACE: %d != CD_MTEXPOLY: %d || CD_MCOL: %d != CD_MLOOPCOL: %d\n",
+ "had to reset!\n CD_MTFACE: %d != CD_MLOOPUV: %d || CD_MCOL: %d != CD_MLOOPCOL: %d\n",
__func__, tottex_tessface, tottex_original, totcol_tessface, totcol_original);
}
}
@@ -388,6 +387,48 @@ void BKE_mesh_ensure_skin_customdata(Mesh *me)
}
}
+bool BKE_mesh_ensure_facemap_customdata(struct Mesh *me)
+{
+ BMesh *bm = me->edit_btmesh ? me->edit_btmesh->bm : NULL;
+ bool changed = false;
+ if (bm) {
+ if (!CustomData_has_layer(&bm->pdata, CD_FACEMAP)) {
+ BM_data_layer_add(bm, &bm->pdata, CD_FACEMAP);
+ changed = true;
+ }
+ }
+ else {
+ if (!CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
+ CustomData_add_layer(&me->pdata,
+ CD_FACEMAP,
+ CD_DEFAULT,
+ NULL,
+ me->totpoly);
+ changed = true;
+ }
+ }
+ return changed;
+}
+
+bool BKE_mesh_clear_facemap_customdata(struct Mesh *me)
+{
+ BMesh *bm = me->edit_btmesh ? me->edit_btmesh->bm : NULL;
+ bool changed = false;
+ if (bm) {
+ if (CustomData_has_layer(&bm->pdata, CD_FACEMAP)) {
+ BM_data_layer_free(bm, &bm->pdata, CD_FACEMAP);
+ changed = true;
+ }
+ }
+ else {
+ if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
+ CustomData_free_layers(&me->pdata, CD_FACEMAP, me->totpoly);
+ changed = true;
+ }
+ }
+ return changed;
+}
+
/* this ensures grouped customdata (e.g. mtexpoly and mloopuv and mtface, or
* mloopcol and mcol) have the same relative active/render/clone/mask indices.
*
@@ -396,14 +437,11 @@ void BKE_mesh_ensure_skin_customdata(Mesh *me)
* versions of the mesh. - campbell*/
static void mesh_update_linked_customdata(Mesh *me, const bool do_ensure_tess_cd)
{
- if (me->edit_btmesh)
- BKE_editmesh_update_linked_customdata(me->edit_btmesh);
-
if (do_ensure_tess_cd) {
mesh_ensure_tessellation_customdata(me);
}
- CustomData_bmesh_update_active_layers(&me->fdata, &me->pdata, &me->ldata);
+ CustomData_bmesh_update_active_layers(&me->fdata, &me->ldata);
}
void BKE_mesh_update_customdata_pointers(Mesh *me, const bool do_ensure_tess_cd)
@@ -422,7 +460,6 @@ void BKE_mesh_update_customdata_pointers(Mesh *me, const bool do_ensure_tess_cd)
me->mpoly = CustomData_get_layer(&me->pdata, CD_MPOLY);
me->mloop = CustomData_get_layer(&me->ldata, CD_MLOOP);
- me->mtpoly = CustomData_get_layer(&me->pdata, CD_MTEXPOLY);
me->mloopcol = CustomData_get_layer(&me->ldata, CD_MLOOPCOL);
me->mloopuv = CustomData_get_layer(&me->ldata, CD_MLOOPUV);
}
@@ -442,6 +479,8 @@ void BKE_mesh_free(Mesh *me)
{
BKE_animdata_free(&me->id, false);
+ BKE_mesh_batch_cache_free(me);
+
CustomData_free(&me->vdata, me->totvert);
CustomData_free(&me->edata, me->totedge);
CustomData_free(&me->fdata, me->totface);
@@ -529,6 +568,7 @@ void BKE_mesh_copy_data(Main *bmain, Mesh *me_dst, const Mesh *me_src, const int
BKE_mesh_update_customdata_pointers(me_dst, do_tessface);
me_dst->edit_btmesh = NULL;
+ me_dst->batch_cache = NULL;
me_dst->mselect = MEM_dupallocN(me_dst->mselect);
me_dst->bb = MEM_dupallocN(me_dst->bb);
@@ -586,33 +626,44 @@ bool BKE_mesh_uv_cdlayer_rename_index(Mesh *me, const int poly_index, const int
ldata = &me->ldata;
fdata = &me->fdata;
}
- cdlp = &pdata->layers[poly_index];
+
cdlu = &ldata->layers[loop_index];
- cdlf = fdata && do_tessface ? &fdata->layers[face_index] : NULL;
+ cdlp = (poly_index != -1) ? &pdata->layers[poly_index] : NULL;
+ cdlf = (face_index != -1) && fdata && do_tessface ? &fdata->layers[face_index] : NULL;
- if (cdlp->name != new_name) {
+ if (cdlu->name != new_name) {
/* Mesh validate passes a name from the CD layer as the new name,
* Avoid memcpy from self to self in this case.
*/
- BLI_strncpy(cdlp->name, new_name, sizeof(cdlp->name));
- CustomData_set_layer_unique_name(pdata, cdlp - pdata->layers);
+ BLI_strncpy(cdlu->name, new_name, sizeof(cdlu->name));
+ CustomData_set_layer_unique_name(ldata, loop_index);
+ }
+
+ if (cdlp == NULL && cdlf == NULL) {
+ return false;
}
/* Loop until we do have exactly the same name for all layers! */
- for (i = 1; !STREQ(cdlp->name, cdlu->name) || (cdlf && !STREQ(cdlp->name, cdlf->name)); i++) {
+ for (i = 1;
+ (cdlp && !STREQ(cdlu->name, cdlp->name)) ||
+ (cdlf && !STREQ(cdlu->name, cdlf->name));
+ i++)
+ {
switch (i % step) {
case 0:
- BLI_strncpy(cdlp->name, cdlu->name, sizeof(cdlp->name));
- CustomData_set_layer_unique_name(pdata, cdlp - pdata->layers);
+ if (cdlp) {
+ BLI_strncpy(cdlp->name, cdlu->name, sizeof(cdlp->name));
+ CustomData_set_layer_unique_name(pdata, poly_index);
+ }
break;
case 1:
BLI_strncpy(cdlu->name, cdlp->name, sizeof(cdlu->name));
- CustomData_set_layer_unique_name(ldata, cdlu - ldata->layers);
+ CustomData_set_layer_unique_name(ldata, loop_index);
break;
case 2:
if (cdlf) {
- BLI_strncpy(cdlf->name, cdlp->name, sizeof(cdlf->name));
- CustomData_set_layer_unique_name(fdata, cdlf - fdata->layers);
+ BLI_strncpy(cdlf->name, cdlu->name, sizeof(cdlf->name));
+ CustomData_set_layer_unique_name(fdata, face_index);
}
break;
}
@@ -623,66 +674,44 @@ bool BKE_mesh_uv_cdlayer_rename_index(Mesh *me, const int poly_index, const int
bool BKE_mesh_uv_cdlayer_rename(Mesh *me, const char *old_name, const char *new_name, bool do_tessface)
{
- CustomData *pdata, *ldata, *fdata;
+ CustomData *ldata, *fdata;
if (me->edit_btmesh) {
- pdata = &me->edit_btmesh->bm->pdata;
ldata = &me->edit_btmesh->bm->ldata;
/* No tessellated data in BMesh! */
fdata = NULL;
do_tessface = false;
}
else {
- pdata = &me->pdata;
ldata = &me->ldata;
fdata = &me->fdata;
do_tessface = (do_tessface && fdata->totlayer);
}
{
- const int pidx_start = CustomData_get_layer_index(pdata, CD_MTEXPOLY);
const int lidx_start = CustomData_get_layer_index(ldata, CD_MLOOPUV);
const int fidx_start = do_tessface ? CustomData_get_layer_index(fdata, CD_MTFACE) : -1;
- int pidx = CustomData_get_named_layer(pdata, CD_MTEXPOLY, old_name);
int lidx = CustomData_get_named_layer(ldata, CD_MLOOPUV, old_name);
int fidx = do_tessface ? CustomData_get_named_layer(fdata, CD_MTFACE, old_name) : -1;
/* None of those cases should happen, in theory!
* Note this assume we have the same number of mtexpoly, mloopuv and mtface layers!
*/
- if (pidx == -1) {
- if (lidx == -1) {
- if (fidx == -1) {
- /* No layer found with this name! */
- return false;
- }
- else {
- lidx = fidx;
- }
- }
- pidx = lidx;
- }
- else {
- if (lidx == -1) {
- lidx = pidx;
+ if (lidx == -1) {
+ if (fidx == -1) {
+ /* No layer found with this name! */
+ return false;
}
- if (fidx == -1 && do_tessface) {
- fidx = pidx;
+ else {
+ lidx = fidx;
}
}
-#if 0
- /* For now, we do not consider mismatch in indices (i.e. same name leading to (relative) different indices). */
- else if (pidx != lidx) {
- lidx = pidx;
- }
-#endif
/* Go back to absolute indices! */
- pidx += pidx_start;
lidx += lidx_start;
if (fidx != -1)
fidx += fidx_start;
- return BKE_mesh_uv_cdlayer_rename_index(me, pidx, lidx, fidx, new_name, do_tessface);
+ return BKE_mesh_uv_cdlayer_rename_index(me, -1, lidx, fidx, new_name, do_tessface);
}
}
@@ -760,6 +789,18 @@ void BKE_mesh_texspace_get(Mesh *me, float r_loc[3], float r_rot[3], float r_siz
if (r_size) copy_v3_v3(r_size, me->size);
}
+void BKE_mesh_texspace_get_reference(Mesh *me, short **r_texflag, float **r_loc, float **r_rot, float **r_size)
+{
+ if (me->bb == NULL || (me->bb->flag & BOUNDBOX_DIRTY)) {
+ BKE_mesh_texspace_calc(me);
+ }
+
+ if (r_texflag != NULL) *r_texflag = &me->texflag;
+ if (r_loc != NULL) *r_loc = me->loc;
+ if (r_rot != NULL) *r_rot = me->rot;
+ if (r_size != NULL) *r_size = me->size;
+}
+
void BKE_mesh_texspace_copy_from_object(Mesh *me, Object *ob)
{
float *texloc, *texrot, *texsize;
@@ -1382,7 +1423,6 @@ void BKE_mesh_from_nurbs_displist(Object *ob, ListBase *dispbase, const bool use
if (alluv) {
const char *uvname = "Orco";
- me->mtpoly = CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, uvname);
me->mloopuv = CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_ASSIGN, alluv, me->totloop, uvname);
}
@@ -1602,10 +1642,10 @@ void BKE_mesh_to_curve_nurblist(DerivedMesh *dm, ListBase *nurblist, const int e
}
}
-void BKE_mesh_to_curve(Scene *scene, Object *ob)
+void BKE_mesh_to_curve(const EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
/* make new mesh data from the original copy */
- DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_MESH);
+ DerivedMesh *dm = mesh_get_derived_final(eval_ctx, scene, ob, CD_MASK_MESH);
ListBase nurblist = {NULL, NULL};
bool needsFree = false;
@@ -2384,7 +2424,7 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals)
/* settings: 1 - preview, 2 - render */
Mesh *BKE_mesh_new_from_object(
- Main *bmain, Scene *sce, Object *ob,
+ const EvaluationContext *eval_ctx, Main *bmain, Scene *sce, Object *ob,
int apply_modifiers, int settings, int calc_tessface, int calc_undeformed)
{
Mesh *tmpmesh;
@@ -2443,7 +2483,7 @@ Mesh *BKE_mesh_new_from_object(
copycu->editnurb = tmpcu->editnurb;
/* get updated display list, and convert to a mesh */
- BKE_displist_make_curveTypes_forRender(sce, tmpobj, &dispbase, &derivedFinal, false, render);
+ BKE_displist_make_curveTypes_forRender(eval_ctx, sce, tmpobj, &dispbase, &derivedFinal, false, render);
copycu->editfont = NULL;
copycu->editnurb = NULL;
@@ -2492,13 +2532,7 @@ Mesh *BKE_mesh_new_from_object(
if (render) {
ListBase disp = {NULL, NULL};
- /* TODO(sergey): This is gonna to work for until EvaluationContext
- * only contains for_render flag. As soon as CoW is
- * implemented, this is to be rethinked.
- */
- EvaluationContext eval_ctx;
- DEG_evaluation_context_init(&eval_ctx, DAG_EVAL_RENDER);
- BKE_displist_make_mball_forRender(&eval_ctx, sce, ob, &disp);
+ BKE_displist_make_mball_forRender(eval_ctx, sce, ob, &disp);
BKE_mesh_from_metaball(&disp, tmpmesh);
BKE_displist_free(&disp);
}
@@ -2537,9 +2571,9 @@ Mesh *BKE_mesh_new_from_object(
/* Write the display mesh into the dummy mesh */
if (render)
- dm = mesh_create_derived_render(sce, ob, mask);
+ dm = mesh_create_derived_render(eval_ctx, sce, ob, mask);
else
- dm = mesh_create_derived_view(sce, ob, mask);
+ dm = mesh_create_derived_view(eval_ctx, sce, ob, mask);
tmpmesh = BKE_mesh_add(bmain, ((ID *)ob->data)->name + 2);
DM_to_mesh(dm, tmpmesh, ob, mask, true);
@@ -2630,7 +2664,7 @@ Mesh *BKE_mesh_new_from_object(
/* **** Depsgraph evaluation **** */
-void BKE_mesh_eval_geometry(EvaluationContext *UNUSED(eval_ctx),
+void BKE_mesh_eval_geometry(const EvaluationContext *UNUSED(eval_ctx),
Mesh *mesh)
{
if (G.debug & G_DEBUG_DEPSGRAPH) {
@@ -2640,3 +2674,20 @@ void BKE_mesh_eval_geometry(EvaluationContext *UNUSED(eval_ctx),
BKE_mesh_texspace_calc(mesh);
}
}
+
+/* Draw Engine */
+void (*BKE_mesh_batch_cache_dirty_cb)(Mesh *me, int mode) = NULL;
+void (*BKE_mesh_batch_cache_free_cb)(Mesh *me) = NULL;
+
+void BKE_mesh_batch_cache_dirty(Mesh *me, int mode)
+{
+ if (me->batch_cache) {
+ BKE_mesh_batch_cache_dirty_cb(me, mode);
+ }
+}
+void BKE_mesh_batch_cache_free(Mesh *me)
+{
+ if (me->batch_cache) {
+ BKE_mesh_batch_cache_free_cb(me);
+ }
+}
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index f95fad38c7c..00d1b29caf8 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -1713,152 +1713,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
* \{ */
@@ -2429,12 +2283,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) */
@@ -2442,17 +2296,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);
@@ -2504,14 +2354,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);
@@ -2521,17 +2371,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);
}
@@ -2854,7 +2701,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
@@ -2875,7 +2722,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.
@@ -3054,7 +2901,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);
@@ -3094,7 +2941,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;
@@ -3116,9 +2963,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 {
@@ -3136,9 +2984,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);
}
@@ -3153,11 +3002,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;
@@ -3168,9 +3017,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++;
@@ -3277,7 +3123,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);
}
@@ -3320,7 +3166,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 */
@@ -3370,7 +3216,7 @@ void BKE_mesh_convert_mfaces_to_mpolys_ex(ID *id, CustomData *fdata, CustomData
# undef ML
- bm_corners_to_loops_ex(id, fdata, ldata, pdata, mface, totloop, i, mp->loopstart, numTex, numCol);
+ bm_corners_to_loops_ex(id, fdata, ldata, mface, totloop, i, mp->loopstart, numTex, numCol);
if (polyindex) {
*polyindex = i;
diff --git a/source/blender/blenkernel/intern/mesh_tangent.c b/source/blender/blenkernel/intern/mesh_tangent.c
new file mode 100644
index 00000000000..77288bd672e
--- /dev/null
+++ b/source/blender/blenkernel/intern/mesh_tangent.c
@@ -0,0 +1,690 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
+ * All rights reserved.
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/mesh_tangent.c
+ * \ingroup bke
+ *
+ * Functions to evaluate mesh tangents.
+ */
+
+#include <limits.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_mesh_types.h"
+#include "DNA_meshdata_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_math.h"
+#include "BLI_stack.h"
+#include "BLI_task.h"
+
+#include "BKE_customdata.h"
+#include "BKE_global.h"
+#include "BKE_mesh.h"
+#include "BKE_mesh_tangent.h"
+#include "BKE_report.h"
+
+#include "BLI_strict_flags.h"
+
+#include "atomic_ops.h"
+#include "mikktspace.h"
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Mesh Tangent Calculations (Single Layer)
+ * \{ */
+
+/* Tangent space utils. */
+
+/* User data. */
+typedef struct {
+ const MPoly *mpolys; /* faces */
+ const MLoop *mloops; /* faces's vertices */
+ const MVert *mverts; /* vertices */
+ const MLoopUV *luvs; /* texture coordinates */
+ float (*lnors)[3]; /* loops' normals */
+ float (*tangents)[4]; /* output tangents */
+ int num_polys; /* number of polygons */
+} BKEMeshToTangent;
+
+/* Mikktspace's API */
+static int get_num_faces(const SMikkTSpaceContext *pContext)
+{
+ BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
+ return p_mesh->num_polys;
+}
+
+static int get_num_verts_of_face(const SMikkTSpaceContext *pContext, const int face_idx)
+{
+ BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
+ return p_mesh->mpolys[face_idx].totloop;
+}
+
+static void get_position(const SMikkTSpaceContext *pContext, float r_co[3], const int face_idx, const int vert_idx)
+{
+ BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
+ const int loop_idx = p_mesh->mpolys[face_idx].loopstart + vert_idx;
+ copy_v3_v3(r_co, p_mesh->mverts[p_mesh->mloops[loop_idx].v].co);
+}
+
+static void get_texture_coordinate(const SMikkTSpaceContext *pContext, float r_uv[2], const int face_idx,
+ const int vert_idx)
+{
+ BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
+ copy_v2_v2(r_uv, p_mesh->luvs[p_mesh->mpolys[face_idx].loopstart + vert_idx].uv);
+}
+
+static void get_normal(const SMikkTSpaceContext *pContext, float r_no[3], const int face_idx, const int vert_idx)
+{
+ BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
+ copy_v3_v3(r_no, p_mesh->lnors[p_mesh->mpolys[face_idx].loopstart + vert_idx]);
+}
+
+static void set_tspace(const SMikkTSpaceContext *pContext, const float fv_tangent[3], const float face_sign,
+ const int face_idx, const int vert_idx)
+{
+ BKEMeshToTangent *p_mesh = (BKEMeshToTangent *)pContext->m_pUserData;
+ float *p_res = p_mesh->tangents[p_mesh->mpolys[face_idx].loopstart + vert_idx];
+ copy_v3_v3(p_res, fv_tangent);
+ p_res[3] = face_sign;
+}
+
+/**
+ * Compute simplified tangent space normals, i.e. tangent vector + sign of bi-tangent one, which combined with
+ * split normals can be used to recreate the full tangent space.
+ * Note: * The mesh should be made of only tris and quads!
+ */
+void BKE_mesh_calc_loop_tangent_single_ex(
+ const MVert *mverts, const int UNUSED(numVerts), const MLoop *mloops,
+ float (*r_looptangent)[4], float (*loopnors)[3], const MLoopUV *loopuvs,
+ const int UNUSED(numLoops), const MPoly *mpolys, const int numPolys,
+ ReportList *reports)
+{
+ BKEMeshToTangent mesh_to_tangent = {NULL};
+ SMikkTSpaceContext s_context = {NULL};
+ SMikkTSpaceInterface s_interface = {NULL};
+
+ const MPoly *mp;
+ int mp_index;
+
+ /* First check we do have a tris/quads only mesh. */
+ for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) {
+ if (mp->totloop > 4) {
+ BKE_report(reports, RPT_ERROR, "Tangent space can only be computed for tris/quads, aborting");
+ return;
+ }
+ }
+
+ /* Compute Mikktspace's tangent normals. */
+ mesh_to_tangent.mpolys = mpolys;
+ mesh_to_tangent.mloops = mloops;
+ mesh_to_tangent.mverts = mverts;
+ mesh_to_tangent.luvs = loopuvs;
+ mesh_to_tangent.lnors = loopnors;
+ mesh_to_tangent.tangents = r_looptangent;
+ mesh_to_tangent.num_polys = numPolys;
+
+ s_context.m_pUserData = &mesh_to_tangent;
+ s_context.m_pInterface = &s_interface;
+ s_interface.m_getNumFaces = get_num_faces;
+ s_interface.m_getNumVerticesOfFace = get_num_verts_of_face;
+ s_interface.m_getPosition = get_position;
+ s_interface.m_getTexCoord = get_texture_coordinate;
+ s_interface.m_getNormal = get_normal;
+ s_interface.m_setTSpaceBasic = set_tspace;
+
+ /* 0 if failed */
+ if (genTangSpaceDefault(&s_context) == false) {
+ BKE_report(reports, RPT_ERROR, "Mikktspace failed to generate tangents for this mesh!");
+ }
+}
+
+/**
+ * Wrapper around BKE_mesh_calc_loop_tangent_single_ex, which takes care of most boiling code.
+ * \note
+ * - There must be a valid loop's CD_NORMALS available.
+ * - The mesh should be made of only tris and quads!
+ */
+void BKE_mesh_calc_loop_tangent_single(Mesh *mesh, const char *uvmap, float (*r_looptangents)[4], ReportList *reports)
+{
+ MLoopUV *loopuvs;
+ float (*loopnors)[3];
+
+ /* Check we have valid texture coordinates first! */
+ if (uvmap) {
+ loopuvs = CustomData_get_layer_named(&mesh->ldata, CD_MLOOPUV, uvmap);
+ }
+ else {
+ loopuvs = CustomData_get_layer(&mesh->ldata, CD_MLOOPUV);
+ }
+ if (!loopuvs) {
+ BKE_reportf(reports, RPT_ERROR, "Tangent space computation needs an UVMap, \"%s\" not found, aborting", uvmap);
+ return;
+ }
+
+ loopnors = CustomData_get_layer(&mesh->ldata, CD_NORMAL);
+ if (!loopnors) {
+ BKE_report(reports, RPT_ERROR, "Tangent space computation needs loop normals, none found, aborting");
+ return;
+ }
+
+ BKE_mesh_calc_loop_tangent_single_ex(mesh->mvert, mesh->totvert, mesh->mloop, r_looptangents,
+ loopnors, loopuvs, mesh->totloop, mesh->mpoly, mesh->totpoly, reports);
+}
+
+/** \} */
+
+
+/* -------------------------------------------------------------------- */
+
+/** \name Mesh Tangent Calculations (All Layers)
+ * \{ */
+
+
+/* Necessary complexity to handle looptri's as quads for correct tangents */
+#define USE_LOOPTRI_DETECT_QUADS
+
+typedef struct {
+ const float (*precomputedFaceNormals)[3];
+ const float (*precomputedLoopNormals)[3];
+ const MLoopTri *looptri;
+ MLoopUV *mloopuv; /* texture coordinates */
+ const MPoly *mpoly; /* indices */
+ const MLoop *mloop; /* indices */
+ const MVert *mvert; /* vertices & normals */
+ const float (*orco)[3];
+ float (*tangent)[4]; /* destination */
+ int numTessFaces;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ /* map from 'fake' face index to looptri,
+ * quads will point to the first looptri of the quad */
+ const int *face_as_quad_map;
+ int num_face_as_quad_map;
+#endif
+
+} SGLSLMeshToTangent;
+
+/* interface */
+static int dm_ts_GetNumFaces(const SMikkTSpaceContext *pContext)
+{
+ SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ return pMesh->num_face_as_quad_map;
+#else
+ return pMesh->numTessFaces;
+#endif
+}
+
+static int dm_ts_GetNumVertsOfFace(const SMikkTSpaceContext *pContext, const int face_num)
+{
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
+ if (pMesh->face_as_quad_map) {
+ const MLoopTri *lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
+ const MPoly *mp = &pMesh->mpoly[lt->poly];
+ if (mp->totloop == 4) {
+ return 4;
+ }
+ }
+ return 3;
+#else
+ UNUSED_VARS(pContext, face_num);
+ return 3;
+#endif
+}
+
+static void dm_ts_GetPosition(
+ const SMikkTSpaceContext *pContext, float r_co[3],
+ const int face_num, const int vert_index)
+{
+ //assert(vert_index >= 0 && vert_index < 4);
+ SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
+ const MLoopTri *lt;
+ uint loop_index;
+ const float *co;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ if (pMesh->face_as_quad_map) {
+ lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
+ const MPoly *mp = &pMesh->mpoly[lt->poly];
+ if (mp->totloop == 4) {
+ loop_index = (uint)(mp->loopstart + vert_index);
+ goto finally;
+ }
+ /* fall through to regular triangle */
+ }
+ else {
+ lt = &pMesh->looptri[face_num];
+ }
+#else
+ lt = &pMesh->looptri[face_num];
+#endif
+ loop_index = lt->tri[vert_index];
+
+finally:
+ co = pMesh->mvert[pMesh->mloop[loop_index].v].co;
+ copy_v3_v3(r_co, co);
+}
+
+static void dm_ts_GetTextureCoordinate(
+ const SMikkTSpaceContext *pContext, float r_uv[2],
+ const int face_num, const int vert_index)
+{
+ //assert(vert_index >= 0 && vert_index < 4);
+ SGLSLMeshToTangent *pMesh = pContext->m_pUserData;
+ const MLoopTri *lt;
+ uint loop_index;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ if (pMesh->face_as_quad_map) {
+ lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
+ const MPoly *mp = &pMesh->mpoly[lt->poly];
+ if (mp->totloop == 4) {
+ loop_index = (uint)(mp->loopstart + vert_index);
+ goto finally;
+ }
+ /* fall through to regular triangle */
+ }
+ else {
+ lt = &pMesh->looptri[face_num];
+ }
+#else
+ lt = &pMesh->looptri[face_num];
+#endif
+ loop_index = lt->tri[vert_index];
+
+finally:
+ if (pMesh->mloopuv != NULL) {
+ const float *uv = pMesh->mloopuv[loop_index].uv;
+ copy_v2_v2(r_uv, uv);
+ }
+ else {
+ const float *orco = pMesh->orco[pMesh->mloop[loop_index].v];
+ map_to_sphere(&r_uv[0], &r_uv[1], orco[0], orco[1], orco[2]);
+ }
+}
+
+static void dm_ts_GetNormal(
+ const SMikkTSpaceContext *pContext, float r_no[3],
+ const int face_num, const int vert_index)
+{
+ //assert(vert_index >= 0 && vert_index < 4);
+ SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
+ const MLoopTri *lt;
+ uint loop_index;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ if (pMesh->face_as_quad_map) {
+ lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
+ const MPoly *mp = &pMesh->mpoly[lt->poly];
+ if (mp->totloop == 4) {
+ loop_index = (uint)(mp->loopstart + vert_index);
+ goto finally;
+ }
+ /* fall through to regular triangle */
+ }
+ else {
+ lt = &pMesh->looptri[face_num];
+ }
+#else
+ lt = &pMesh->looptri[face_num];
+#endif
+ loop_index = lt->tri[vert_index];
+
+finally:
+ if (pMesh->precomputedLoopNormals) {
+ copy_v3_v3(r_no, pMesh->precomputedLoopNormals[loop_index]);
+ }
+ else if ((pMesh->mpoly[lt->poly].flag & ME_SMOOTH) == 0) { /* flat */
+ if (pMesh->precomputedFaceNormals) {
+ copy_v3_v3(r_no, pMesh->precomputedFaceNormals[lt->poly]);
+ }
+ else {
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ const MPoly *mp = &pMesh->mpoly[lt->poly];
+ if (mp->totloop == 4) {
+ normal_quad_v3(
+ r_no,
+ pMesh->mvert[pMesh->mloop[mp->loopstart + 0].v].co,
+ pMesh->mvert[pMesh->mloop[mp->loopstart + 1].v].co,
+ pMesh->mvert[pMesh->mloop[mp->loopstart + 2].v].co,
+ pMesh->mvert[pMesh->mloop[mp->loopstart + 3].v].co);
+ }
+ else
+#endif
+ {
+ normal_tri_v3(
+ r_no,
+ pMesh->mvert[pMesh->mloop[lt->tri[0]].v].co,
+ pMesh->mvert[pMesh->mloop[lt->tri[1]].v].co,
+ pMesh->mvert[pMesh->mloop[lt->tri[2]].v].co);
+ }
+ }
+ }
+ else {
+ const short *no = pMesh->mvert[pMesh->mloop[loop_index].v].no;
+ normal_short_to_float_v3(r_no, no);
+ }
+}
+
+static void dm_ts_SetTSpace(
+ const SMikkTSpaceContext *pContext, const float fvTangent[3], const float fSign,
+ const int face_num, const int vert_index)
+{
+ //assert(vert_index >= 0 && vert_index < 4);
+ SGLSLMeshToTangent *pMesh = (SGLSLMeshToTangent *) pContext->m_pUserData;
+ const MLoopTri *lt;
+ uint loop_index;
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ if (pMesh->face_as_quad_map) {
+ lt = &pMesh->looptri[pMesh->face_as_quad_map[face_num]];
+ const MPoly *mp = &pMesh->mpoly[lt->poly];
+ if (mp->totloop == 4) {
+ loop_index = (uint)(mp->loopstart + vert_index);
+ goto finally;
+ }
+ /* fall through to regular triangle */
+ }
+ else {
+ lt = &pMesh->looptri[face_num];
+ }
+#else
+ lt = &pMesh->looptri[face_num];
+#endif
+ loop_index = lt->tri[vert_index];
+
+ float *pRes;
+
+finally:
+ pRes = pMesh->tangent[loop_index];
+ copy_v3_v3(pRes, fvTangent);
+ pRes[3] = fSign;
+}
+
+static void DM_calc_loop_tangents_thread(TaskPool * __restrict UNUSED(pool), void *taskdata, int UNUSED(threadid))
+{
+ struct SGLSLMeshToTangent *mesh2tangent = taskdata;
+ /* new computation method */
+ {
+ SMikkTSpaceContext sContext = {NULL};
+ SMikkTSpaceInterface sInterface = {NULL};
+
+ sContext.m_pUserData = mesh2tangent;
+ sContext.m_pInterface = &sInterface;
+ sInterface.m_getNumFaces = dm_ts_GetNumFaces;
+ sInterface.m_getNumVerticesOfFace = dm_ts_GetNumVertsOfFace;
+ sInterface.m_getPosition = dm_ts_GetPosition;
+ sInterface.m_getTexCoord = dm_ts_GetTextureCoordinate;
+ sInterface.m_getNormal = dm_ts_GetNormal;
+ sInterface.m_setTSpaceBasic = dm_ts_SetTSpace;
+
+ /* 0 if failed */
+ genTangSpaceDefault(&sContext);
+ }
+}
+
+void BKE_mesh_add_loop_tangent_named_layer_for_uv(
+ CustomData *uv_data, CustomData *tan_data, int numLoopData,
+ const char *layer_name)
+{
+ if (CustomData_get_named_layer_index(tan_data, CD_TANGENT, layer_name) == -1 &&
+ CustomData_get_named_layer_index(uv_data, CD_MLOOPUV, layer_name) != -1)
+ {
+ CustomData_add_layer_named(
+ tan_data, CD_TANGENT, CD_CALLOC, NULL,
+ numLoopData, layer_name);
+ }
+}
+
+/**
+ * Here we get some useful information such as active uv layer name and search if it is already in tangent_names.
+ * Also, we calculate tangent_mask that works as a descriptor of tangents state.
+ * If tangent_mask has changed, then recalculate tangents.
+ */
+void BKE_mesh_calc_loop_tangent_step_0(
+ const CustomData *loopData, bool calc_active_tangent,
+ const char (*tangent_names)[MAX_NAME], int tangent_names_count,
+ bool *rcalc_act, bool *rcalc_ren, int *ract_uv_n, int *rren_uv_n,
+ char *ract_uv_name, char *rren_uv_name, short *rtangent_mask) {
+ /* Active uv in viewport */
+ int layer_index = CustomData_get_layer_index(loopData, CD_MLOOPUV);
+ *ract_uv_n = CustomData_get_active_layer(loopData, CD_MLOOPUV);
+ ract_uv_name[0] = 0;
+ if (*ract_uv_n != -1) {
+ strcpy(ract_uv_name, loopData->layers[*ract_uv_n + layer_index].name);
+ }
+
+ /* Active tangent in render */
+ *rren_uv_n = CustomData_get_render_layer(loopData, CD_MLOOPUV);
+ rren_uv_name[0] = 0;
+ if (*rren_uv_n != -1) {
+ strcpy(rren_uv_name, loopData->layers[*rren_uv_n + layer_index].name);
+ }
+
+ /* If active tangent not in tangent_names we take it into account */
+ *rcalc_act = false;
+ *rcalc_ren = false;
+ for (int i = 0; i < tangent_names_count; i++) {
+ if (tangent_names[i][0] == 0) {
+ calc_active_tangent = true;
+ }
+ }
+ if (calc_active_tangent) {
+ *rcalc_act = true;
+ *rcalc_ren = true;
+ for (int i = 0; i < tangent_names_count; i++) {
+ if (STREQ(ract_uv_name, tangent_names[i]))
+ *rcalc_act = false;
+ if (STREQ(rren_uv_name, tangent_names[i]))
+ *rcalc_ren = false;
+ }
+ }
+ *rtangent_mask = 0;
+
+ const int uv_layer_num = CustomData_number_of_layers(loopData, CD_MLOOPUV);
+ for (int n = 0; n < uv_layer_num; n++) {
+ const char *name = CustomData_get_layer_name(loopData, CD_MLOOPUV, n);
+ bool add = false;
+ for (int i = 0; i < tangent_names_count; i++) {
+ if (tangent_names[i][0] && STREQ(tangent_names[i], name)) {
+ add = true;
+ break;
+ }
+ }
+ if (!add && ((*rcalc_act && ract_uv_name[0] && STREQ(ract_uv_name, name)) ||
+ (*rcalc_ren && rren_uv_name[0] && STREQ(rren_uv_name, name))))
+ {
+ add = true;
+ }
+ if (add)
+ *rtangent_mask |= (short)(1 << n);
+ }
+
+ if (uv_layer_num == 0)
+ *rtangent_mask |= DM_TANGENT_MASK_ORCO;
+}
+
+/**
+ * See: #BKE_editmesh_loop_tangent_calc (matching logic).
+ */
+void BKE_mesh_calc_loop_tangent_ex(
+ const MVert *mvert,
+ const MPoly *mpoly, const uint mpoly_len,
+ const MLoop *mloop,
+ const MLoopTri *looptri,
+ const uint looptri_len,
+
+ CustomData *loopdata,
+ bool calc_active_tangent,
+ const char (*tangent_names)[MAX_NAME], int tangent_names_len,
+ const float (*poly_normals)[3],
+ const float (*loop_normals)[3],
+ const float (*vert_orco)[3],
+ /* result */
+ CustomData *loopdata_out,
+ const uint loopdata_out_len,
+ short *tangent_mask_curr_p)
+{
+ int act_uv_n = -1;
+ int ren_uv_n = -1;
+ bool calc_act = false;
+ bool calc_ren = false;
+ char act_uv_name[MAX_NAME];
+ char ren_uv_name[MAX_NAME];
+ short tangent_mask = 0;
+ short tangent_mask_curr = *tangent_mask_curr_p;
+
+ BKE_mesh_calc_loop_tangent_step_0(
+ loopdata, calc_active_tangent, tangent_names, tangent_names_len,
+ &calc_act, &calc_ren, &act_uv_n, &ren_uv_n, act_uv_name, ren_uv_name, &tangent_mask);
+ if ((tangent_mask_curr | tangent_mask) != tangent_mask_curr) {
+ /* Check we have all the needed layers */
+ /* Allocate needed tangent layers */
+ for (int i = 0; i < tangent_names_len; i++)
+ if (tangent_names[i][0])
+ BKE_mesh_add_loop_tangent_named_layer_for_uv(loopdata, loopdata_out, (int)loopdata_out_len, tangent_names[i]);
+ if ((tangent_mask & DM_TANGENT_MASK_ORCO) && CustomData_get_named_layer_index(loopdata, CD_TANGENT, "") == -1)
+ CustomData_add_layer_named(loopdata_out, CD_TANGENT, CD_CALLOC, NULL, (int)loopdata_out_len, "");
+ if (calc_act && act_uv_name[0])
+ BKE_mesh_add_loop_tangent_named_layer_for_uv(loopdata, loopdata_out, (int)loopdata_out_len, act_uv_name);
+ if (calc_ren && ren_uv_name[0])
+ BKE_mesh_add_loop_tangent_named_layer_for_uv(loopdata, loopdata_out, (int)loopdata_out_len, ren_uv_name);
+
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ int num_face_as_quad_map;
+ int *face_as_quad_map = NULL;
+
+ /* map faces to quads */
+ if (looptri_len != mpoly_len) {
+ /* over alloc, since we dont know how many ngon or quads we have */
+
+ /* map fake face index to looptri */
+ face_as_quad_map = MEM_mallocN(sizeof(int) * looptri_len, __func__);
+ int k, j;
+ for (k = 0, j = 0; j < (int)looptri_len; k++, j++) {
+ face_as_quad_map[k] = j;
+ /* step over all quads */
+ if (mpoly[looptri[j].poly].totloop == 4) {
+ j++; /* skips the nest looptri */
+ }
+ }
+ num_face_as_quad_map = k;
+ }
+ else {
+ num_face_as_quad_map = (int)looptri_len;
+ }
+#endif
+
+ /* Calculation */
+ if (looptri_len != 0) {
+ TaskScheduler *scheduler = BLI_task_scheduler_get();
+ TaskPool *task_pool;
+ task_pool = BLI_task_pool_create(scheduler, NULL);
+
+ tangent_mask_curr = 0;
+ /* Calculate tangent layers */
+ SGLSLMeshToTangent data_array[MAX_MTFACE];
+ const int tangent_layer_num = CustomData_number_of_layers(loopdata_out, CD_TANGENT);
+ for (int n = 0; n < tangent_layer_num; n++) {
+ int index = CustomData_get_layer_index_n(loopdata_out, CD_TANGENT, n);
+ BLI_assert(n < MAX_MTFACE);
+ SGLSLMeshToTangent *mesh2tangent = &data_array[n];
+ mesh2tangent->numTessFaces = (int)looptri_len;
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ mesh2tangent->face_as_quad_map = face_as_quad_map;
+ mesh2tangent->num_face_as_quad_map = num_face_as_quad_map;
+#endif
+ mesh2tangent->mvert = mvert;
+ mesh2tangent->mpoly = mpoly;
+ mesh2tangent->mloop = mloop;
+ mesh2tangent->looptri = looptri;
+ /* Note, we assume we do have tessellated loop normals at this point (in case it is object-enabled),
+ * have to check this is valid...
+ */
+ mesh2tangent->precomputedLoopNormals = loop_normals;
+ mesh2tangent->precomputedFaceNormals = poly_normals;
+
+ mesh2tangent->orco = NULL;
+ mesh2tangent->mloopuv = CustomData_get_layer_named(loopdata, CD_MLOOPUV, loopdata_out->layers[index].name);
+
+ /* Fill the resulting tangent_mask */
+ if (!mesh2tangent->mloopuv) {
+ mesh2tangent->orco = vert_orco;
+ if (!mesh2tangent->orco)
+ continue;
+
+ tangent_mask_curr |= DM_TANGENT_MASK_ORCO;
+ }
+ else {
+ int uv_ind = CustomData_get_named_layer_index(loopdata, CD_MLOOPUV, loopdata_out->layers[index].name);
+ int uv_start = CustomData_get_layer_index(loopdata, CD_MLOOPUV);
+ BLI_assert(uv_ind != -1 && uv_start != -1);
+ BLI_assert(uv_ind - uv_start < MAX_MTFACE);
+ tangent_mask_curr |= (short)(1 << (uv_ind - uv_start));
+ }
+
+ mesh2tangent->tangent = loopdata_out->layers[index].data;
+ BLI_task_pool_push(task_pool, DM_calc_loop_tangents_thread, mesh2tangent, false, TASK_PRIORITY_LOW);
+ }
+
+ BLI_assert(tangent_mask_curr == tangent_mask);
+ BLI_task_pool_work_and_wait(task_pool);
+ BLI_task_pool_free(task_pool);
+ }
+ else {
+ tangent_mask_curr = tangent_mask;
+ }
+#ifdef USE_LOOPTRI_DETECT_QUADS
+ if (face_as_quad_map) {
+ MEM_freeN(face_as_quad_map);
+ }
+#undef USE_LOOPTRI_DETECT_QUADS
+
+#endif
+
+ *tangent_mask_curr_p = tangent_mask_curr;
+
+ /* Update active layer index */
+ int act_uv_index = CustomData_get_layer_index_n(loopdata, CD_MLOOPUV, act_uv_n);
+ if (act_uv_index != -1) {
+ int tan_index = CustomData_get_named_layer_index(loopdata, CD_TANGENT, loopdata->layers[act_uv_index].name);
+ CustomData_set_layer_active_index(loopdata, CD_TANGENT, tan_index);
+ }/* else tangent has been built from orco */
+
+ /* Update render layer index */
+ int ren_uv_index = CustomData_get_layer_index_n(loopdata, CD_MLOOPUV, ren_uv_n);
+ if (ren_uv_index != -1) {
+ int tan_index = CustomData_get_named_layer_index(loopdata, CD_TANGENT, loopdata->layers[ren_uv_index].name);
+ CustomData_set_layer_render_index(loopdata, CD_TANGENT, tan_index);
+ }/* else tangent has been built from orco */
+ }
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
index 4aeddbb4c45..54de843bc64 100644
--- a/source/blender/blenkernel/intern/mesh_validate.c
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -43,10 +43,11 @@
#include "BLI_math_vector.h"
#include "BKE_deform.h"
-#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_mesh.h"
+#include "DEG_depsgraph.h"
+
#include "MEM_guardedalloc.h"
/* loop v/e are unsigned, so using max uint_32 value as invalid marker... */
@@ -936,7 +937,7 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata,
{
bool is_valid = true;
bool is_change_v, is_change_e, is_change_l, is_change_p;
- int tot_texpoly, tot_uvloop, tot_vcolloop;
+ int tot_uvloop, tot_vcolloop;
CustomDataMask mask = check_meshmask ? CD_MASK_MESH : 0;
is_valid &= mesh_validate_customdata(vdata, mask, do_verbose, do_fixes, &is_change_v);
@@ -944,17 +945,8 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata,
is_valid &= mesh_validate_customdata(ldata, mask, do_verbose, do_fixes, &is_change_l);
is_valid &= mesh_validate_customdata(pdata, mask, do_verbose, do_fixes, &is_change_p);
- tot_texpoly = CustomData_number_of_layers(pdata, CD_MTEXPOLY);
tot_uvloop = CustomData_number_of_layers(ldata, CD_MLOOPUV);
tot_vcolloop = CustomData_number_of_layers(ldata, CD_MLOOPCOL);
- if (tot_texpoly != tot_uvloop) {
- PRINT_ERR("\tCustomDataLayer mismatch, tot_texpoly(%d), tot_uvloop(%d)\n",
- tot_texpoly, tot_uvloop);
- }
- if (tot_texpoly > MAX_MTFACE) {
- PRINT_ERR("\tMore UV layers than %d allowed, %d last ones won't be available for render, shaders, etc.\n",
- MAX_MTFACE, tot_texpoly - MAX_MTFACE);
- }
if (tot_uvloop > MAX_MTFACE) {
PRINT_ERR("\tMore UV layers than %d allowed, %d last ones won't be available for render, shaders, etc.\n",
MAX_MTFACE, tot_uvloop - MAX_MTFACE);
@@ -965,18 +957,10 @@ bool BKE_mesh_validate_all_customdata(CustomData *vdata, CustomData *edata,
}
/* check indices of clone/stencil */
- if (do_fixes && CustomData_get_clone_layer(pdata, CD_MTEXPOLY) >= tot_texpoly) {
- CustomData_set_layer_clone(pdata, CD_MTEXPOLY, 0);
- is_change_p = true;
- }
if (do_fixes && CustomData_get_clone_layer(ldata, CD_MLOOPUV) >= tot_uvloop) {
CustomData_set_layer_clone(ldata, CD_MLOOPUV, 0);
is_change_l = true;
}
- if (do_fixes && CustomData_get_stencil_layer(pdata, CD_MTEXPOLY) >= tot_texpoly) {
- CustomData_set_layer_stencil(pdata, CD_MTEXPOLY, 0);
- is_change_p = true;
- }
if (do_fixes && CustomData_get_stencil_layer(ldata, CD_MLOOPUV) >= tot_uvloop) {
CustomData_set_layer_stencil(ldata, CD_MLOOPUV, 0);
is_change_l = true;
@@ -1019,7 +1003,7 @@ int BKE_mesh_validate(Mesh *me, const int do_verbose, const int cddata_check_mas
&changed);
if (changed) {
- DAG_id_tag_update(&me->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&me->id, OB_RECALC_DATA);
return true;
}
else {
@@ -1028,64 +1012,6 @@ int BKE_mesh_validate(Mesh *me, const int do_verbose, const int cddata_check_mas
}
/**
- * Duplicate of BM_mesh_cd_validate() for Mesh data.
- */
-void BKE_mesh_cd_validate(Mesh *me)
-{
- int totlayer_mtex = CustomData_number_of_layers(&me->pdata, CD_MTEXPOLY);
- int totlayer_uv = CustomData_number_of_layers(&me->ldata, CD_MLOOPUV);
- int totlayer_mcol = CustomData_number_of_layers(&me->ldata, CD_MLOOPCOL);
- int mtex_index = CustomData_get_layer_index(&me->pdata, CD_MTEXPOLY);
- int uv_index = CustomData_get_layer_index(&me->ldata, CD_MLOOPUV);
- int i;
-
- /* XXX For now, do not delete those, just warn they are not really usable. */
- if (UNLIKELY(totlayer_mtex > MAX_MTFACE)) {
- printf("WARNING! More UV layers than %d allowed, %d last ones won't be available for render, shaders, etc.\n",
- MAX_MTFACE, totlayer_mtex - MAX_MTFACE);
- }
- if (UNLIKELY(totlayer_uv > MAX_MTFACE)) {
- printf("WARNING! More UV layers than %d allowed, %d last ones won't be available for render, shaders, etc.\n",
- MAX_MTFACE, totlayer_uv - MAX_MTFACE);
- }
- if (UNLIKELY(totlayer_mcol > MAX_MCOL)) {
- printf("WARNING! More VCol layers than %d allowed, %d last ones won't be available for render, shaders, etc.\n",
- MAX_MCOL, totlayer_mcol - MAX_MCOL);
- }
-
- if (LIKELY(totlayer_mtex == totlayer_uv)) {
- /* pass */
- }
- else if (totlayer_mtex < totlayer_uv) {
- do {
- const char *from_name = me->ldata.layers[uv_index + totlayer_mtex].name;
- CustomData_add_layer_named(&me->pdata, CD_MTEXPOLY, CD_DEFAULT, NULL, me->totpoly, from_name);
- CustomData_set_layer_unique_name(&me->pdata, totlayer_mtex);
- } while (totlayer_uv != ++totlayer_mtex);
- mtex_index = CustomData_get_layer_index(&me->pdata, CD_MTEXPOLY);
- }
- else if (totlayer_uv < totlayer_mtex) {
- do {
- const char *from_name = me->pdata.layers[mtex_index + totlayer_uv].name;
- CustomData_add_layer_named(&me->ldata, CD_MLOOPUV, CD_DEFAULT, NULL, me->totloop, from_name);
- CustomData_set_layer_unique_name(&me->ldata, totlayer_uv);
- } while (totlayer_mtex != ++totlayer_uv);
- uv_index = CustomData_get_layer_index(&me->ldata, CD_MLOOPUV);
- }
-
- BLI_assert(totlayer_mtex == totlayer_uv);
-
- /* Check uv/tex names match as well!!! */
- for (i = 0; i < totlayer_mtex; i++, mtex_index++, uv_index++) {
- const char *name_src = me->pdata.layers[mtex_index].name;
- const char *name_dst = me->ldata.layers[uv_index].name;
- if (!STREQ(name_src, name_dst)) {
- BKE_mesh_uv_cdlayer_rename_index(me, mtex_index, uv_index, -1, name_src, false);
- }
- }
-}
-
-/**
* Check all material indices of polygons are valid, invalid ones are set to 0.
* \returns is_valid.
*/
@@ -1105,7 +1031,7 @@ int BKE_mesh_validate_material_indices(Mesh *me)
}
if (!is_valid) {
- DAG_id_tag_update(&me->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&me->id, OB_RECALC_DATA);
return true;
}
else {
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 1e7c3104d17..8eb1a7733c1 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -757,8 +757,8 @@ void modifier_path_init(char *path, int path_maxlen, const char *name)
/* wrapper around ModifierTypeInfo.applyModifier that ensures valid normals */
struct DerivedMesh *modwrap_applyModifier(
- ModifierData *md, Object *ob,
- struct DerivedMesh *dm,
+ ModifierData *md, const struct EvaluationContext *eval_ctx,
+ Object *ob, struct DerivedMesh *dm,
ModifierApplyFlag flag)
{
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -767,12 +767,12 @@ struct DerivedMesh *modwrap_applyModifier(
if (mti->dependsOnNormals && mti->dependsOnNormals(md)) {
DM_ensure_normals(dm);
}
- return mti->applyModifier(md, ob, dm, flag);
+ return mti->applyModifier(md, eval_ctx, ob, dm, flag);
}
struct DerivedMesh *modwrap_applyModifierEM(
- ModifierData *md, Object *ob,
- struct BMEditMesh *em,
+ ModifierData *md, const struct EvaluationContext *eval_ctx,
+ Object *ob, struct BMEditMesh *em,
DerivedMesh *dm,
ModifierApplyFlag flag)
{
@@ -782,12 +782,12 @@ struct DerivedMesh *modwrap_applyModifierEM(
if (mti->dependsOnNormals && mti->dependsOnNormals(md)) {
DM_ensure_normals(dm);
}
- return mti->applyModifierEM(md, ob, em, dm, flag);
+ return mti->applyModifierEM(md, eval_ctx, ob, em, dm, flag);
}
void modwrap_deformVerts(
- ModifierData *md, Object *ob,
- DerivedMesh *dm,
+ ModifierData *md, const struct EvaluationContext *eval_ctx,
+ Object *ob, DerivedMesh *dm,
float (*vertexCos)[3], int numVerts,
ModifierApplyFlag flag)
{
@@ -797,11 +797,11 @@ void modwrap_deformVerts(
if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
DM_ensure_normals(dm);
}
- mti->deformVerts(md, ob, dm, vertexCos, numVerts, flag);
+ mti->deformVerts(md, eval_ctx, ob, dm, vertexCos, numVerts, flag);
}
void modwrap_deformVertsEM(
- ModifierData *md, Object *ob,
+ ModifierData *md, const struct EvaluationContext *eval_ctx, Object *ob,
struct BMEditMesh *em, DerivedMesh *dm,
float (*vertexCos)[3], int numVerts)
{
@@ -811,6 +811,6 @@ void modwrap_deformVertsEM(
if (dm && mti->dependsOnNormals && mti->dependsOnNormals(md)) {
DM_ensure_normals(dm);
}
- mti->deformVertsEM(md, ob, em, dm, vertexCos, numVerts);
+ mti->deformVertsEM(md, eval_ctx, ob, em, dm, vertexCos, numVerts);
}
/* end modifier callback wrappers */
diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c
index 9c8fc9bfd0c..55f11604710 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(const struct EvaluationContext *eval_ctx, Scene *scene, MultiresModifierData *mmd, Object *ob)
{
ModifierData *md = (ModifierData *)mmd;
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
- DerivedMesh *tdm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
+ DerivedMesh *tdm = mesh_get_derived_deform(eval_ctx, scene, ob, CD_MASK_BAREMESH);
DerivedMesh *dm;
- dm = mti->applyModifier(md, ob, tdm, MOD_APPLY_USECACHE | MOD_APPLY_IGNORE_SIMPLIFY);
+ dm = mti->applyModifier(md, eval_ctx, ob, tdm, MOD_APPLY_USECACHE | MOD_APPLY_IGNORE_SIMPLIFY);
if (dm == tdm) {
dm = CDDM_copy(tdm);
}
@@ -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(const struct EvaluationContext *eval_ctx, Scene *scene, MultiresModifierData *mmd,
Object *ob, DerivedMesh *srcdm)
{
- DerivedMesh *mrdm = get_multires_dm(scene, mmd, ob);
+ DerivedMesh *mrdm = get_multires_dm(eval_ctx, scene, mmd, ob);
if (mrdm && srcdm && mrdm->getNumVerts(mrdm) == srcdm->getNumVerts(srcdm)) {
multires_mvert_to_ss(mrdm, srcdm->getVertArray(srcdm));
@@ -420,13 +420,13 @@ int multiresModifier_reshapeFromDM(Scene *scene, MultiresModifierData *mmd,
}
/* Returns 1 on success, 0 if the src's totvert doesn't match */
-int multiresModifier_reshape(Scene *scene, MultiresModifierData *mmd, Object *dst, Object *src)
+int multiresModifier_reshape(const struct EvaluationContext *eval_ctx, Scene *scene, MultiresModifierData *mmd, Object *dst, Object *src)
{
- DerivedMesh *srcdm = mesh_get_derived_final(scene, src, CD_MASK_BAREMESH);
- return multiresModifier_reshapeFromDM(scene, mmd, dst, srcdm);
+ DerivedMesh *srcdm = mesh_get_derived_final(eval_ctx, scene, src, CD_MASK_BAREMESH);
+ return multiresModifier_reshapeFromDM(eval_ctx, scene, mmd, dst, srcdm);
}
-int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mmd,
+int multiresModifier_reshapeFromDeformMod(const struct EvaluationContext *eval_ctx, Scene *scene, MultiresModifierData *mmd,
Object *ob, ModifierData *md)
{
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
@@ -438,12 +438,12 @@ int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mm
return 0;
/* Create DerivedMesh for deformation modifier */
- dm = get_multires_dm(scene, mmd, ob);
+ dm = get_multires_dm(eval_ctx, scene, mmd, ob);
numVerts = dm->getNumVerts(dm);
deformedVerts = MEM_malloc_arrayN(numVerts, sizeof(float[3]), "multiresReshape_deformVerts");
dm->getVertCos(dm, deformedVerts);
- mti->deformVerts(md, ob, dm, deformedVerts, numVerts, 0);
+ mti->deformVerts(md, eval_ctx, ob, dm, deformedVerts, numVerts, 0);
ndm = CDDM_copy(dm);
CDDM_apply_vert_coords(ndm, deformedVerts);
@@ -452,7 +452,7 @@ int multiresModifier_reshapeFromDeformMod(Scene *scene, MultiresModifierData *mm
dm->release(dm);
/* Reshaping */
- result = multiresModifier_reshapeFromDM(scene, mmd, ob, ndm);
+ result = multiresModifier_reshapeFromDM(eval_ctx, scene, mmd, ob, ndm);
/* Cleanup */
ndm->release(ndm);
@@ -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(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float smat[3][3])
{
DerivedMesh *dm = NULL, *cddm = NULL, *subdm = NULL;
CCGElem **gridData, **subGridData;
@@ -2300,10 +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(eval_ctx, scene, &high_mmd, ob);
/* prepare scaled CDDM to create ccgDN */
- cddm = mesh_get_derived_deform(scene, ob, CD_MASK_BAREMESH);
+ cddm = mesh_get_derived_deform(eval_ctx, scene, ob, CD_MASK_BAREMESH);
totvert = cddm->getNumVerts(cddm);
vertCos = MEM_malloc_arrayN(totvert, sizeof(*vertCos), "multiresScale vertCos");
@@ -2364,17 +2364,17 @@ int multires_mdisp_corners(MDisps *s)
return 0;
}
-void multiresModifier_scale_disp(Scene *scene, Object *ob)
+void multiresModifier_scale_disp(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
float smat[3][3];
/* object's scale matrix */
BKE_object_scale_to_mat3(ob, smat);
- multires_apply_smat(scene, ob, smat);
+ multires_apply_smat(eval_ctx, scene, ob, smat);
}
-void multiresModifier_prepare_join(Scene *scene, Object *ob, Object *to_ob)
+void multiresModifier_prepare_join(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, Object *to_ob)
{
float smat[3][3], tmat[3][3], mat[3][3];
multires_sync_levels(scene, to_ob, ob);
@@ -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(eval_ctx, scene, ob, mat);
}
/* update multires data after topology changing */
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index 2363eb525d5..cbb7a766dfe 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -59,7 +59,7 @@
#include "BKE_library.h"
#ifdef WITH_AUDASPACE
-# include AUD_SPECIAL_H
+# include <AUD_Special.h>
#endif
#include "RNA_access.h"
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 6be6514b5ec..ab9e2665ff0 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -2023,7 +2023,7 @@ bNodeTree *ntreeLocalize(bNodeTree *ntree)
for (node = ntree->nodes.first; node; node = node->next) {
/* store new_node pointer to original */
- node->new_node->new_node = node;
+ node->new_node->original = node;
}
if (ntree->typeinfo->localize)
@@ -3599,6 +3599,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();
@@ -3791,3 +3792,63 @@ 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)
+{
+ for (bNode *node = ntree->nodes.first; node; node = node->next) {
+ if (node->type == CMP_NODE_R_LAYERS && (Scene *)node->id == scene) {
+ if (node->custom1 == layer_index) {
+ node->custom1 = 0;
+ }
+ else if (node->custom1 > layer_index) {
+ node->custom1--;
+ }
+ }
+ }
+}
+
+static void node_copy_default_values_list(ListBase *sockets_dst,
+ const ListBase *sockets_src)
+{
+ bNodeSocket *sock_dst = sockets_dst->first;
+ const bNodeSocket *sock_src = sockets_src->first;
+ while (sock_dst != NULL) {
+ node_socket_copy_default_value(sock_dst, sock_src);
+ sock_dst = sock_dst->next;
+ sock_src = sock_src->next;
+ }
+}
+
+static void node_copy_default_values(bNode *node_dst, const bNode *node_src)
+{
+ node_copy_default_values_list(&node_dst->inputs, &node_src->inputs);
+ node_copy_default_values_list(&node_dst->outputs, &node_src->outputs);
+}
+
+void BKE_nodetree_copy_default_values(bNodeTree *ntree_dst,
+ const bNodeTree *ntree_src)
+{
+ if (ntree_dst == ntree_src) {
+ return;
+ }
+ bNode *node_dst = ntree_dst->nodes.first;
+ const bNode *node_src = ntree_src->nodes.first;
+ while (node_dst != NULL) {
+ node_copy_default_values(node_dst, node_src);
+ node_dst = node_dst->next;
+ node_src = node_src->next;
+ }
+}
+
+void BKE_nodetree_shading_params_eval(const struct EvaluationContext *UNUSED(eval_ctx),
+ bNodeTree *ntree_dst,
+ const bNodeTree *ntree_src)
+{
+ if (G.debug & G_DEBUG_DEPSGRAPH) {
+ printf("%s on %s (%p)\n", __func__, ntree_src->id.name, ntree_dst);
+ }
+ BKE_nodetree_copy_default_values(ntree_dst, ntree_src);
+}
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index c6b4e3fb0c7..923cea6acff 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -58,6 +58,7 @@
#include "DNA_view3d_types.h"
#include "DNA_world_types.h"
#include "DNA_object_types.h"
+#include "DNA_lightprobe_types.h"
#include "DNA_property_types.h"
#include "DNA_rigidbody_types.h"
@@ -78,7 +79,6 @@
#include "BKE_action.h"
#include "BKE_bullet.h"
#include "BKE_deform.h"
-#include "BKE_depsgraph.h"
#include "BKE_DerivedMesh.h"
#include "BKE_animsys.h"
#include "BKE_anim.h"
@@ -91,6 +91,7 @@
#include "BKE_icons.h"
#include "BKE_key.h"
#include "BKE_lamp.h"
+#include "BKE_layer.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
@@ -103,9 +104,11 @@
#include "BKE_multires.h"
#include "BKE_node.h"
#include "BKE_object.h"
+#include "BKE_object_facemap.h"
#include "BKE_paint.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
+#include "BKE_lightprobe.h"
#include "BKE_property.h"
#include "BKE_rigidbody.h"
#include "BKE_sca.h"
@@ -118,6 +121,10 @@
#include "BKE_camera.h"
#include "BKE_image.h"
+#include "DEG_depsgraph.h"
+
+#include "DRW_engine.h"
+
#ifdef WITH_MOD_FLUID
#include "LBM_fluidsim.h"
#endif
@@ -129,7 +136,7 @@
#include "CCGSubSurf.h"
#include "atomic_ops.h"
-#include "GPU_material.h"
+#include "GPU_lamp.h"
/* Vertex parent modifies original BMesh which is not safe for threading.
* Ideally such a modification should be handled as a separate DAG update
@@ -152,16 +159,6 @@ void BKE_object_workob_clear(Object *workob)
workob->rotmode = ROT_MODE_EUL;
}
-void BKE_object_update_base_layer(struct Scene *scene, Object *ob)
-{
- Base *base = scene->base.first;
-
- while (base) {
- if (base->object == ob) base->lay = ob->lay;
- base = base->next;
- }
-}
-
void BKE_object_free_particlesystems(Object *ob)
{
ParticleSystem *psys;
@@ -356,7 +353,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.newid;
+ /* 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 +409,7 @@ void BKE_object_free_caches(Object *object)
* guaranteed to be in a known state.
*/
if (update_flag != 0) {
- DAG_id_tag_update(&object->id, update_flag);
+ DEG_id_tag_update(&object->id, update_flag);
}
}
@@ -418,6 +426,7 @@ void BKE_object_free(Object *ob)
MEM_SAFE_FREE(ob->bb);
BLI_freelistN(&ob->defbase);
+ BLI_freelistN(&ob->fmaps);
if (ob->pose) {
BKE_pose_free_ex(ob->pose, false);
ob->pose = NULL;
@@ -448,6 +457,16 @@ void BKE_object_free(Object *ob)
}
GPU_lamp_free(ob);
+ for (ObjectEngineData *oed = ob->drawdata.first; oed; oed = oed->next) {
+ if (oed->storage) {
+ if (oed->free) {
+ oed->free(oed->storage);
+ }
+ MEM_freeN(oed->storage);
+ }
+ }
+ BLI_freelistN(&ob->drawdata);
+
BKE_sculptsession_free(ob);
BLI_freelistN(&ob->pc_ids);
@@ -464,6 +483,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 */
@@ -528,6 +550,36 @@ bool BKE_object_is_in_wpaint_select_vert(Object *ob)
return false;
}
+/**
+ * Return if the object is visible, as evaluated by depsgraph
+ */
+bool BKE_object_is_visible(Object *ob, const eObjectVisibilityCheck mode)
+{
+ if ((ob->base_flag & BASE_VISIBLED) == 0) {
+ return false;
+ }
+
+ if (mode == OB_VISIBILITY_CHECK_UNKNOWN_RENDER_MODE) {
+ return true;
+ }
+
+ if (((ob->transflag & OB_DUPLI) == 0) &&
+ (ob->particlesystem.first == NULL))
+ {
+ return true;
+ }
+
+ switch (mode) {
+ case OB_VISIBILITY_CHECK_FOR_VIEWPORT:
+ return ((ob->duplicator_visibility_flag & OB_DUPLI_FLAG_VIEWPORT) != 0);
+ case OB_VISIBILITY_CHECK_FOR_RENDER:
+ return ((ob->duplicator_visibility_flag & OB_DUPLI_FLAG_RENDER) != 0);
+ default:
+ BLI_assert(!"Object visible test mode not supported.");
+ return false;
+ }
+}
+
bool BKE_object_exists_check(Object *obtest)
{
Object *ob;
@@ -581,6 +633,7 @@ void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name)
case OB_LATTICE: return BKE_lattice_add(bmain, name);
case OB_ARMATURE: return BKE_armature_add(bmain, name);
case OB_SPEAKER: return BKE_speaker_add(bmain, name);
+ case OB_LIGHTPROBE:return BKE_lightprobe_add(bmain, name);
case OB_EMPTY: return NULL;
default:
printf("%s: Internal error, bad type: %d\n", __func__, type);
@@ -652,6 +705,7 @@ void BKE_object_init(Object *ob)
ob->col_group = 0x01;
ob->col_mask = 0xffff;
ob->preview = NULL;
+ ob->duplicator_visibility_flag = OB_DUPLI_FLAG_VIEWPORT | OB_DUPLI_FLAG_RENDER;
/* NT fluid sim defaults */
ob->fluidsimSettings = NULL;
@@ -672,6 +726,9 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
ob = BKE_libblock_alloc(bmain, ID_OB, name, 0);
+ /* We increase object user count when linking to SceneCollections. */
+ id_us_min(&ob->id);
+
/* default object vars */
ob->type = type;
@@ -680,29 +737,65 @@ Object *BKE_object_add_only_object(Main *bmain, int type, const char *name)
return ob;
}
-/* general add: to scene, with layer from area and default name */
+
+static Object *object_add_common(Main *bmain, ViewLayer *view_layer, int type, const char *name)
+{
+ Object *ob;
+
+ ob = BKE_object_add_only_object(bmain, type, name);
+ ob->data = BKE_object_obdata_add_from_type(bmain, type, name);
+ BKE_view_layer_base_deselect_all(view_layer);
+
+ DEG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ return ob;
+}
+
+/**
+ * General add: to scene, with layer from area and default name
+ *
+ * Object is added to the active SceneCollection.
+ * If there is no linked collection to the active ViewLayer we create a new one.
+ */
/* creates minimum required data, but without vertices etc. */
Object *BKE_object_add(
- Main *bmain, Scene *scene,
+ Main *bmain, Scene *scene, ViewLayer *view_layer,
int type, const char *name)
{
Object *ob;
Base *base;
+ LayerCollection *layer_collection;
- ob = BKE_object_add_only_object(bmain, type, name);
+ ob = object_add_common(bmain, view_layer, type, name);
- ob->data = BKE_object_obdata_add_from_type(bmain, type, name);
+ layer_collection = BKE_layer_collection_get_active_ensure(scene, view_layer);
+ BKE_collection_object_add(&scene->id, layer_collection->scene_collection, ob);
- ob->lay = scene->lay;
-
- base = BKE_scene_base_add(scene, ob);
- BKE_scene_base_deselect_all(scene);
- BKE_scene_base_select(scene, base);
- DAG_id_tag_update_ex(bmain, &ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ base = BKE_view_layer_base_find(view_layer, ob);
+ BKE_view_layer_base_select(view_layer, base);
return ob;
}
+/**
+ * Add a new object, using another one as a reference
+ *
+ * /param ob_src object to use to determine the collections of the new object.
+ */
+Object *BKE_object_add_from(
+ Main *bmain, Scene *scene, ViewLayer *view_layer,
+ int type, const char *name, Object *ob_src)
+{
+ Object *ob;
+ Base *base;
+
+ ob = object_add_common(bmain, view_layer, type, name);
+ BKE_collection_object_add_from(scene, ob_src, ob);
+
+ base = BKE_view_layer_base_find(view_layer, ob);
+ BKE_view_layer_base_select(view_layer, base);
+
+ return ob;
+}
#ifdef WITH_GAMEENGINE
@@ -794,9 +887,9 @@ static LodLevel *lod_level_select(Object *ob, const float camera_position[3])
return current;
}
-bool BKE_object_lod_is_usable(Object *ob, Scene *scene)
+bool BKE_object_lod_is_usable(Object *ob, ViewLayer *view_layer)
{
- bool active = (scene) ? ob == OBACT : false;
+ bool active = (view_layer) ? ob == OBACT(view_layer) : false;
return (ob->mode == OB_MODE_OBJECT || !active);
}
@@ -810,11 +903,11 @@ void BKE_object_lod_update(Object *ob, const float camera_position[3])
}
}
-static Object *lod_ob_get(Object *ob, Scene *scene, int flag)
+static Object *lod_ob_get(Object *ob, ViewLayer *view_layer, int flag)
{
LodLevel *current = ob->currentlod;
- if (!current || !BKE_object_lod_is_usable(ob, scene))
+ if (!current || !BKE_object_lod_is_usable(ob, view_layer))
return ob;
while (current->prev && (!(current->flags & flag) || !current->source || current->source->type != OB_MESH)) {
@@ -824,14 +917,14 @@ static Object *lod_ob_get(Object *ob, Scene *scene, int flag)
return current->source;
}
-struct Object *BKE_object_lod_meshob_get(Object *ob, Scene *scene)
+struct Object *BKE_object_lod_meshob_get(Object *ob, ViewLayer *view_layer)
{
- return lod_ob_get(ob, scene, OB_LOD_USE_MESH);
+ return lod_ob_get(ob, view_layer, OB_LOD_USE_MESH);
}
-struct Object *BKE_object_lod_matob_get(Object *ob, Scene *scene)
+struct Object *BKE_object_lod_matob_get(Object *ob, ViewLayer *view_layer)
{
- return lod_ob_get(ob, scene, OB_LOD_USE_MAT);
+ return lod_ob_get(ob, view_layer, OB_LOD_USE_MAT);
}
#endif /* WITH_GAMEENGINE */
@@ -943,6 +1036,7 @@ ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys, const int f
psysn->effectors = NULL;
psysn->tree = NULL;
psysn->bvhtree = NULL;
+ psysn->batch_cache = NULL;
BLI_listbase_clear(&psysn->pathcachebufs);
BLI_listbase_clear(&psysn->childcachebufs);
@@ -1147,6 +1241,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;
@@ -1169,6 +1264,7 @@ void BKE_object_copy_data(Main *UNUSED(bmain), Object *ob_dst, const Object *ob_
ob_dst->derivedFinal = NULL;
BLI_listbase_clear(&ob_dst->gpulamp);
+ BLI_listbase_clear(&ob_dst->drawdata);
BLI_listbase_clear(&ob_dst->pc_ids);
ob_dst->mpath = NULL;
@@ -1329,8 +1425,8 @@ void BKE_object_make_proxy(Object *ob, Object *target, Object *gob)
ob->proxy_group = gob;
id_lib_extern(&target->id);
- DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
- DAG_id_tag_update(&target->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
+ DEG_id_tag_update(&target->id, OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME);
/* copy transform
* - gob means this proxy comes from a group, just apply the matrix
@@ -1673,13 +1769,16 @@ static bool ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4])
Curve *cu = par->data;
float vec[4], dir[3], quat[4], radius, ctime;
+ /* TODO: Make sure this doesn't crash. */
+#if 0
/* only happens on reload file, but violates depsgraph still... fix! */
if (par->curve_cache == NULL) {
if (scene == NULL) {
return false;
}
- BKE_displist_make_curveTypes(scene, par, 0);
+ BKE_displist_make_curveTypes(eval_ctx, scene, par, 0);
}
+#endif
if (par->curve_cache->path == NULL) {
return false;
@@ -2060,8 +2159,9 @@ static bool where_is_object_parslow(Object *ob, float obmat[4][4], float slowmat
}
/* note, scene is the active scene while actual_scene is the scene the object resides in */
-void BKE_object_where_is_calc_time_ex(Scene *scene, Object *ob, float ctime,
- RigidBodyWorld *rbw, float r_originmat[3][3])
+void BKE_object_where_is_calc_time_ex(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, float ctime,
+ RigidBodyWorld *rbw, float r_originmat[3][3])
{
if (ob == NULL) return;
@@ -2096,7 +2196,7 @@ void BKE_object_where_is_calc_time_ex(Scene *scene, Object *ob, float ctime,
if (ob->constraints.first && !(ob->transflag & OB_NO_CONSTRAINTS)) {
bConstraintOb *cob;
cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
- BKE_constraints_solve(&ob->constraints, cob, ctime);
+ BKE_constraints_solve(eval_ctx, &ob->constraints, cob, ctime);
BKE_constraints_clear_evalob(cob);
}
@@ -2105,9 +2205,9 @@ void BKE_object_where_is_calc_time_ex(Scene *scene, Object *ob, float ctime,
else ob->transflag &= ~OB_NEG_SCALE;
}
-void BKE_object_where_is_calc_time(Scene *scene, Object *ob, float ctime)
+void BKE_object_where_is_calc_time(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, float ctime)
{
- BKE_object_where_is_calc_time_ex(scene, ob, ctime, NULL, NULL);
+ BKE_object_where_is_calc_time_ex(eval_ctx, scene, ob, ctime, NULL, NULL);
}
/* get object transformation matrix without recalculating dependencies and
@@ -2132,17 +2232,17 @@ void BKE_object_where_is_calc_mat4(Scene *scene, Object *ob, float obmat[4][4])
}
}
-void BKE_object_where_is_calc_ex(Scene *scene, RigidBodyWorld *rbw, Object *ob, float r_originmat[3][3])
+void BKE_object_where_is_calc_ex(const EvaluationContext *eval_ctx, Scene *scene, RigidBodyWorld *rbw, Object *ob, float r_originmat[3][3])
{
- BKE_object_where_is_calc_time_ex(scene, ob, BKE_scene_frame_get(scene), rbw, r_originmat);
+ BKE_object_where_is_calc_time_ex(eval_ctx, scene, ob, BKE_scene_frame_get(scene), rbw, r_originmat);
}
-void BKE_object_where_is_calc(Scene *scene, Object *ob)
+void BKE_object_where_is_calc(const EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
- BKE_object_where_is_calc_time_ex(scene, ob, BKE_scene_frame_get(scene), NULL, NULL);
+ BKE_object_where_is_calc_time_ex(eval_ctx, scene, ob, BKE_scene_frame_get(scene), NULL, NULL);
}
/* for calculation of the inverse parent transform, only used for editor */
-void BKE_object_workob_calc_parent(Scene *scene, Object *ob, Object *workob)
+void BKE_object_workob_calc_parent(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, Object *workob)
{
BKE_object_workob_clear(workob);
@@ -2164,7 +2264,7 @@ void BKE_object_workob_calc_parent(Scene *scene, Object *ob, Object *workob)
BLI_strncpy(workob->parsubstr, ob->parsubstr, sizeof(workob->parsubstr));
- BKE_object_where_is_calc(scene, workob);
+ BKE_object_where_is_calc(eval_ctx, scene, workob);
}
/* see BKE_pchan_apply_mat4() for the equivalent 'pchan' function */
@@ -2489,14 +2589,14 @@ void BKE_object_foreach_display_point(
}
void BKE_scene_foreach_display_point(
- Scene *scene, View3D *v3d, const short flag,
+ Scene *scene, ViewLayer *view_layer,
void (*func_cb)(const float[3], void *), void *user_data)
{
Base *base;
Object *ob;
- for (base = FIRSTBASE; base; base = base->next) {
- if (BASE_VISIBLE_BGMODE(v3d, scene, base) && (base->flag & flag) == flag) {
+ for (base = FIRSTBASE(view_layer); base; base = base->next) {
+ if (((base->flag & BASE_VISIBLED) != 0) && ((base->flag & BASE_SELECTED) != 0)) {
ob = base->object;
if ((ob->transflag & OB_DUPLI) == 0) {
@@ -2586,7 +2686,7 @@ bool BKE_object_parent_loop_check(const Object *par, const Object *ob)
return BKE_object_parent_loop_check(par->parent, ob);
}
-static void object_handle_update_proxy(EvaluationContext *eval_ctx,
+static void object_handle_update_proxy(const EvaluationContext *eval_ctx,
Scene *scene,
Object *object,
const bool do_proxy_update)
@@ -2616,12 +2716,17 @@ static void object_handle_update_proxy(EvaluationContext *eval_ctx,
/* the main object update call, for object matrix, constraints, keys and displist (modifiers) */
/* requires flags to be set! */
/* Ideally we shouldn't have to pass the rigid body world, but need bigger restructuring to avoid id */
-void BKE_object_handle_update_ex(EvaluationContext *eval_ctx,
+void BKE_object_handle_update_ex(const EvaluationContext *eval_ctx,
Scene *scene, Object *ob,
RigidBodyWorld *rbw,
const bool do_proxy_update)
{
- if ((ob->recalc & OB_RECALC_ALL) == 0) {
+ const ID *object_data = ob->data;
+ const bool recalc_object = (ob->id.recalc & ID_RECALC) != 0;
+ const bool recalc_data =
+ (object_data != NULL) ? ((object_data->recalc & ID_RECALC_ALL) != 0)
+ : 0;
+ if (!recalc_object && ! recalc_data) {
object_handle_update_proxy(eval_ctx, scene, ob, do_proxy_update);
return;
}
@@ -2632,7 +2737,7 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx,
BKE_pose_update_constraint_flags(ob->pose);
}
}
- if (ob->recalc & OB_RECALC_DATA) {
+ if (recalc_data) {
if (ob->type == OB_ARMATURE) {
/* this happens for reading old files and to match library armatures
* with poses we do it ahead of BKE_object_where_is_calc to ensure animation
@@ -2645,21 +2750,21 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx,
/* XXX new animsys warning: depsgraph tag OB_RECALC_DATA should not skip drivers,
* which is only in BKE_object_where_is_calc now */
/* XXX: should this case be OB_RECALC_OB instead? */
- if (ob->recalc & OB_RECALC_ALL) {
+ if (recalc_object || recalc_data) {
if (G.debug & G_DEBUG_DEPSGRAPH) {
printf("recalcob %s\n", ob->id.name + 2);
}
/* Handle proxy copy for target. */
if (!BKE_object_eval_proxy_copy(eval_ctx, ob)) {
- BKE_object_where_is_calc_ex(scene, rbw, ob, NULL);
+ BKE_object_where_is_calc_ex(eval_ctx, scene, rbw, ob, NULL);
}
}
- if (ob->recalc & OB_RECALC_DATA) {
+ if (recalc_data) {
BKE_object_handle_data_update(eval_ctx, scene, ob);
}
- ob->recalc &= ~OB_RECALC_ALL;
+ ob->id.recalc &= ID_RECALC_ALL;
object_handle_update_proxy(eval_ctx, scene, ob, do_proxy_update);
}
@@ -2669,7 +2774,7 @@ void BKE_object_handle_update_ex(EvaluationContext *eval_ctx,
* e.g. "scene" <-- set 1 <-- set 2 ("ob" lives here) <-- set 3 <-- ... <-- set n
* rigid bodies depend on their world so use BKE_object_handle_update_ex() to also pass along the corrent rigid body world
*/
-void BKE_object_handle_update(EvaluationContext *eval_ctx, Scene *scene, Object *ob)
+void BKE_object_handle_update(const EvaluationContext *eval_ctx, Scene *scene, Object *ob)
{
BKE_object_handle_update_ex(eval_ctx, scene, ob, NULL, true);
}
@@ -2716,14 +2821,7 @@ int BKE_object_obdata_texspace_get(Object *ob, short **r_texflag, float **r_loc,
switch (GS(((ID *)ob->data)->name)) {
case ID_ME:
{
- Mesh *me = ob->data;
- if (me->bb == NULL || (me->bb->flag & BOUNDBOX_DIRTY)) {
- BKE_mesh_texspace_calc(me);
- }
- if (r_texflag) *r_texflag = &me->texflag;
- if (r_loc) *r_loc = me->loc;
- if (r_size) *r_size = me->size;
- if (r_rot) *r_rot = me->rot;
+ BKE_mesh_texspace_get_reference((Mesh *)ob->data, r_texflag, r_loc, r_rot, r_size);
break;
}
case ID_CU:
@@ -3290,33 +3388,33 @@ static void obrel_list_add(LinkNode **links, Object *ob)
}
/*
- * Iterates over all objects of the given scene.
+ * Iterates over all objects of the given scene layer.
* Depending on the eObjectSet flag:
* collect either OB_SET_ALL, OB_SET_VISIBLE or OB_SET_SELECTED objects.
* If OB_SET_VISIBLE or OB_SET_SELECTED are collected,
* then also add related objects according to the given includeFilters.
*/
-LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectSet, eObRelationTypes includeFilter)
+LinkNode *BKE_object_relational_superset(struct ViewLayer *view_layer, eObjectSet objectSet, eObRelationTypes includeFilter)
{
LinkNode *links = NULL;
Base *base;
/* Remove markers from all objects */
- for (base = scene->base.first; base; base = base->next) {
+ for (base = view_layer->object_bases.first; base; base = base->next) {
base->object->id.tag &= ~LIB_TAG_DOIT;
}
/* iterate over all selected and visible objects */
- for (base = scene->base.first; base; base = base->next) {
+ for (base = view_layer->object_bases.first; base; base = base->next) {
if (objectSet == OB_SET_ALL) {
/* as we get all anyways just add it */
Object *ob = base->object;
obrel_list_add(&links, ob);
}
else {
- if ((objectSet == OB_SET_SELECTED && TESTBASELIB_BGMODE(((View3D *)NULL), scene, base)) ||
- (objectSet == OB_SET_VISIBLE && BASE_EDITABLE_BGMODE(((View3D *)NULL), scene, base)))
+ if ((objectSet == OB_SET_SELECTED && TESTBASELIB_BGMODE(base)) ||
+ (objectSet == OB_SET_VISIBLE && BASE_EDITABLE_BGMODE(base)))
{
Object *ob = base->object;
@@ -3345,8 +3443,8 @@ LinkNode *BKE_object_relational_superset(struct Scene *scene, eObjectSet objectS
/* child relationship */
if (includeFilter & (OB_REL_CHILDREN | OB_REL_CHILDREN_RECURSIVE)) {
Base *local_base;
- for (local_base = scene->base.first; local_base; local_base = local_base->next) {
- if (BASE_EDITABLE_BGMODE(((View3D *)NULL), scene, local_base)) {
+ for (local_base = view_layer->object_bases.first; local_base; local_base = local_base->next) {
+ if (BASE_EDITABLE_BGMODE(local_base)) {
Object *child = local_base->object;
if (obrel_list_test(child)) {
@@ -3390,18 +3488,11 @@ struct LinkNode *BKE_object_groups(Object *ob)
return group_linknode;
}
-void BKE_object_groups_clear(Scene *scene, Base *base, Object *object)
+void BKE_object_groups_clear(Object *ob)
{
Group *group = NULL;
-
- BLI_assert((base == NULL) || (base->object == object));
-
- if (scene && base == NULL) {
- base = BKE_scene_base_find(scene, object);
- }
-
- while ((group = BKE_group_object_find(group, base->object))) {
- BKE_group_object_unlink(group, object, scene, base);
+ while ((group = BKE_group_object_find(group, ob))) {
+ BKE_group_object_unlink(group, ob);
}
}
@@ -3602,9 +3693,9 @@ static void object_cacheIgnoreClear(Object *ob, int state)
/* Note: this function should eventually be replaced by depsgraph functionality.
* Avoid calling this in new code unless there is a very good reason for it!
*/
-bool BKE_object_modifier_update_subframe(Scene *scene, Object *ob, bool update_mesh,
- int parent_recursion, float frame,
- int type)
+bool BKE_object_modifier_update_subframe(
+ const EvaluationContext *eval_ctx, Scene *scene, Object *ob, bool update_mesh,
+ int parent_recursion, float frame, int type)
{
ModifierData *md = modifiers_findByType(ob, (ModifierType)type);
bConstraint *con;
@@ -3627,8 +3718,8 @@ bool BKE_object_modifier_update_subframe(Scene *scene, Object *ob, bool update_m
if (parent_recursion) {
int recursion = parent_recursion - 1;
bool no_update = false;
- if (ob->parent) no_update |= BKE_object_modifier_update_subframe(scene, ob->parent, 0, recursion, frame, type);
- if (ob->track) no_update |= BKE_object_modifier_update_subframe(scene, ob->track, 0, recursion, frame, type);
+ if (ob->parent) no_update |= BKE_object_modifier_update_subframe(eval_ctx, scene, ob->parent, 0, recursion, frame, type);
+ if (ob->track) no_update |= BKE_object_modifier_update_subframe(eval_ctx, scene, ob->track, 0, recursion, frame, type);
/* skip subframe if object is parented
* to vertex of a dynamic paint canvas */
@@ -3645,7 +3736,7 @@ bool BKE_object_modifier_update_subframe(Scene *scene, Object *ob, bool update_m
cti->get_constraint_targets(con, &targets);
for (ct = targets.first; ct; ct = ct->next) {
if (ct->tar)
- BKE_object_modifier_update_subframe(scene, ct->tar, 0, recursion, frame, type);
+ BKE_object_modifier_update_subframe(eval_ctx, scene, ct->tar, 0, recursion, frame, type);
}
/* free temp targets */
if (cti->flush_constraint_targets)
@@ -3655,7 +3746,8 @@ bool BKE_object_modifier_update_subframe(Scene *scene, Object *ob, bool update_m
}
/* was originally OB_RECALC_ALL - TODO - which flags are really needed??? */
- ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
+ /* TODO(sergey): What about animation? */
+ ob->id.recalc |= ID_RECALC_ALL;
BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, frame, ADT_RECALC_ANIM);
if (update_mesh) {
/* ignore cache clear during subframe updates
@@ -3665,7 +3757,7 @@ bool BKE_object_modifier_update_subframe(Scene *scene, Object *ob, bool update_m
object_cacheIgnoreClear(ob, 0);
}
else
- BKE_object_where_is_calc_time(scene, ob, frame);
+ BKE_object_where_is_calc_time(eval_ctx, scene, ob, frame);
/* for curve following objects, parented curve has to be updated too */
if (ob->type == OB_CURVE) {
@@ -3676,7 +3768,7 @@ bool BKE_object_modifier_update_subframe(Scene *scene, Object *ob, bool update_m
if (ob->type == OB_ARMATURE) {
bArmature *arm = ob->data;
BKE_animsys_evaluate_animdata(scene, &arm->id, arm->adt, frame, ADT_RECALC_ANIM);
- BKE_pose_where_is(scene, ob);
+ BKE_pose_where_is(eval_ctx, scene, ob);
}
return false;
diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c
index d387e30050c..754434eaef6 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..13589866e48 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -49,10 +49,10 @@
#include "BKE_animsys.h"
#include "BKE_DerivedMesh.h"
-#include "BKE_depsgraph.h"
#include "BKE_font.h"
-#include "BKE_group.h"
#include "BKE_global.h"
+#include "BKE_group.h"
+#include "BKE_idprop.h"
#include "BKE_lattice.h"
#include "BKE_main.h"
#include "BKE_mesh.h"
@@ -62,6 +62,7 @@
#include "BKE_editmesh.h"
#include "BKE_anim.h"
+#include "DEG_depsgraph.h"
#include "BLI_strict_flags.h"
#include "BLI_hash.h"
@@ -69,15 +70,15 @@
/* Dupli-Geometry */
typedef struct DupliContext {
- EvaluationContext *eval_ctx;
+ const EvaluationContext *eval_ctx;
bool do_update;
bool animated;
Group *group; /* XXX child objects are selected from this group if set, could be nicer */
Scene *scene;
+ ViewLayer *view_layer;
Object *object;
float space_mat[4][4];
- unsigned int lay;
int persistent_id[MAX_DUPLI_RECUR];
int level;
@@ -96,10 +97,11 @@ typedef struct DupliGenerator {
static const DupliGenerator *get_dupli_generator(const DupliContext *ctx);
/* create initial context for root object */
-static void init_context(DupliContext *r_ctx, EvaluationContext *eval_ctx, Scene *scene, Object *ob, float space_mat[4][4], bool update)
+static void init_context(DupliContext *r_ctx, const EvaluationContext *eval_ctx, Scene *scene, Object *ob, float space_mat[4][4], bool update)
{
r_ctx->eval_ctx = eval_ctx;
r_ctx->scene = scene;
+ r_ctx->view_layer = eval_ctx->view_layer;
/* don't allow BKE_object_handle_update for viewport during render, can crash */
r_ctx->do_update = update && !(G.is_rendering && eval_ctx->mode != DAG_EVAL_RENDER);
r_ctx->animated = false;
@@ -110,7 +112,6 @@ static void init_context(DupliContext *r_ctx, EvaluationContext *eval_ctx, Scene
copy_m4_m4(r_ctx->space_mat, space_mat);
else
unit_m4(r_ctx->space_mat);
- r_ctx->lay = ob->lay;
r_ctx->level = 0;
r_ctx->gen = get_dupli_generator(r_ctx);
@@ -143,7 +144,8 @@ static void copy_dupli_context(DupliContext *r_ctx, const DupliContext *ctx, Obj
*/
static DupliObject *make_dupli(const DupliContext *ctx,
Object *ob, float mat[4][4], int index,
- bool animated, bool hide)
+ bool animated, bool hide,
+ IDProperty *collection_properties)
{
DupliObject *dob;
int i;
@@ -198,6 +200,10 @@ static DupliObject *make_dupli(const DupliContext *ctx,
dob->random_id ^= BLI_hash_int(BLI_hash_string(ctx->object->id.name + 2));
}
+ if (collection_properties) {
+ dob->collection_properties = IDP_CopyProperty(collection_properties);
+ }
+
return dob;
}
@@ -238,32 +244,30 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild
Object *obedit = ctx->scene->obedit;
if (ctx->group) {
- unsigned int lay = ctx->group->layer;
int groupid = 0;
- GroupObject *go;
- for (go = ctx->group->gobject.first; go; go = go->next, groupid++) {
- Object *ob = go->ob;
-
- if ((ob->lay & lay) && ob != obedit && is_child(ob, parent)) {
+ FOREACH_GROUP_BASE(ctx->group, base)
+ {
+ Object *ob = base->object;
+ if ((base->flag & BASE_VISIBLED) && ob != obedit && is_child(ob, parent)) {
DupliContext pctx;
copy_dupli_context(&pctx, ctx, ctx->object, NULL, groupid, false);
/* mballs have a different dupli handling */
- if (ob->type != OB_MBALL)
+ if (ob->type != OB_MBALL) {
ob->flag |= OB_DONE; /* doesnt render */
-
+ }
make_child_duplis_cb(&pctx, userdata, ob);
}
+ groupid++;
}
+ FOREACH_GROUP_BASE_END
}
else {
- unsigned int lay = ctx->scene->lay;
int baseid = 0;
- Base *base;
- for (base = ctx->scene->base.first; base; base = base->next, baseid++) {
+ ViewLayer *view_layer = ctx->view_layer;
+ for (Base *base = view_layer->object_bases.first; base; base = base->next, baseid++) {
Object *ob = base->object;
-
- if ((base->lay & lay) && ob != obedit && is_child(ob, parent)) {
+ if ((base->flag & BASE_VISIBLED) && ob != obedit && is_child(ob, parent)) {
DupliContext pctx;
copy_dupli_context(&pctx, ctx, ctx->object, NULL, baseid, false);
@@ -283,13 +287,12 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild
/* OB_DUPLIGROUP */
static void make_duplis_group(const DupliContext *ctx)
{
- bool for_render = (ctx->eval_ctx->mode == DAG_EVAL_RENDER);
Object *ob = ctx->object;
Group *group;
- GroupObject *go;
+ Base *base;
float group_mat[4][4];
int id;
- bool animated, hide;
+ bool animated;
if (ob->dup_group == NULL) return;
group = ob->dup_group;
@@ -311,34 +314,18 @@ static void make_duplis_group(const DupliContext *ctx)
animated = BKE_group_is_animated(group, ob);
- for (go = group->gobject.first, id = 0; go; go = go->next, id++) {
- /* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */
- if (go->ob != ob) {
+ for (base = group->view_layer->object_bases.first, id = 0; base; base = base->next, id++) {
+ if (base->object != ob && (base->flag & BASE_VISIBLED)) {
float mat[4][4];
- /* Special case for instancing dupli-groups, see: T40051
- * this object may be instanced via dupli-verts/faces, in this case we don't want to render
- * (blender convention), but _do_ show in the viewport.
- *
- * Regular objects work fine but not if we're instancing dupli-groups,
- * because the rules for rendering aren't applied to objects they instance.
- * We could recursively pass down the 'hide' flag instead, but that seems unnecessary.
- */
- if (for_render && go->ob->parent && go->ob->parent->transflag & (OB_DUPLIVERTS | OB_DUPLIFACES)) {
- continue;
- }
-
/* group dupli offset, should apply after everything else */
- mul_m4_m4m4(mat, group_mat, go->ob->obmat);
+ mul_m4_m4m4(mat, group_mat, base->object->obmat);
- /* check the group instance and object layers match, also that the object visible flags are ok. */
- hide = (go->ob->lay & group->layer) == 0 ||
- (for_render ? go->ob->restrictflag & OB_RESTRICT_RENDER : go->ob->restrictflag & OB_RESTRICT_VIEW);
-
- make_dupli(ctx, go->ob, mat, id, animated, hide);
+ BLI_assert(base->collection_properties != NULL);
+ make_dupli(ctx, base->object, mat, id, animated, false, base->collection_properties);
/* recursion */
- make_recursive_duplis(ctx, go->ob, group_mat, id, animated);
+ make_recursive_duplis(ctx, base->object, group_mat, id, animated);
}
}
}
@@ -377,10 +364,6 @@ static void make_duplis_frames(const DupliContext *ctx)
/* duplicate over the required range */
if (ob->transflag & OB_DUPLINOSPEED) enable_cu_speed = 0;
- /* special flag to avoid setting recalc flags to notify the depsgraph of
- * updates, as this is not a permanent change to the object */
- ob->id.recalc |= ID_RECALC_SKIP_ANIM_TAG;
-
for (scene->r.cfra = ob->dupsta; scene->r.cfra <= dupend; scene->r.cfra++) {
int ok = 1;
@@ -399,9 +382,9 @@ static void make_duplis_frames(const DupliContext *ctx)
* However, this has always been the way that this worked (i.e. pre 2.5), so I guess that it'll be fine!
*/
BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */
- BKE_object_where_is_calc_time(scene, ob, (float)scene->r.cfra);
+ BKE_object_where_is_calc_time(ctx->eval_ctx, scene, ob, (float)scene->r.cfra);
- make_dupli(ctx, ob, ob->obmat, scene->r.cfra, false, false);
+ make_dupli(ctx, ob, ob->obmat, scene->r.cfra, false, false, NULL);
}
}
@@ -413,7 +396,7 @@ static void make_duplis_frames(const DupliContext *ctx)
scene->r.cfra = cfrao;
BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */
- BKE_object_where_is_calc_time(scene, ob, (float)scene->r.cfra);
+ BKE_object_where_is_calc_time(ctx->eval_ctx, scene, ob, (float)scene->r.cfra);
/* but, to make sure unkeyed object transforms are still sane,
* let's copy object's original data back over
@@ -486,7 +469,7 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3],
*/
mul_m4_m4m4(space_mat, obmat, inst_ob->imat);
- dob = make_dupli(vdd->ctx, vdd->inst_ob, obmat, index, false, false);
+ dob = make_dupli(vdd->ctx, vdd->inst_ob, obmat, index, false, false, NULL);
if (vdd->orco)
copy_v3_v3(dob->orco, vdd->orco[index]);
@@ -548,13 +531,13 @@ static void make_duplis_verts(const DupliContext *ctx)
CustomDataMask dm_mask = (use_texcoords ? CD_MASK_BAREMESH | CD_MASK_ORCO : CD_MASK_BAREMESH);
if (ctx->eval_ctx->mode == DAG_EVAL_RENDER) {
- vdd.dm = mesh_create_derived_render(scene, parent, dm_mask);
+ vdd.dm = mesh_create_derived_render(ctx->eval_ctx, scene, parent, dm_mask);
}
else if (em) {
- vdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask);
+ vdd.dm = editbmesh_get_derived_cage(ctx->eval_ctx, scene, parent, em, dm_mask);
}
else {
- vdd.dm = mesh_get_derived_final(scene, parent, dm_mask);
+ vdd.dm = mesh_get_derived_final(ctx->eval_ctx, scene, parent, dm_mask);
}
vdd.edit_btmesh = me->edit_btmesh;
@@ -671,7 +654,7 @@ static void make_duplis_font(const DupliContext *ctx)
copy_v3_v3(obmat[3], vec);
- make_dupli(ctx, ob, obmat, a, false, false);
+ make_dupli(ctx, ob, obmat, a, false, false, NULL);
}
}
@@ -777,7 +760,7 @@ static void make_child_duplis_faces(const DupliContext *ctx, void *userdata, Obj
*/
mul_m4_m4m4(space_mat, obmat, inst_ob->imat);
- dob = make_dupli(ctx, inst_ob, obmat, a, false, false);
+ dob = make_dupli(ctx, inst_ob, obmat, a, false, false, NULL);
if (use_texcoords) {
float w = 1.0f / (float)mp->totloop;
@@ -816,13 +799,13 @@ static void make_duplis_faces(const DupliContext *ctx)
CustomDataMask dm_mask = (use_texcoords ? CD_MASK_BAREMESH | CD_MASK_ORCO | CD_MASK_MLOOPUV : CD_MASK_BAREMESH);
if (ctx->eval_ctx->mode == DAG_EVAL_RENDER) {
- fdd.dm = mesh_create_derived_render(scene, parent, dm_mask);
+ fdd.dm = mesh_create_derived_render(ctx->eval_ctx, scene, parent, dm_mask);
}
else if (em) {
- fdd.dm = editbmesh_get_derived_cage(scene, parent, em, dm_mask);
+ fdd.dm = editbmesh_get_derived_cage(ctx->eval_ctx, scene, parent, em, dm_mask);
}
else {
- fdd.dm = mesh_get_derived_final(scene, parent, dm_mask);
+ fdd.dm = mesh_get_derived_final(ctx->eval_ctx, scene, parent, dm_mask);
}
if (use_texcoords) {
@@ -860,7 +843,6 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
bool for_render = ctx->eval_ctx->mode == DAG_EVAL_RENDER;
bool use_texcoords = ELEM(ctx->eval_ctx->mode, DAG_EVAL_RENDER, DAG_EVAL_PREVIEW);
- GroupObject *go;
Object *ob = NULL, **oblist = NULL, obcopy, *obcopylist = NULL;
DupliObject *dob;
ParticleDupliWeight *dw;
@@ -900,6 +882,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
if ((psys->renderdata || part->draw_as == PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
ParticleSimulationData sim = {NULL};
+ sim.eval_ctx = ctx->eval_ctx;
sim.scene = scene;
sim.ob = par;
sim.psys = psys;
@@ -913,10 +896,10 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
return;
}
else { /*PART_DRAW_GR */
- if (part->dup_group == NULL || BLI_listbase_is_empty(&part->dup_group->gobject))
+ if (part->dup_group == NULL || BLI_listbase_is_empty(&part->dup_group->view_layer->object_bases))
return;
- if (BLI_findptr(&part->dup_group->gobject, par, offsetof(GroupObject, ob))) {
+ if (BLI_findptr(&part->dup_group->view_layer->object_bases, par, offsetof(Base, object))) {
return;
}
}
@@ -948,8 +931,12 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
totgroup += dw->count;
}
else {
- for (go = part->dup_group->gobject.first; go; go = go->next)
+ FOREACH_GROUP_OBJECT(part->dup_group, object)
+ {
+ (void) object;
totgroup++;
+ }
+ FOREACH_GROUP_OBJECT_END
}
/* we also copy the actual objects to restore afterwards, since
@@ -968,11 +955,18 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
}
}
else {
- go = part->dup_group->gobject.first;
- for (a = 0; a < totgroup; a++, go = go->next) {
- oblist[a] = go->ob;
- obcopylist[a] = *go->ob;
+ a = 0;
+ FOREACH_GROUP_OBJECT(part->dup_group, object)
+ {
+ oblist[a] = object;
+ obcopylist[a] = *object;
+ a++;
+
+ if (a >= totgroup) {
+ continue;
+ }
}
+ FOREACH_GROUP_OBJECT_END
}
}
else {
@@ -1061,27 +1055,37 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
}
if (part->ren_as == PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) {
- for (go = part->dup_group->gobject.first, b = 0; go; go = go->next, b++) {
-
+ b = 0;
+ FOREACH_GROUP_OBJECT(part->dup_group, object)
+ {
copy_m4_m4(tmat, oblist[b]->obmat);
+
/* apply particle scale */
mul_mat3_m4_fl(tmat, size * scale);
mul_v3_fl(tmat[3], size * scale);
+
/* group dupli offset, should apply after everything else */
- if (!is_zero_v3(part->dup_group->dupli_ofs))
+ if (!is_zero_v3(part->dup_group->dupli_ofs)) {
sub_v3_v3(tmat[3], part->dup_group->dupli_ofs);
+ }
+
/* individual particle transform */
mul_m4_m4m4(mat, pamat, tmat);
- dob = make_dupli(ctx, go->ob, mat, a, false, false);
+ dob = make_dupli(ctx, object, mat, a, false, false, NULL);
dob->particle_system = psys;
- if (use_texcoords)
+
+ if (use_texcoords) {
psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
+ }
+
+ b++;
}
+ FOREACH_GROUP_OBJECT_END
}
else {
/* to give ipos in object correct offset */
- BKE_object_where_is_calc_time(scene, ob, ctime - pa_time);
+ BKE_object_where_is_calc_time(ctx->eval_ctx, scene, ob, ctime - pa_time);
copy_v3_v3(vec, obmat[3]);
obmat[3][0] = obmat[3][1] = obmat[3][2] = 0.0f;
@@ -1122,7 +1126,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
if (part->draw & PART_DRAW_GLOBAL_OB)
add_v3_v3v3(mat[3], mat[3], vec);
- dob = make_dupli(ctx, ob, mat, a, false, false);
+ dob = make_dupli(ctx, ob, mat, a, false, false, NULL);
dob->particle_system = psys;
if (use_texcoords)
psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco);
@@ -1217,7 +1221,7 @@ static const DupliGenerator *get_dupli_generator(const DupliContext *ctx)
/* ---- ListBase dupli container implementation ---- */
/* Returns a list of DupliObject */
-ListBase *object_duplilist_ex(EvaluationContext *eval_ctx, Scene *scene, Object *ob, bool update)
+ListBase *object_duplilist_ex(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, bool update)
{
ListBase *duplilist = MEM_callocN(sizeof(ListBase), "duplilist");
DupliContext ctx;
@@ -1232,13 +1236,21 @@ ListBase *object_duplilist_ex(EvaluationContext *eval_ctx, Scene *scene, Object
/* note: previously updating was always done, this is why it defaults to be on
* but there are likely places it can be called without updating */
-ListBase *object_duplilist(EvaluationContext *eval_ctx, Scene *sce, Object *ob)
+ListBase *object_duplilist(const EvaluationContext *eval_ctx, Scene *sce, Object *ob)
{
return object_duplilist_ex(eval_ctx, sce, ob, true);
}
void free_object_duplilist(ListBase *lb)
{
+
+ for (DupliObject *dob = lb->first; dob; dob = dob->next) {
+ if (dob->collection_properties) {
+ IDP_FreeProperty(dob->collection_properties);
+ MEM_freeN(dob->collection_properties);
+ }
+ }
+
BLI_freelistN(lb);
MEM_freeN(lb);
}
@@ -1273,7 +1285,7 @@ int count_duplilist(Object *ob)
return 1;
}
-DupliApplyData *duplilist_apply(Object *ob, Scene *scene, ListBase *duplilist)
+DupliApplyData *duplilist_apply(const EvaluationContext *eval_ctx, Object *ob, Scene *scene, ListBase *duplilist)
{
DupliApplyData *apply_data = NULL;
int num_objects = BLI_listbase_count(duplilist);
@@ -1289,7 +1301,7 @@ DupliApplyData *duplilist_apply(Object *ob, Scene *scene, ListBase *duplilist)
for (dob = duplilist->first, i = 0; dob; dob = dob->next, ++i) {
/* make sure derivedmesh is calculated once, before drawing */
if (scene && !(dob->ob->transflag & OB_DUPLICALCDERIVED) && dob->ob->type == OB_MESH) {
- mesh_get_derived_final(scene, dob->ob, scene->customdata_mask);
+ mesh_get_derived_final(eval_ctx, scene, dob->ob, scene->customdata_mask);
dob->ob->transflag |= OB_DUPLICALCDERIVED;
}
}
diff --git a/source/blender/blenkernel/intern/object_facemap.c b/source/blender/blenkernel/intern/object_facemap.c
new file mode 100644
index 00000000000..1218dd376cb
--- /dev/null
+++ b/source/blender/blenkernel/intern/object_facemap.c
@@ -0,0 +1,257 @@
+
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2008 Blender Foundation.
+ * All rights reserved.
+ *
+ *
+ * Contributor(s): Blender Foundation
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/object_facemap.c
+ * \ingroup bke
+ */
+
+#include <string.h>
+
+#include "DNA_object_types.h"
+#include "DNA_mesh_types.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_path_util.h"
+#include "BLI_string.h"
+#include "BLI_string_utils.h"
+#include "BLI_listbase.h"
+
+#include "BKE_context.h"
+#include "BKE_customdata.h"
+#include "BKE_editmesh.h"
+#include "BKE_object.h"
+#include "BKE_object_facemap.h" /* own include */
+#include "BKE_object_deform.h"
+
+#include "BLT_translation.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "RNA_define.h"
+#include "RNA_access.h"
+
+static bool fmap_unique_check(void *arg, const char *name)
+{
+ struct {Object *ob; void *fm; } *data = arg;
+
+ bFaceMap *fmap;
+
+ for (fmap = data->ob->fmaps.first; fmap; fmap = fmap->next) {
+ if (data->fm != fmap) {
+ if (!strcmp(fmap->name, name)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+static bFaceMap *fmap_duplicate(bFaceMap *infmap)
+{
+ bFaceMap *outfmap;
+
+ if (!infmap)
+ return NULL;
+
+ outfmap = MEM_callocN(sizeof(bFaceMap), "copy facemap");
+
+ /* For now, just copy everything over. */
+ memcpy(outfmap, infmap, sizeof(bFaceMap));
+
+ outfmap->next = outfmap->prev = NULL;
+
+ return outfmap;
+}
+
+void BKE_object_facemap_copy_list(ListBase *outbase, const ListBase *inbase)
+{
+ bFaceMap *fmap, *fmapn;
+
+ BLI_listbase_clear(outbase);
+
+ for (fmap = inbase->first; fmap; fmap = fmap->next) {
+ fmapn = fmap_duplicate(fmap);
+ BLI_addtail(outbase, fmapn);
+ }
+}
+
+void BKE_object_facemap_unique_name(Object *ob, bFaceMap *fmap)
+{
+ struct {Object *ob; void *fmap; } data;
+ data.ob = ob;
+ data.fmap = fmap;
+
+ BLI_uniquename_cb(fmap_unique_check, &data, DATA_("Group"), '.', fmap->name, sizeof(fmap->name));
+}
+
+bFaceMap *BKE_object_facemap_add_name(Object *ob, const char *name)
+{
+ bFaceMap *fmap;
+
+ if (!ob || ob->type != OB_MESH)
+ return NULL;
+
+ fmap = MEM_callocN(sizeof(bFaceMap), __func__);
+
+ BLI_strncpy(fmap->name, name, sizeof(fmap->name));
+
+ BLI_addtail(&ob->fmaps, fmap);
+
+ ob->actfmap = BLI_listbase_count(&ob->fmaps);
+
+ BKE_object_facemap_unique_name(ob, fmap);
+
+ return fmap;
+}
+
+bFaceMap *BKE_object_facemap_add(Object *ob)
+{
+ return BKE_object_facemap_add_name(ob, DATA_("FaceMap"));
+}
+
+
+static void object_fmap_remove_edit_mode(Object *ob, bFaceMap *fmap, bool do_selected, bool purge)
+{
+ const int fmap_nr = BLI_findindex(&ob->fmaps, fmap);
+
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (me->edit_btmesh) {
+ BMEditMesh *em = me->edit_btmesh;
+ const int cd_fmap_offset = CustomData_get_offset(&em->bm->pdata, CD_FACEMAP);
+
+ if (cd_fmap_offset != -1) {
+ BMFace *efa;
+ BMIter iter;
+ int *map;
+
+ if (purge) {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
+
+ if (map) {
+ if (*map == fmap_nr)
+ *map = -1;
+ else if (*map > fmap_nr)
+ *map -= 1;
+ }
+ }
+ }
+ else {
+ BM_ITER_MESH (efa, &iter, em->bm, BM_FACES_OF_MESH) {
+ map = BM_ELEM_CD_GET_VOID_P(efa, cd_fmap_offset);
+
+ if (map && *map == fmap_nr && (!do_selected || BM_elem_flag_test(efa, BM_ELEM_SELECT))) {
+ *map = -1;
+ }
+ }
+ }
+ }
+
+ if (ob->actfmap == BLI_listbase_count(&ob->fmaps))
+ ob->actfmap--;
+
+ BLI_remlink(&ob->fmaps, fmap);
+ MEM_freeN(fmap);
+ }
+ }
+}
+
+static void object_fmap_remove_object_mode(Object *ob, bFaceMap *fmap, bool purge)
+{
+ const int fmap_nr = BLI_findindex(&ob->fmaps, fmap);
+
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+
+ if (CustomData_has_layer(&me->pdata, CD_FACEMAP)) {
+ int *map = CustomData_get_layer(&me->pdata, CD_FACEMAP);
+ int i;
+
+ if (map) {
+ for (i = 0; i < me->totpoly; i++) {
+ if (map[i] == fmap_nr)
+ map[i] = -1;
+ else if (purge && map[i] > fmap_nr)
+ map[i]--;
+ }
+ }
+ }
+
+ if (ob->actfmap == BLI_listbase_count(&ob->fmaps))
+ ob->actfmap--;
+
+ BLI_remlink(&ob->fmaps, fmap);
+ MEM_freeN(fmap);
+ }
+}
+
+static void fmap_remove_exec(Object *ob, bFaceMap *fmap, const bool is_edit_mode, const bool purge)
+{
+ if (is_edit_mode)
+ object_fmap_remove_edit_mode(ob, fmap, false, purge);
+ else
+ object_fmap_remove_object_mode(ob, fmap, purge);
+}
+
+void BKE_object_facemap_remove(Object *ob, bFaceMap *fmap)
+{
+ fmap_remove_exec(ob, fmap, BKE_object_is_in_editmode(ob), true);
+}
+
+void BKE_object_facemap_clear(Object *ob)
+{
+ bFaceMap *fmap = (bFaceMap *)ob->fmaps.first;
+
+ if (fmap) {
+ const bool edit_mode = BKE_object_is_in_editmode_vgroup(ob);
+
+ while (fmap) {
+ bFaceMap *next_fmap = fmap->next;
+ fmap_remove_exec(ob, fmap, edit_mode, false);
+ fmap = next_fmap;
+ }
+ }
+ /* remove all face-maps */
+ if (ob->type == OB_MESH) {
+ Mesh *me = ob->data;
+ CustomData_free_layer(&me->pdata, CD_FACEMAP, me->totpoly, 0);
+ }
+ ob->actfmap = 0;
+}
+
+int BKE_object_facemap_name_index(Object *ob, const char *name)
+{
+ return (name) ? BLI_findstringindex(&ob->fmaps, name, offsetof(bFaceMap, name)) : -1;
+}
+
+bFaceMap *BKE_object_facemap_find_name(Object *ob, const char *name)
+{
+ return BLI_findstring(&ob->fmaps, name, offsetof(bFaceMap, name));
+}
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 84d2f624577..71d8c1981af 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -32,18 +32,18 @@
#include "DNA_group_types.h"
#include "DNA_key_types.h"
#include "DNA_material_types.h"
+#include "DNA_mesh_types.h"
#include "DNA_scene_types.h"
#include "BLI_blenlib.h"
#include "BLI_utildefines.h"
#include "BLI_math.h"
-#include "BLI_threads.h"
#include "BKE_global.h"
#include "BKE_armature.h"
#include "BKE_action.h"
#include "BKE_constraint.h"
-#include "BKE_depsgraph.h"
+#include "BKE_curve.h"
#include "BKE_DerivedMesh.h"
#include "BKE_animsys.h"
#include "BKE_displist.h"
@@ -51,28 +51,26 @@
#include "BKE_key.h"
#include "BKE_lamp.h"
#include "BKE_lattice.h"
+#include "BKE_library.h"
#include "BKE_editmesh.h"
#include "BKE_object.h"
#include "BKE_particle.h"
#include "BKE_pointcache.h"
#include "BKE_scene.h"
#include "BKE_material.h"
+#include "BKE_mball.h"
+#include "BKE_mesh.h"
#include "BKE_image.h"
+#include "MEM_guardedalloc.h"
#include "DEG_depsgraph.h"
-#ifdef WITH_LEGACY_DEPSGRAPH
-# define DEBUG_PRINT if (!DEG_depsgraph_use_legacy() && G.debug & G_DEBUG_DEPSGRAPH) printf
-#else
-# define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
-#endif
-
-static ThreadMutex material_lock = BLI_MUTEX_INITIALIZER;
+#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
-void BKE_object_eval_local_transform(EvaluationContext *UNUSED(eval_ctx),
+void BKE_object_eval_local_transform(const EvaluationContext *UNUSED(eval_ctx),
Object *ob)
{
- DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob);
/* calculate local matrix */
BKE_object_to_mat4(ob, ob->obmat);
@@ -80,7 +78,7 @@ void BKE_object_eval_local_transform(EvaluationContext *UNUSED(eval_ctx),
/* Evaluate parent */
/* NOTE: based on solve_parenting(), but with the cruft stripped out */
-void BKE_object_eval_parent(EvaluationContext *UNUSED(eval_ctx),
+void BKE_object_eval_parent(const EvaluationContext *UNUSED(eval_ctx),
Scene *scene,
Object *ob)
{
@@ -90,7 +88,7 @@ void BKE_object_eval_parent(EvaluationContext *UNUSED(eval_ctx),
float tmat[4][4];
float locmat[4][4];
- DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob);
/* get local matrix (but don't calculate it, as that was done already!) */
// XXX: redundant?
@@ -112,14 +110,14 @@ void BKE_object_eval_parent(EvaluationContext *UNUSED(eval_ctx),
}
}
-void BKE_object_eval_constraints(EvaluationContext *UNUSED(eval_ctx),
+void BKE_object_eval_constraints(const EvaluationContext *eval_ctx,
Scene *scene,
Object *ob)
{
bConstraintOb *cob;
float ctime = BKE_scene_frame_get(scene);
- DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob);
/* evaluate constraints stack */
/* TODO: split this into:
@@ -131,22 +129,23 @@ void BKE_object_eval_constraints(EvaluationContext *UNUSED(eval_ctx),
*
*/
cob = BKE_constraints_make_evalob(scene, ob, NULL, CONSTRAINT_OBTYPE_OBJECT);
- BKE_constraints_solve(&ob->constraints, cob, ctime);
+ BKE_constraints_solve(eval_ctx, &ob->constraints, cob, ctime);
BKE_constraints_clear_evalob(cob);
}
-void BKE_object_eval_done(EvaluationContext *UNUSED(eval_ctx), Object *ob)
+void BKE_object_eval_done(const EvaluationContext *UNUSED(eval_ctx), Object *ob)
{
- DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob);
/* Set negative scale flag in object. */
if (is_negative_m4(ob->obmat)) ob->transflag |= OB_NEG_SCALE;
else ob->transflag &= ~OB_NEG_SCALE;
}
-void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
- Scene *scene,
- Object *ob)
+void BKE_object_handle_data_update(
+ const EvaluationContext *eval_ctx,
+ Scene *scene,
+ Object *ob)
{
ID *data_id = (ID *)ob->data;
AnimData *adt = BKE_animdata_from_id(data_id);
@@ -183,10 +182,10 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
}
#endif
if (em) {
- makeDerivedMesh(scene, ob, em, data_mask, false); /* was CD_MASK_BAREMESH */
+ makeDerivedMesh(eval_ctx, scene, ob, em, data_mask, false); /* was CD_MASK_BAREMESH */
}
else {
- makeDerivedMesh(scene, ob, NULL, data_mask, false);
+ makeDerivedMesh(eval_ctx, scene, ob, NULL, data_mask, false);
}
break;
}
@@ -198,7 +197,7 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
}
}
else {
- BKE_pose_where_is(scene, ob);
+ BKE_pose_where_is(eval_ctx, scene, ob);
}
break;
@@ -209,11 +208,11 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
case OB_CURVE:
case OB_SURF:
case OB_FONT:
- BKE_displist_make_curveTypes(scene, ob, 0);
+ BKE_displist_make_curveTypes(eval_ctx, scene, ob, 0);
break;
case OB_LATTICE:
- BKE_lattice_modifiers_calc(scene, ob);
+ BKE_lattice_modifiers_calc(eval_ctx, scene, ob);
break;
case OB_EMPTY:
@@ -223,28 +222,6 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
break;
}
- /* related materials */
- /* XXX: without depsgraph tagging, this will always need to be run, which will be slow!
- * However, not doing anything (or trying to hack around this lack) is not an option
- * anymore, especially due to Cycles [#31834]
- */
- if (ob->totcol) {
- int a;
- if (ob->totcol != 0) {
- BLI_mutex_lock(&material_lock);
- for (a = 1; a <= ob->totcol; a++) {
- Material *ma = give_current_material(ob, a);
- if (ma) {
- /* recursively update drivers for this material */
- material_drivers_update(scene, ma, ctime);
- }
- }
- BLI_mutex_unlock(&material_lock);
- }
- }
- else if (ob->type == OB_LAMP)
- lamp_drivers_update(scene, ob->data, ctime);
-
/* particles */
if (ob != scene->obedit && ob->particlesystem.first) {
ParticleSystem *tpsys, *psys;
@@ -266,7 +243,7 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
ob->transflag |= OB_DUPLIPARTS;
}
- particle_system_update(scene, ob, psys, (eval_ctx->mode == DAG_EVAL_RENDER));
+ particle_system_update(eval_ctx, scene, ob, psys, (eval_ctx->mode == DAG_EVAL_RENDER));
psys = psys->next;
}
else if (psys->flag & PSYS_DELETE) {
@@ -284,7 +261,7 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
* the derivedmesh must be created before init_render_mesh,
* since object_duplilist does dupliparticles before that */
CustomDataMask data_mask = CD_MASK_BAREMESH | CD_MASK_MFACE | CD_MASK_MTFACE | CD_MASK_MCOL;
- dm = mesh_create_derived_render(scene, ob, data_mask);
+ dm = mesh_create_derived_render(eval_ctx, scene, ob, data_mask);
dm->release(dm);
for (psys = ob->particlesystem.first; psys; psys = psys->next)
@@ -295,7 +272,7 @@ void BKE_object_handle_data_update(EvaluationContext *eval_ctx,
/* quick cache removed */
}
-bool BKE_object_eval_proxy_copy(EvaluationContext *UNUSED(eval_ctx),
+bool BKE_object_eval_proxy_copy(const EvaluationContext *UNUSED(eval_ctx),
Object *object)
{
/* Handle proxy copy for target, */
@@ -319,35 +296,98 @@ bool BKE_object_eval_proxy_copy(EvaluationContext *UNUSED(eval_ctx),
return false;
}
-void BKE_object_eval_uber_transform(EvaluationContext *eval_ctx, Object *object)
+void BKE_object_eval_uber_transform(const EvaluationContext *eval_ctx, Object *object)
{
BKE_object_eval_proxy_copy(eval_ctx, object);
- object->recalc &= ~(OB_RECALC_OB | OB_RECALC_TIME);
- if (object->data == NULL) {
- object->recalc &= ~OB_RECALC_DATA;
- }
}
-void BKE_object_eval_uber_data(EvaluationContext *eval_ctx,
+void BKE_object_eval_uber_data(const EvaluationContext *eval_ctx,
Scene *scene,
Object *ob)
{
- DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob);
BLI_assert(ob->type != OB_ARMATURE);
BKE_object_handle_data_update(eval_ctx, scene, ob);
- ob->recalc &= ~(OB_RECALC_DATA | OB_RECALC_TIME);
+ switch (ob->type) {
+ case OB_MESH:
+ BKE_mesh_batch_cache_dirty(ob->data, BKE_MESH_BATCH_DIRTY_ALL);
+ break;
+ case OB_LATTICE:
+ BKE_lattice_batch_cache_dirty(ob->data, BKE_LATTICE_BATCH_DIRTY_ALL);
+ break;
+ case OB_CURVE:
+ case OB_FONT:
+ case OB_SURF:
+ BKE_curve_batch_cache_dirty(ob->data, BKE_CURVE_BATCH_DIRTY_ALL);
+ break;
+ case OB_MBALL:
+ BKE_mball_batch_cache_dirty(ob->data, BKE_MBALL_BATCH_DIRTY_ALL);
+ break;
+ }
+
+ if (DEG_depsgraph_use_copy_on_write()) {
+ if (ob->type == OB_MESH) {
+ /* Quick hack to convert evaluated derivedMesh to Mesh. */
+ DerivedMesh *dm = ob->derivedFinal;
+ if (dm != NULL) {
+ Mesh *mesh = (Mesh *)ob->data;
+ Mesh *new_mesh = BKE_libblock_alloc_notest(ID_ME);
+ BKE_mesh_init(new_mesh);
+ /* Copy ID name so GS(new_mesh->id) works correct later on. */
+ BLI_strncpy(new_mesh->id.name, mesh->id.name, sizeof(new_mesh->id.name));
+ /* Copy materials so render engines can access them. */
+ new_mesh->mat = MEM_dupallocN(mesh->mat);
+ new_mesh->totcol = mesh->totcol;
+ DM_to_mesh(dm, new_mesh, ob, CD_MASK_MESH, true);
+ new_mesh->edit_btmesh = mesh->edit_btmesh;
+ /* Store result mesh as derived_mesh of object. This way we have
+ * explicit way to query final object evaluated data and know for sure
+ * who owns the newly created mesh datablock.
+ */
+ ob->mesh_evaluated = new_mesh;
+ /* TODO(sergey): This is kind of compatibility thing, so all render
+ * engines can use object->data for mesh data for display. This is
+ * something what we might want to change in the future.
+ */
+ ob->data = new_mesh;
+ /* Special flags to help debugging. */
+ new_mesh->id.tag |= LIB_TAG_COPY_ON_WRITE_EVAL;
+ /* Save some memory by throwing DerivedMesh away. */
+ /* NOTE: Watch out, some tools might need it!
+ * So keep around for now..
+ */
+ /* Store original ID as a pointer in evaluated ID.
+ * This way we can restore original object data when we are freeing
+ * evaluated mesh.
+ */
+ new_mesh->id.newid = &mesh->id;
+ }
+#if 0
+ if (ob->derivedFinal != NULL) {
+ ob->derivedFinal->needsFree = 1;
+ ob->derivedFinal->release(ob->derivedFinal);
+ ob->derivedFinal = NULL;
+ }
+ if (ob->derivedDeform != NULL) {
+ ob->derivedDeform->needsFree = 1;
+ ob->derivedDeform->release(ob->derivedDeform);
+ ob->derivedDeform = NULL;
+ }
+#endif
+ }
+ }
}
-void BKE_object_eval_cloth(EvaluationContext *UNUSED(eval_ctx),
+void BKE_object_eval_cloth(const EvaluationContext *UNUSED(eval_ctx),
Scene *scene,
Object *object)
{
- DEBUG_PRINT("%s on %s\n", __func__, object->id.name);
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, object->id.name, object);
BKE_ptcache_object_reset(scene, object, PTCACHE_RESET_DEPSGRAPH);
}
-void BKE_object_eval_transform_all(EvaluationContext *eval_ctx,
+void BKE_object_eval_transform_all(const EvaluationContext *eval_ctx,
Scene *scene,
Object *object)
{
@@ -362,3 +402,51 @@ void BKE_object_eval_transform_all(EvaluationContext *eval_ctx,
BKE_object_eval_uber_transform(eval_ctx, object);
BKE_object_eval_done(eval_ctx, object);
}
+
+void BKE_object_eval_update_shading(const EvaluationContext *UNUSED(eval_ctx),
+ Object *object)
+{
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, object->id.name, object);
+ if (object->type == OB_MESH) {
+ BKE_mesh_batch_cache_dirty(object->data, BKE_MESH_BATCH_DIRTY_SHADING);
+ }
+}
+
+void BKE_object_data_select_update(const EvaluationContext *UNUSED(eval_ctx),
+ struct ID *object_data)
+{
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, object_data->name, object_data);
+ switch (GS(object_data->name)) {
+ case ID_ME:
+ BKE_mesh_batch_cache_dirty((Mesh *)object_data,
+ BKE_CURVE_BATCH_DIRTY_SELECT);
+ break;
+ case ID_CU:
+ BKE_curve_batch_cache_dirty((Curve *)object_data,
+ BKE_CURVE_BATCH_DIRTY_SELECT);
+ break;
+ case ID_LT:
+ BKE_lattice_batch_cache_dirty((struct Lattice *)object_data,
+ BKE_CURVE_BATCH_DIRTY_SELECT);
+ break;
+ default:
+ break;
+ }
+}
+
+void BKE_object_eval_flush_base_flags(const EvaluationContext *UNUSED(eval_ctx),
+ Object *object, Base *base, bool is_from_set)
+{
+ DEBUG_PRINT("%s on %s (%p)\n", __func__, object->id.name, object);
+ /* Make sure we have the base collection settings is already populated.
+ * This will fail when BKE_layer_eval_layer_collection_pre hasn't run yet
+ * Which usually means a missing call to DEG_id_tag_update(). */
+ BLI_assert(!BLI_listbase_is_empty(&base->collection_properties->data.group));
+ /* Copy flags and settings from base. */
+ object->base_flag = base->flag;
+ if (is_from_set) {
+ object->base_flag |= BASE_FROM_SET;
+ object->base_flag &= ~(BASE_SELECTED | BASE_SELECTABLED);
+ }
+ object->base_collection_properties = base->collection_properties;
+}
diff --git a/source/blender/blenkernel/intern/outliner_treehash.c b/source/blender/blenkernel/intern/outliner_treehash.c
index 4d97121e2a3..d9a602aa41e 100644
--- a/source/blender/blenkernel/intern/outliner_treehash.c
+++ b/source/blender/blenkernel/intern/outliner_treehash.c
@@ -27,6 +27,7 @@
*/
#include <stdlib.h>
+#include <string.h>
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
@@ -56,7 +57,7 @@ static TseGroup *tse_group_create(void)
return tse_group;
}
-static void tse_group_add(TseGroup *tse_group, TreeStoreElem *elem)
+static void tse_group_add_element(TseGroup *tse_group, TreeStoreElem *elem)
{
if (UNLIKELY(tse_group->size == tse_group->allocated)) {
tse_group->allocated *= 2;
@@ -66,6 +67,26 @@ static void tse_group_add(TseGroup *tse_group, TreeStoreElem *elem)
tse_group->size++;
}
+static void tse_group_remove_element(TseGroup *tse_group, TreeStoreElem *elem)
+{
+ int min_allocated = MAX2(1, tse_group->allocated / 2);
+ BLI_assert(tse_group->allocated == 1 || (tse_group->allocated % 2) == 0);
+
+ tse_group->size--;
+ BLI_assert(tse_group->size >= 0);
+ for (int i = 0; i < tse_group->size; i++) {
+ if (tse_group->elems[i] == elem) {
+ memcpy(tse_group->elems[i], tse_group->elems[i + 1], (tse_group->size - (i + 1)) * sizeof(TreeStoreElem *));
+ break;
+ }
+ }
+
+ if (UNLIKELY(tse_group->size > 0 && tse_group->size <= min_allocated)) {
+ tse_group->allocated = min_allocated;
+ tse_group->elems = MEM_reallocN(tse_group->elems, sizeof(TreeStoreElem *) * tse_group->allocated);
+ }
+}
+
static void tse_group_free(TseGroup *tse_group)
{
MEM_freeN(tse_group->elems);
@@ -140,7 +161,21 @@ void BKE_outliner_treehash_add_element(void *treehash, TreeStoreElem *elem)
*val_p = tse_group_create();
}
group = *val_p;
- tse_group_add(group, elem);
+ tse_group_add_element(group, elem);
+}
+
+void BKE_outliner_treehash_remove_element(void *treehash, TreeStoreElem *elem)
+{
+ TseGroup *group = BLI_ghash_lookup(treehash, elem);
+
+ BLI_assert(group != NULL);
+ if (group->size <= 1) {
+ /* one element -> remove group completely */
+ BLI_ghash_remove(treehash, elem, NULL, free_treehash_group);
+ }
+ else {
+ tse_group_remove_element(group, elem);
+ }
}
static TseGroup *BKE_outliner_treehash_lookup_group(GHash *th, short type, short nr, struct ID *id)
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index c6aa9c40fce..152a882de97 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -53,7 +53,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 +64,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 +75,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 +89,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 +157,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:
@@ -188,14 +189,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) {
@@ -238,14 +240,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) {
@@ -733,7 +736,7 @@ void BKE_sculptsession_bm_to_me(Object *ob, bool reorder)
sculptsession_bm_to_me_update_data_only(ob, reorder);
/* ensure the objects DerivedMesh mesh doesn't hold onto arrays now realloc'd in the mesh [#34473] */
- DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+ DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
}
}
@@ -743,7 +746,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.
*/
@@ -874,8 +877,9 @@ static bool sculpt_modifiers_active(Scene *scene, Sculpt *sd, Object *ob)
/**
* \param need_mask So the DerivedMesh thats returned has mask data
*/
-void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
- bool need_pmap, bool need_mask)
+void BKE_sculpt_update_mesh_elements(
+ const EvaluationContext *eval_ctx, Scene *scene, Sculpt *sd, Object *ob,
+ bool need_pmap, bool need_mask)
{
DerivedMesh *dm;
SculptSession *ss = ob->sculpt;
@@ -914,7 +918,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(eval_ctx, scene, ob, CD_MASK_BAREMESH);
/* VWPaint require mesh info for loop lookup, so require sculpt mode here */
if (mmd && ob->mode & OB_MODE_SCULPT) {
@@ -949,7 +953,7 @@ void BKE_sculpt_update_mesh_elements(Scene *scene, Sculpt *sd, Object *ob,
ss->orig_cos = (ss->kb) ? BKE_keyblock_convert_to_vertcos(ob, ss->kb) : BKE_mesh_vertexCos_get(me, NULL);
- BKE_crazyspace_build_sculpt(scene, ob, &ss->deform_imats, &ss->deform_cos);
+ BKE_crazyspace_build_sculpt(eval_ctx, scene, ob, &ss->deform_imats, &ss->deform_cos);
BKE_pbvh_apply_vertCos(ss->pbvh, ss->deform_cos);
for (a = 0; a < me->totvert; ++a) {
@@ -985,6 +989,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 c0849e6bff4..b204a448e7f 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -78,7 +78,6 @@
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_library_remap.h"
-#include "BKE_depsgraph.h"
#include "BKE_modifier.h"
#include "BKE_mesh.h"
#include "BKE_cdderivedmesh.h"
@@ -86,6 +85,9 @@
#include "BKE_scene.h"
#include "BKE_deform.h"
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+
#include "RE_render_ext.h"
unsigned int PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT];
@@ -250,7 +252,7 @@ struct LatticeDeformData *psys_create_lattice_deform_data(ParticleSimulationData
{
struct LatticeDeformData *lattice_deform_data = NULL;
- if (psys_in_edit_mode(sim->scene, sim->psys) == 0) {
+ if (psys_in_edit_mode(sim->eval_ctx->view_layer, sim->psys) == 0) {
Object *lattice = NULL;
ModifierData *md = (ModifierData *)psys_get_modifier(sim->ob, sim->psys);
int mode = G.is_rendering ? eModifierMode_Render : eModifierMode_Realtime;
@@ -286,10 +288,16 @@ void psys_enable_all(Object *ob)
for (; psys; psys = psys->next)
psys->flag &= ~PSYS_DISABLED;
}
-bool psys_in_edit_mode(Scene *scene, ParticleSystem *psys)
+
+bool psys_in_edit_mode(ViewLayer *view_layer, ParticleSystem *psys)
{
- return (scene->basact && (scene->basact->object->mode & OB_MODE_PARTICLE_EDIT) && psys == psys_get_current((scene->basact)->object) && (psys->edit || psys->pointcache->edit) && !psys->renderdata);
+ return (view_layer->basact &&
+ (view_layer->basact->object->mode & OB_MODE_PARTICLE_EDIT) &&
+ psys == psys_get_current((view_layer->basact)->object) &&
+ (psys->edit || psys->pointcache->edit) &&
+ !psys->renderdata);
}
+
bool psys_check_enabled(Object *ob, ParticleSystem *psys, const bool use_render_params)
{
ParticleSystemModifierData *psmd;
@@ -319,18 +327,17 @@ bool psys_check_edited(ParticleSystem *psys)
void psys_check_group_weights(ParticleSettings *part)
{
ParticleDupliWeight *dw, *tdw;
- GroupObject *go;
int current = 0;
- if (part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->gobject.first) {
+ if (part->ren_as == PART_DRAW_GR && part->dup_group && part->dup_group->view_layer->object_bases.first) {
/* First try to find NULL objects from their index,
* and remove all weights that don't have an object in the group. */
dw = part->dupliweights.first;
while (dw) {
if (dw->ob == NULL || !BKE_group_object_exists(part->dup_group, dw->ob)) {
- go = (GroupObject *)BLI_findlink(&part->dup_group->gobject, dw->index);
- if (go) {
- dw->ob = go->ob;
+ Base *base = BLI_findlink(&part->dup_group->view_layer->object_bases, dw->index);
+ if (base != NULL) {
+ dw->ob = base->object;
}
else {
tdw = dw->next;
@@ -344,21 +351,21 @@ void psys_check_group_weights(ParticleSettings *part)
}
/* then add objects in the group to new list */
- go = part->dup_group->gobject.first;
- while (go) {
+ FOREACH_GROUP_OBJECT(part->dup_group, object)
+ {
dw = part->dupliweights.first;
- while (dw && dw->ob != go->ob)
+ while (dw && dw->ob != object) {
dw = dw->next;
-
+ }
+
if (!dw) {
dw = MEM_callocN(sizeof(ParticleDupliWeight), "ParticleDupliWeight");
- dw->ob = go->ob;
+ dw->ob = object;
dw->count = 1;
BLI_addtail(&part->dupliweights, dw);
}
-
- go = go->next;
}
+ FOREACH_GROUP_OBJECT_END
dw = part->dupliweights.first;
for (; dw; dw = dw->next) {
@@ -607,6 +614,8 @@ void psys_free(Object *ob, ParticleSystem *psys)
MEM_freeN(psys->pdd);
}
+ BKE_particle_batch_cache_free(psys);
+
MEM_freeN(psys);
}
}
@@ -1843,7 +1852,7 @@ void precalc_guides(ParticleSimulationData *sim, ListBase *effectors)
}
}
-int do_guides(ParticleSettings *part, ListBase *effectors, ParticleKey *state, int index, float time)
+int do_guides(const EvaluationContext *eval_ctx, ParticleSettings *part, ListBase *effectors, ParticleKey *state, int index, float time)
{
CurveMapping *clumpcurve = (part->child_flag & PART_CHILD_USE_CLUMP_CURVE) ? part->clumpcurve : NULL;
CurveMapping *roughcurve = (part->child_flag & PART_CHILD_USE_ROUGH_CURVE) ? part->roughcurve : NULL;
@@ -1906,7 +1915,7 @@ int do_guides(ParticleSettings *part, ListBase *effectors, ParticleKey *state, i
/* curve taper */
if (cu->taperobj)
- mul_v3_fl(vec_to_point, BKE_displist_calc_taper(eff->scene, cu->taperobj, (int)(data->strength * guidetime * 100.0f), 100));
+ mul_v3_fl(vec_to_point, BKE_displist_calc_taper(eval_ctx, eff->scene, cu->taperobj, (int)(data->strength * guidetime * 100.0f), 100));
else { /* curve size*/
if (cu->flag & CU_PATH_RADIUS) {
@@ -2089,7 +2098,7 @@ static bool psys_thread_context_init_path(
psys_thread_context_init(ctx, sim);
/*---start figuring out what is actually wanted---*/
- if (psys_in_edit_mode(scene, psys)) {
+ if (psys_in_edit_mode(sim->eval_ctx->view_layer, psys)) {
ParticleEditSettings *pset = &scene->toolsettings->particle;
if ((psys->renderdata == 0 && use_render_params == 0) && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0)
@@ -2178,7 +2187,7 @@ static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cp
ParticleSystem *psys = ctx->sim.psys;
ParticleSettings *part = psys->part;
ParticleCacheKey **cache = psys->childcache;
- ParticleCacheKey **pcache = psys_in_edit_mode(ctx->sim.scene, psys) && psys->edit ? psys->edit->pathcache : psys->pathcache;
+ ParticleCacheKey **pcache = psys_in_edit_mode(ctx->sim.eval_ctx->view_layer, psys) && psys->edit ? psys->edit->pathcache : psys->pathcache;
ParticleCacheKey *child, *key[4];
ParticleTexture ptex;
float *cpa_fuv = 0, *par_rot = 0, rot[4];
@@ -2587,7 +2596,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re
if ((psys->flag & PSYS_HAIR_DONE || psys->flag & PSYS_KEYED || psys->pointcache) == 0)
return;
- if (psys_in_edit_mode(sim->scene, psys))
+ if (psys_in_edit_mode(sim->eval_ctx->view_layer, psys))
if (psys->renderdata == 0 && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0)
return;
@@ -2707,7 +2716,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re
if (sim->psys->effectors && (psys->part->flag & PART_CHILD_EFFECT) == 0) {
for (k = 0, ca = cache[p]; k <= segments; k++, ca++)
/* ca is safe to cast, since only co and vel are used */
- do_guides(sim->psys->part, sim->psys->effectors, (ParticleKey *)ca, p, (float)k / (float)segments);
+ do_guides(sim->eval_ctx, sim->psys->part, sim->psys->effectors, (ParticleKey *)ca, p, (float)k / (float)segments);
}
/* lattices have to be calculated separately to avoid mixups between effector calculations */
@@ -2755,7 +2764,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re
if (vg_length)
MEM_freeN(vg_length);
}
-void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cfra, const bool use_render_params)
+void psys_cache_edit_paths(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, PTCacheEdit *edit, float cfra, const bool use_render_params)
{
ParticleCacheKey *ca, **cache = edit->pathcache;
ParticleEditSettings *pset = &scene->toolsettings->particle;
@@ -2946,6 +2955,7 @@ void psys_cache_edit_paths(Scene *scene, Object *ob, PTCacheEdit *edit, float cf
if (psys) {
ParticleSimulationData sim = {0};
+ sim.eval_ctx = eval_ctx;
sim.scene = scene;
sim.ob = ob;
sim.psys = psys;
@@ -3160,8 +3170,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;
}
@@ -3206,8 +3216,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)
@@ -3270,7 +3280,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;
@@ -3292,6 +3302,7 @@ static void default_particle_settings(ParticleSettings *part)
part->omat = 1;
part->use_modifier_stack = false;
+ part->draw_size = 0.1f;
}
@@ -3768,7 +3779,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
pind.bspline = (psys->part->flag & PART_HAIR_BSPLINE);
/* pind.dm disabled in editmode means we don't get effectors taken into
* account when subdividing for instance */
- pind.dm = psys_in_edit_mode(sim->scene, psys) ? NULL : psys->hair_out_dm;
+ pind.dm = psys_in_edit_mode(sim->eval_ctx->view_layer, psys) ? NULL : psys->hair_out_dm;
init_particle_interpolation(sim->ob, psys, pa, &pind);
do_particle_interpolation(psys, p, pa, t, &pind, state);
@@ -3783,7 +3794,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
mul_mat3_m4_v3(hairmat, state->vel);
if (sim->psys->effectors && (part->flag & PART_CHILD_GUIDE) == 0) {
- do_guides(sim->psys->part, sim->psys->effectors, state, p, state->time);
+ do_guides(sim->eval_ctx, sim->psys->part, sim->psys->effectors, state, p, state->time);
/* TODO: proper velocity handling */
}
@@ -4310,9 +4321,10 @@ void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3]
madd_v3_v3fl(center, yvec, bb->offset[1]);
}
-void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys)
+void psys_apply_hair_lattice(const EvaluationContext *eval_ctx, Scene *scene, Object *ob, ParticleSystem *psys)
{
ParticleSimulationData sim = {0};
+ sim.eval_ctx = eval_ctx;
sim.scene = scene;
sim.ob = ob;
sim.psys = psys;
@@ -4345,3 +4357,22 @@ void psys_apply_hair_lattice(Scene *scene, Object *ob, ParticleSystem *psys)
psys->flag |= PSYS_EDITED;
}
}
+
+
+
+/* Draw Engine */
+void (*BKE_particle_batch_cache_dirty_cb)(ParticleSystem *psys, int mode) = NULL;
+void (*BKE_particle_batch_cache_free_cb)(ParticleSystem *psys) = NULL;
+
+void BKE_particle_batch_cache_dirty(ParticleSystem *psys, int mode)
+{
+ if (psys->batch_cache) {
+ BKE_particle_batch_cache_dirty_cb(psys, mode);
+ }
+}
+void BKE_particle_batch_cache_free(ParticleSystem *psys)
+{
+ if (psys->batch_cache) {
+ BKE_particle_batch_cache_free_cb(psys);
+ }
+}
diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c
index bfcda89a635..d2ad05c20b7 100644
--- a/source/blender/blenkernel/intern/particle_child.c
+++ b/source/blender/blenkernel/intern/particle_child.c
@@ -702,7 +702,7 @@ void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim,
if (part->flag & PART_CHILD_EFFECT)
/* state is safe to cast, since only co and vel are used */
- guided = do_guides(sim->psys->part, sim->psys->effectors, (ParticleKey *)state, cpa->parent, t);
+ guided = do_guides(sim->eval_ctx, sim->psys->part, sim->psys->effectors, (ParticleKey *)state, cpa->parent, t);
if (guided == 0) {
float orco_offset[3];
diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c
index 9a7980827ad..ff8a638089f 100644
--- a/source/blender/blenkernel/intern/particle_distribute.c
+++ b/source/blender/blenkernel/intern/particle_distribute.c
@@ -312,19 +312,16 @@ static void distribute_grid(DerivedMesh *dm, ParticleSystem *psys)
static void hammersley_create(float *out, int n, int seed, float amount)
{
RNG *rng;
- double p, t, offs[2];
- int k, kk;
+
+ double offs[2], t;
rng = BLI_rng_new(31415926 + n + seed);
offs[0] = BLI_rng_get_double(rng) + (double)amount;
offs[1] = BLI_rng_get_double(rng) + (double)amount;
BLI_rng_free(rng);
- for (k = 0; k < n; k++) {
- t = 0;
- for (p = 0.5, kk = k; kk; p *= 0.5, kk >>= 1)
- if (kk & 1) /* kk mod 2 = 1 */
- t += p;
+ for (int k = 0; k < n; k++) {
+ BLI_hammersley_1D(k, &t);
out[2*k + 0] = fmod((double)k/(double)n + offs[0], 1.0);
out[2*k + 1] = fmod(t + offs[1], 1.0);
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index c5cc7c28243..ac10ad44bf1 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -78,6 +78,7 @@
#include "BKE_particle.h"
#include "BKE_global.h"
+#include "BKE_collection.h"
#include "BKE_DerivedMesh.h"
#include "BKE_object.h"
#include "BKE_material.h"
@@ -88,7 +89,8 @@
#include "BKE_modifier.h"
#include "BKE_scene.h"
#include "BKE_bvhutils.h"
-#include "BKE_depsgraph.h"
+
+#include "DEG_depsgraph.h"
#include "PIL_time.h"
@@ -980,14 +982,14 @@ void psys_get_birth_coords(ParticleSimulationData *sim, ParticleData *pa, Partic
}
/* recursively evaluate emitter parent anim at cfra */
-static void evaluate_emitter_anim(Scene *scene, Object *ob, float cfra)
+static void evaluate_emitter_anim(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float cfra)
{
if (ob->parent)
- evaluate_emitter_anim(scene, ob->parent, cfra);
+ evaluate_emitter_anim(eval_ctx, scene, ob->parent, cfra);
/* we have to force RECALC_ANIM here since where_is_objec_time only does drivers */
BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, cfra, ADT_RECALC_ANIM);
- BKE_object_where_is_calc_time(scene, ob, cfra);
+ BKE_object_where_is_calc_time(eval_ctx, scene, ob, cfra);
}
/* sets particle to the emitter surface with initial velocity & rotation */
@@ -1001,7 +1003,7 @@ void reset_particle(ParticleSimulationData *sim, ParticleData *pa, float dtime,
/* get precise emitter matrix if particle is born */
if (part->type != PART_HAIR && dtime > 0.f && pa->time < cfra && pa->time >= sim->psys->cfra) {
- evaluate_emitter_anim(sim->scene, sim->ob, pa->time);
+ evaluate_emitter_anim(sim->eval_ctx, sim->scene, sim->ob, pa->time);
psys->flag |= PSYS_OB_ANIM_RESTORE;
}
@@ -1133,7 +1135,8 @@ static void set_keyed_keys(ParticleSimulationData *sim)
int totpart = psys->totpart, k, totkeys = psys->totkeyed;
int keyed_flag = 0;
- ksim.scene= sim->scene;
+ ksim.eval_ctx = sim->eval_ctx;
+ ksim.scene = sim->scene;
/* no proper targets so let's clear and bail out */
if (psys->totkeyed==0) {
@@ -1294,7 +1297,7 @@ void psys_update_particle_tree(ParticleSystem *psys, float cfra)
static void psys_update_effectors(ParticleSimulationData *sim)
{
pdEndEffectors(&sim->psys->effectors);
- sim->psys->effectors = pdInitEffectors(sim->scene, sim->ob, sim->psys,
+ sim->psys->effectors = pdInitEffectors(sim->eval_ctx, sim->scene, sim->ob, sim->psys,
sim->psys->part->effector_weights, true);
precalc_guides(sim, sim->psys->effectors);
}
@@ -2115,7 +2118,7 @@ static void basic_integrate(ParticleSimulationData *sim, int p, float dfra, floa
tkey.time=pa->state.time;
if (part->type != PART_HAIR) {
- if (do_guides(sim->psys->part, sim->psys->effectors, &tkey, p, time)) {
+ if (do_guides(sim->eval_ctx, sim->psys->part, sim->psys->effectors, &tkey, p, time)) {
copy_v3_v3(pa->state.co,tkey.co);
/* guides don't produce valid velocity */
sub_v3_v3v3(pa->state.vel, tkey.co, pa->prev_state.co);
@@ -2896,7 +2899,6 @@ 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)
@@ -2931,7 +2933,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons
skip = 1; /* draw visualization */
else if (psys->pointcache->flag & PTCACHE_BAKING)
skip = 1; /* no need to cache paths while baking dynamics */
- else if (psys_in_edit_mode(sim->scene, psys)) {
+ else if (psys_in_edit_mode(sim->eval_ctx->view_layer, psys)) {
if ((pset->flag & PE_DRAW_PART)==0)
skip = 1;
else if (part->childtype==0 && (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED)==0)
@@ -2941,8 +2943,9 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons
/* particle instance modifier with "path" option need cached paths even if particle system doesn't */
- for (base = sim->scene->base.first; base; base= base->next) {
- ModifierData *md = modifiers_findByType(base->object, eModifierType_ParticleInstance);
+ FOREACH_SCENE_OBJECT(sim->scene, ob)
+ {
+ ModifierData *md = modifiers_findByType(ob, eModifierType_ParticleInstance);
if (md) {
ParticleInstanceModifierData *pimd = (ParticleInstanceModifierData *)md;
if (pimd->flag & eParticleInstanceFlag_Path && pimd->ob == sim->ob && pimd->psys == (psys - (ParticleSystem*)sim->ob->particlesystem.first)) {
@@ -2951,6 +2954,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons
}
}
}
+ FOREACH_SCENE_OBJECT_END
if (!skip) {
psys_cache_paths(sim, cfra, use_render_params);
@@ -3196,7 +3200,7 @@ static void do_hair_dynamics(ParticleSimulationData *sim)
psys->hair_out_dm = CDDM_copy(psys->hair_in_dm);
psys->hair_out_dm->getVertCos(psys->hair_out_dm, deformedVerts);
- clothModifier_do(psys->clmd, sim->scene, sim->ob, psys->hair_in_dm, deformedVerts);
+ clothModifier_do(psys->clmd, sim->eval_ctx, sim->scene, sim->ob, psys->hair_in_dm, deformedVerts);
CDDM_apply_vert_coords(psys->hair_out_dm, deformedVerts);
@@ -4196,7 +4200,7 @@ static int hair_needs_recalc(ParticleSystem *psys)
/* main particle update call, checks that things are ok on the large scale and
* then advances in to actual particle calculations depending on particle type */
-void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys, const bool use_render_params)
+void particle_system_update(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, ParticleSystem *psys, const bool use_render_params)
{
ParticleSimulationData sim= {0};
ParticleSettings *part = psys->part;
@@ -4210,10 +4214,11 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys, cons
cfra= BKE_scene_frame_get(scene);
- sim.scene= scene;
- sim.ob= ob;
- sim.psys= psys;
- sim.psmd= psys_get_modifier(ob, psys);
+ sim.eval_ctx = eval_ctx;
+ sim.scene = scene;
+ sim.ob = ob;
+ sim.psys = psys;
+ sim.psmd = psys_get_modifier(ob, psys);
/* system was already updated from modifier stack */
if (sim.psmd->flag & eParticleSystemFlag_psys_updated) {
@@ -4356,7 +4361,7 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys, cons
/* make sure emitter is left at correct time (particle emission can change this) */
if (psys->flag & PSYS_OB_ANIM_RESTORE) {
- evaluate_emitter_anim(scene, ob, cfra);
+ evaluate_emitter_anim(eval_ctx, scene, ob, cfra);
psys->flag &= ~PSYS_OB_ANIM_RESTORE;
}
@@ -4366,6 +4371,8 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys, cons
/* save matrix for duplicators, at rendertime the actual dupliobject's matrix is used so don't update! */
if (psys->renderdata==0)
invert_m4_m4(psys->imat, ob->obmat);
+
+ BKE_particle_batch_cache_dirty(psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
}
/* ID looper */
@@ -4396,12 +4403,30 @@ void BKE_particlesystem_id_loop(ParticleSystem *psys, ParticleSystemIDFunc func,
/* **** Depsgraph evaluation **** */
-void BKE_particle_system_eval_init(EvaluationContext *UNUSED(eval_ctx),
+void BKE_particle_system_settings_eval(const struct EvaluationContext *UNUSED(eval_ctx),
+ ParticleSystem *psys)
+{
+ if (G.debug & G_DEBUG_DEPSGRAPH) {
+ printf("%s on %s (%p)\n", __func__, psys->name, psys);
+ }
+ psys->recalc |= psys->part->recalc;
+}
+
+void BKE_particle_system_settings_recalc_clear(struct EvaluationContext *UNUSED(eval_ctx),
+ ParticleSettings *particle_settings)
+{
+ if (G.debug & G_DEBUG_DEPSGRAPH) {
+ printf("%s on %s (%p)\n", __func__, particle_settings->id.name, particle_settings);
+ }
+ particle_settings->recalc = 0;
+}
+
+void BKE_particle_system_eval_init(const struct EvaluationContext *UNUSED(eval_ctx),
Scene *scene,
Object *ob)
{
if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s on %s\n", __func__, ob->id.name);
+ printf("%s on %s (%p)\n", __func__, ob->id.name, ob);
}
BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH);
}
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index d926c96c0d8..63f2c7e5452 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -41,6 +41,7 @@
#include "BKE_paint.h"
#include "GPU_buffers.h"
+#include "GPU_immediate.h"
#include "bmesh.h"
@@ -1187,15 +1188,16 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode)
void BKE_pbvh_draw_BB(PBVH *bvh)
{
- GPU_pbvh_BB_draw_init();
+ unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 3, GWN_FETCH_FLOAT);
+ immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
for (int a = 0; a < bvh->totnode; a++) {
PBVHNode *node = &bvh->nodes[a];
- GPU_pbvh_BB_draw(node->vb.bmin, node->vb.bmax, ((node->flag & PBVH_Leaf) != 0));
+ GPU_pbvh_BB_draw(node->vb.bmin, node->vb.bmax, ((node->flag & PBVH_Leaf) != 0), pos);
}
- GPU_pbvh_BB_draw_end();
+ immUnbindProgram();
}
static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag)
@@ -2016,24 +2018,6 @@ void BKE_pbvh_node_draw(PBVHNode *node, void *data_v)
{
PBVHNodeDrawData *data = data_v;
-#if 0
- /* XXX: Just some quick code to show leaf nodes in different colors */
- float col[3];
- float spec[3] = {0.0f, 0.0f, 0.0f};
-
- if (0) { //is_partial) {
- col[0] = (rand() / (float)RAND_MAX); col[1] = col[2] = 0.6;
- }
- else {
- srand((long long)node);
- for (int i = 0; i < 3; ++i)
- col[i] = (rand() / (float)RAND_MAX) * 0.3 + 0.7;
- }
-
- GPU_basic_shader_colors(col, spec, 0, 1.0f);
- glColor3f(1, 0, 0);
-#endif
-
if (!(node->flag & PBVH_FullyHidden)) {
GPU_pbvh_buffers_draw(node->draw_buffers,
data->setMaterial,
@@ -2152,6 +2136,67 @@ void BKE_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*fnors)[3],
BKE_pbvh_draw_BB(bvh);
}
+struct PBVHNodeDrawCallbackData {
+
+ void (*draw_fn)(void *user_data, Gwn_Batch *batch);
+ void *user_data;
+ bool fast;
+};
+
+static void pbvh_node_draw_cb(PBVHNode *node, void *data_v)
+{
+ struct PBVHNodeDrawCallbackData *data = data_v;
+
+ if (!(node->flag & PBVH_FullyHidden)) {
+ Gwn_Batch *triangles = GPU_pbvh_buffers_batch_get(node->draw_buffers, data->fast);
+ if (triangles != NULL) {
+ data->draw_fn(data->user_data, triangles);
+ }
+ }
+}
+
+/**
+ * Version of #BKE_pbvh_draw that runs a callback.
+ */
+void BKE_pbvh_draw_cb(
+ PBVH *bvh, float (*planes)[4], float (*fnors)[3], bool fast,
+ void (*draw_fn)(void *user_data, Gwn_Batch *batch), void *user_data)
+{
+ struct PBVHNodeDrawCallbackData draw_data = {
+ .fast = fast,
+ .draw_fn = draw_fn,
+ .user_data = user_data,
+ };
+ PBVHNode **nodes;
+ int totnode;
+
+ for (int a = 0; a < bvh->totnode; a++)
+ pbvh_node_check_diffuse_changed(bvh, &bvh->nodes[a]);
+
+ BKE_pbvh_search_gather(bvh, update_search_cb, SET_INT_IN_POINTER(PBVH_UpdateNormals | PBVH_UpdateDrawBuffers),
+ &nodes, &totnode);
+
+ pbvh_update_normals(bvh, nodes, totnode, fnors);
+ pbvh_update_draw_buffers(bvh, nodes, totnode);
+
+ if (nodes) MEM_freeN(nodes);
+
+ if (planes) {
+ BKE_pbvh_search_callback(
+ bvh, BKE_pbvh_node_planes_contain_AABB,
+ planes, pbvh_node_draw_cb, &draw_data);
+ }
+ else {
+ BKE_pbvh_search_callback(
+ bvh, NULL,
+ NULL, pbvh_node_draw_cb, &draw_data);
+ }
+#if 0
+ if (G.debug_value == 14)
+ pbvh_draw_BB(bvh);
+#endif
+}
+
void BKE_pbvh_grids_update(PBVH *bvh, CCGElem **grids, void **gridfaces,
DMFlagMat *flagmats, BLI_bitmap **grid_hidden)
{
@@ -2361,24 +2406,24 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node,
vi->vmask = CustomData_get_layer(bvh->vdata, CD_PAINT_MASK);
}
-void pbvh_show_diffuse_color_set(PBVH *bvh, bool show_diffuse_color)
+bool pbvh_has_mask(PBVH *bvh)
{
- bool has_mask = false;
-
switch (bvh->type) {
case PBVH_GRIDS:
- has_mask = (bvh->gridkey.has_mask != 0);
- break;
+ return (bvh->gridkey.has_mask != 0);
case PBVH_FACES:
- has_mask = (bvh->vdata && CustomData_get_layer(bvh->vdata,
- CD_PAINT_MASK));
- break;
+ return (bvh->vdata && CustomData_get_layer(bvh->vdata,
+ CD_PAINT_MASK));
case PBVH_BMESH:
- has_mask = (bvh->bm && (CustomData_get_offset(&bvh->bm->vdata, CD_PAINT_MASK) != -1));
- break;
+ return (bvh->bm && (CustomData_get_offset(&bvh->bm->vdata, CD_PAINT_MASK) != -1));
}
- bvh->show_diffuse_color = !has_mask || show_diffuse_color;
+ return false;
+}
+
+void pbvh_show_diffuse_color_set(PBVH *bvh, bool show_diffuse_color)
+{
+ bvh->show_diffuse_color = !pbvh_has_mask(bvh) || show_diffuse_color;
}
void pbvh_show_mask_set(PBVH *bvh, bool show_mask)
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 7a1b378b3c4..b794fcfd929 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -3509,13 +3509,14 @@ PointCache *BKE_ptcache_copy_list(ListBase *ptcaches_new, const ListBase *ptcach
* every user action changing stuff, and then it runs a complete bake??? (ton) */
/* Baking */
-void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene)
+void BKE_ptcache_quick_cache_all(Main *bmain, Scene *scene, ViewLayer *view_layer)
{
PTCacheBaker baker;
memset(&baker, 0, sizeof(baker));
baker.main = bmain;
baker.scene = scene;
+ baker.view_layer = view_layer;
baker.bake = 0;
baker.render = 0;
baker.anim_init = 0;
@@ -3541,6 +3542,8 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
{
Main *bmain = baker->main;
Scene *scene = baker->scene;
+ ViewLayer *view_layer = baker->view_layer;
+ struct Depsgraph *depsgraph = baker->depsgraph;
Scene *sce_iter; /* SETLOOPER macro only */
Base *base;
ListBase pidlist;
@@ -3603,7 +3606,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
}
}
else {
- for (SETLOOPER(scene, sce_iter, base)) {
+ for (SETLOOPER_VIEW_LAYER(scene, view_layer, sce_iter, base)) {
/* cache/bake everything in the scene */
BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
@@ -3659,7 +3662,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
stime = ptime = PIL_check_seconds_timer();
for (int fr = CFRA; fr <= endframe; fr += baker->quick_step, CFRA = fr) {
- BKE_scene_update_for_newframe(G.main->eval_ctx, bmain, scene, scene->lay);
+ BKE_scene_graph_update_for_newframe(G.main->eval_ctx, depsgraph, bmain, scene, view_layer);
if (baker->update_progress) {
float progress = ((float)(CFRA - startframe)/(float)(endframe - startframe));
@@ -3714,7 +3717,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
}
}
else {
- for (SETLOOPER(scene, sce_iter, base)) {
+ for (SETLOOPER_VIEW_LAYER(scene, view_layer, sce_iter, base)) {
BKE_ptcache_ids_from_object(&pidlist, base->object, scene, MAX_DUPLI_RECUR);
for (pid=pidlist.first; pid; pid=pid->next) {
@@ -3745,7 +3748,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
CFRA = cfrao;
if (bake) { /* already on cfra unless baking */
- BKE_scene_update_for_newframe(bmain->eval_ctx, bmain, scene, scene->lay);
+ BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
}
/* TODO: call redraw all windows somehow */
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index 03eb83376e7..bd4b817c8cd 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -55,9 +55,9 @@
#include "DNA_scene_types.h"
#include "BKE_cdderivedmesh.h"
-#include "BKE_depsgraph.h"
#include "BKE_effect.h"
#include "BKE_global.h"
+#include "BKE_group.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_mesh.h"
@@ -91,26 +91,30 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
if (rbw->physics_world) {
/* free physics references, we assume that all physics objects in will have been added to the world */
- GroupObject *go;
if (rbw->constraints) {
- for (go = rbw->constraints->gobject.first; go; go = go->next) {
- if (go->ob && go->ob->rigidbody_constraint) {
- RigidBodyCon *rbc = go->ob->rigidbody_constraint;
-
- if (rbc->physics_constraint)
+ FOREACH_GROUP_OBJECT(rbw->constraints, object)
+ {
+ if (object->rigidbody_constraint) {
+ RigidBodyCon *rbc = object->rigidbody_constraint;
+ if (rbc->physics_constraint) {
RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
+ }
}
}
+ FOREACH_GROUP_OBJECT_END
}
- if (rbw->group) {
- for (go = rbw->group->gobject.first; go; go = go->next) {
- if (go->ob && go->ob->rigidbody_object) {
- RigidBodyOb *rbo = go->ob->rigidbody_object;
- if (rbo->physics_object)
+ if (rbw->group) {
+ FOREACH_GROUP_OBJECT(rbw->group, object)
+ {
+ if (object->rigidbody_object) {
+ RigidBodyOb *rbo = object->rigidbody_object;
+ if (rbo->physics_object) {
RB_dworld_remove_body(rbw->physics_world, rbo->physics_object);
+ }
}
}
+ FOREACH_GROUP_OBJECT_END
}
/* free dynamics world */
RB_dworld_delete(rbw->physics_world);
@@ -1125,7 +1129,6 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob)
RigidBodyWorld *rbw = scene->rigidbody_world;
RigidBodyOb *rbo = ob->rigidbody_object;
RigidBodyCon *rbc;
- GroupObject *go;
int i;
if (rbw) {
@@ -1145,8 +1148,8 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob)
/* remove object from rigid body constraints */
if (rbw->constraints) {
- for (go = rbw->constraints->gobject.first; go; go = go->next) {
- Object *obt = go->ob;
+ FOREACH_GROUP_OBJECT(rbw->constraints, obt)
+ {
if (obt && obt->rigidbody_constraint) {
rbc = obt->rigidbody_constraint;
if (ELEM(ob, rbc->ob1, rbc->ob2)) {
@@ -1154,6 +1157,7 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob)
}
}
}
+ FOREACH_GROUP_OBJECT_END
}
}
@@ -1187,20 +1191,22 @@ void BKE_rigidbody_remove_constraint(Scene *scene, Object *ob)
/* Update object array and rigid body count so they're in sync with the rigid body group */
static void rigidbody_update_ob_array(RigidBodyWorld *rbw)
{
- GroupObject *go;
int i, n;
- n = BLI_listbase_count(&rbw->group->gobject);
+ n = BLI_listbase_count(&rbw->group->view_layer->object_bases);
if (rbw->numbodies != n) {
rbw->numbodies = n;
rbw->objects = realloc(rbw->objects, sizeof(Object *) * rbw->numbodies);
}
- for (go = rbw->group->gobject.first, i = 0; go; go = go->next, i++) {
- Object *ob = go->ob;
- rbw->objects[i] = ob;
+ i = 0;
+ FOREACH_GROUP_OBJECT(rbw->group, object)
+ {
+ rbw->objects[i] = object;
+ i++;
}
+ FOREACH_GROUP_OBJECT_END
}
static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw)
@@ -1223,7 +1229,7 @@ static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw)
rigidbody_update_ob_array(rbw);
}
-static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *ob, RigidBodyOb *rbo)
+static void rigidbody_update_sim_ob(const struct EvaluationContext *eval_ctx, Scene *scene, RigidBodyWorld *rbw, Object *ob, RigidBodyOb *rbo)
{
float loc[3];
float rot[4];
@@ -1271,7 +1277,7 @@ static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *o
ListBase *effectors;
/* get effectors present in the group specified by effector_weights */
- effectors = pdInitEffectors(scene, ob, NULL, effector_weights, true);
+ effectors = pdInitEffectors(eval_ctx, scene, ob, NULL, effector_weights, true);
if (effectors) {
float eff_force[3] = {0.0f, 0.0f, 0.0f};
float eff_loc[3], eff_vel[3];
@@ -1312,10 +1318,8 @@ static void rigidbody_update_sim_ob(Scene *scene, RigidBodyWorld *rbw, Object *o
*
* \param rebuild Rebuild entire simulation
*/
-static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, bool rebuild)
+static void rigidbody_update_simulation(const struct EvaluationContext *eval_ctx, Scene *scene, RigidBodyWorld *rbw, bool rebuild)
{
- GroupObject *go;
-
/* update world */
if (rebuild)
BKE_rigidbody_validate_sim_world(scene, rbw, true);
@@ -1328,28 +1332,26 @@ static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, bool
* Memory management needs redesign here, this is just a dirty workaround.
*/
if (rebuild && rbw->constraints) {
- for (go = rbw->constraints->gobject.first; go; go = go->next) {
- Object *ob = go->ob;
- if (ob) {
- RigidBodyCon *rbc = ob->rigidbody_constraint;
- if (rbc && rbc->physics_constraint) {
- RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
- RB_constraint_delete(rbc->physics_constraint);
- rbc->physics_constraint = NULL;
- }
+ FOREACH_GROUP_OBJECT(rbw->constraints, ob)
+ {
+ RigidBodyCon *rbc = ob->rigidbody_constraint;
+ if (rbc && rbc->physics_constraint) {
+ RB_dworld_remove_constraint(rbw->physics_world, rbc->physics_constraint);
+ RB_constraint_delete(rbc->physics_constraint);
+ rbc->physics_constraint = NULL;
}
}
+ FOREACH_GROUP_OBJECT_END
}
/* update objects */
- for (go = rbw->group->gobject.first; go; go = go->next) {
- Object *ob = go->ob;
-
- if (ob && ob->type == OB_MESH) {
+ FOREACH_GROUP_OBJECT(rbw->group, ob)
+ {
+ if (ob->type == OB_MESH) {
/* validate that we've got valid object set up here... */
RigidBodyOb *rbo = ob->rigidbody_object;
/* update transformation matrix of the object so we don't get a frame of lag for simple animations */
- BKE_object_where_is_calc(scene, ob);
+ BKE_object_where_is_calc(eval_ctx, scene, ob);
if (rbo == NULL) {
/* Since this object is included in the sim group but doesn't have
@@ -1383,65 +1385,62 @@ static void rigidbody_update_simulation(Scene *scene, RigidBodyWorld *rbw, bool
}
/* update simulation object... */
- rigidbody_update_sim_ob(scene, rbw, ob, rbo);
+ rigidbody_update_sim_ob(eval_ctx, scene, rbw, ob, rbo);
}
}
+ FOREACH_GROUP_OBJECT_END
/* update constraints */
if (rbw->constraints == NULL) /* no constraints, move on */
return;
- for (go = rbw->constraints->gobject.first; go; go = go->next) {
- Object *ob = go->ob;
- if (ob) {
- /* validate that we've got valid object set up here... */
- RigidBodyCon *rbc = ob->rigidbody_constraint;
- /* update transformation matrix of the object so we don't get a frame of lag for simple animations */
- BKE_object_where_is_calc(scene, ob);
+ FOREACH_GROUP_OBJECT(rbw->constraints, ob)
+ {
+ /* validate that we've got valid object set up here... */
+ RigidBodyCon *rbc = ob->rigidbody_constraint;
+ /* update transformation matrix of the object so we don't get a frame of lag for simple animations */
+ BKE_object_where_is_calc(eval_ctx, scene, ob);
- if (rbc == NULL) {
- /* Since this object is included in the group but doesn't have
- * constraint settings (perhaps it was added manually), add!
- */
- ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, RBC_TYPE_FIXED);
- rigidbody_validate_sim_constraint(rbw, ob, true);
+ if (rbc == NULL) {
+ /* Since this object is included in the group but doesn't have
+ * constraint settings (perhaps it was added manually), add!
+ */
+ ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, RBC_TYPE_FIXED);
+ rigidbody_validate_sim_constraint(rbw, ob, true);
- rbc = ob->rigidbody_constraint;
+ rbc = ob->rigidbody_constraint;
+ }
+ else {
+ /* perform simulation data updates as tagged */
+ if (rebuild) {
+ /* World has been rebuilt so rebuild constraint */
+ rigidbody_validate_sim_constraint(rbw, ob, true);
}
- else {
- /* perform simulation data updates as tagged */
- if (rebuild) {
- /* World has been rebuilt so rebuild constraint */
- rigidbody_validate_sim_constraint(rbw, ob, true);
- }
- else if (rbc->flag & RBC_FLAG_NEEDS_VALIDATE) {
- rigidbody_validate_sim_constraint(rbw, ob, false);
- }
- rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE;
+ else if (rbc->flag & RBC_FLAG_NEEDS_VALIDATE) {
+ rigidbody_validate_sim_constraint(rbw, ob, false);
}
+ rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE;
}
}
+ FOREACH_GROUP_OBJECT_END
}
static void rigidbody_update_simulation_post_step(RigidBodyWorld *rbw)
{
- GroupObject *go;
-
- for (go = rbw->group->gobject.first; go; go = go->next) {
- Object *ob = go->ob;
-
- if (ob) {
- RigidBodyOb *rbo = ob->rigidbody_object;
- /* reset kinematic state for transformed objects */
- if (rbo && (ob->flag & SELECT) && (G.moving & G_TRANSFORM_OBJ)) {
- RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED);
- RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo));
- /* deactivate passive objects so they don't interfere with deactivation of active objects */
- if (rbo->type == RBO_TYPE_PASSIVE)
- RB_body_deactivate(rbo->physics_object);
- }
+ FOREACH_GROUP_BASE(rbw->group, base)
+ {
+ Object *ob = base->object;
+ RigidBodyOb *rbo = ob->rigidbody_object;
+ /* Reset kinematic state for transformed objects. */
+ if (rbo && (base->flag & BASE_SELECTED) && (G.moving & G_TRANSFORM_OBJ)) {
+ RB_body_set_kinematic_state(rbo->physics_object, rbo->flag & RBO_FLAG_KINEMATIC || rbo->flag & RBO_FLAG_DISABLED);
+ RB_body_set_mass(rbo->physics_object, RBO_GET_MASS(rbo));
+ /* Deactivate passive objects so they don't interfere with deactivation of active objects. */
+ if (rbo->type == RBO_TYPE_PASSIVE)
+ RB_body_deactivate(rbo->physics_object);
}
}
+ FOREACH_GROUP_BASE_END
}
bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float ctime)
@@ -1556,7 +1555,7 @@ void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw)
/* Rebuild rigid body world */
/* NOTE: this needs to be called before frame update to work correctly */
-void BKE_rigidbody_rebuild_world(Scene *scene, float ctime)
+void BKE_rigidbody_rebuild_world(const struct EvaluationContext *eval_ctx, Scene *scene, float ctime)
{
RigidBodyWorld *rbw = scene->rigidbody_world;
PointCache *cache;
@@ -1568,14 +1567,14 @@ void BKE_rigidbody_rebuild_world(Scene *scene, float ctime)
cache = rbw->pointcache;
/* flag cache as outdated if we don't have a world or number of objects in the simulation has changed */
- if (rbw->physics_world == NULL || rbw->numbodies != BLI_listbase_count(&rbw->group->gobject)) {
+ if (rbw->physics_world == NULL || rbw->numbodies != BLI_listbase_count(&rbw->group->view_layer->object_bases)) {
cache->flag |= PTCACHE_OUTDATED;
}
if (ctime == startframe + 1 && rbw->ltime == startframe) {
if (cache->flag & PTCACHE_OUTDATED) {
BKE_ptcache_id_reset(scene, &pid, PTCACHE_RESET_OUTDATED);
- rigidbody_update_simulation(scene, rbw, true);
+ rigidbody_update_simulation(eval_ctx, scene, rbw, true);
BKE_ptcache_validate(cache, (int)ctime);
cache->last_exact = 0;
cache->flag &= ~PTCACHE_REDO_NEEDED;
@@ -1584,7 +1583,7 @@ void BKE_rigidbody_rebuild_world(Scene *scene, float ctime)
}
/* Run RigidBody simulation for the specified physics world */
-void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
+void BKE_rigidbody_do_simulation(const struct EvaluationContext *eval_ctx, Scene *scene, float ctime)
{
float timestep;
RigidBodyWorld *rbw = scene->rigidbody_world;
@@ -1622,14 +1621,14 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime)
}
/* advance simulation, we can only step one frame forward */
- if (can_simulate) {
+ if (ctime == rbw->ltime + 1) {
/* write cache for first frame when on second frame */
if (rbw->ltime == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact == 0)) {
BKE_ptcache_write(&pid, startframe);
}
/* update and validate simulation */
- rigidbody_update_simulation(scene, rbw, false);
+ rigidbody_update_simulation(eval_ctx, scene, rbw, false);
/* calculate how much time elapsed since last step in seconds */
timestep = 1.0f / (float)FPS * (ctime - rbw->ltime) * rbw->time_scale;
@@ -1673,8 +1672,8 @@ void BKE_rigidbody_sync_transforms(RigidBodyWorld *rbw, Object *ob, float ctime)
void BKE_rigidbody_aftertrans_update(Object *ob, float loc[3], float rot[3], float quat[4], float rotAxis[3], float rotAngle) {}
bool BKE_rigidbody_check_sim_running(RigidBodyWorld *rbw, float ctime) { return false; }
void BKE_rigidbody_cache_reset(RigidBodyWorld *rbw) {}
-void BKE_rigidbody_rebuild_world(Scene *scene, float ctime) {}
-void BKE_rigidbody_do_simulation(Scene *scene, float ctime) {}
+void BKE_rigidbody_rebuild_world(const struct EvaluationContext *eval_ctx, Scene *scene, float ctime) {}
+void BKE_rigidbody_do_simulation(const struct EvaluationContext *eval_ctx, Scene *scene, float ctime) {}
#ifdef __GNUC__
# pragma GCC diagnostic pop
@@ -1685,7 +1684,7 @@ void BKE_rigidbody_do_simulation(Scene *scene, float ctime) {}
/* -------------------- */
/* Depsgraph evaluation */
-void BKE_rigidbody_rebuild_sim(EvaluationContext *UNUSED(eval_ctx),
+void BKE_rigidbody_rebuild_sim(const struct EvaluationContext *eval_ctx,
Scene *scene)
{
float ctime = BKE_scene_frame_get(scene);
@@ -1696,11 +1695,11 @@ void BKE_rigidbody_rebuild_sim(EvaluationContext *UNUSED(eval_ctx),
/* rebuild sim data (i.e. after resetting to start of timeline) */
if (BKE_scene_check_rigidbody_active(scene)) {
- BKE_rigidbody_rebuild_world(scene, ctime);
+ BKE_rigidbody_rebuild_world(eval_ctx, scene, ctime);
}
}
-void BKE_rigidbody_eval_simulation(EvaluationContext *UNUSED(eval_ctx),
+void BKE_rigidbody_eval_simulation(const struct EvaluationContext *eval_ctx,
Scene *scene)
{
float ctime = BKE_scene_frame_get(scene);
@@ -1711,11 +1710,11 @@ void BKE_rigidbody_eval_simulation(EvaluationContext *UNUSED(eval_ctx),
/* evaluate rigidbody sim */
if (BKE_scene_check_rigidbody_active(scene)) {
- BKE_rigidbody_do_simulation(scene, ctime);
+ BKE_rigidbody_do_simulation(eval_ctx, scene, ctime);
}
}
-void BKE_rigidbody_object_sync_transforms(EvaluationContext *UNUSED(eval_ctx),
+void BKE_rigidbody_object_sync_transforms(const struct EvaluationContext *UNUSED(eval_ctx),
Scene *scene,
Object *ob)
{
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 13cd991a73b..91e03337397 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -49,6 +49,7 @@
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
#include "DNA_windowmanager_types.h"
+#include "DNA_workspace_types.h"
#include "DNA_gpencil_types.h"
#include "BLI_math.h"
@@ -67,8 +68,8 @@
#include "BKE_action.h"
#include "BKE_armature.h"
#include "BKE_cachefile.h"
+#include "BKE_collection.h"
#include "BKE_colortools.h"
-#include "BKE_depsgraph.h"
#include "BKE_editmesh.h"
#include "BKE_fcurve.h"
#include "BKE_freestyle.h"
@@ -78,6 +79,7 @@
#include "BKE_icons.h"
#include "BKE_idprop.h"
#include "BKE_image.h"
+#include "BKE_layer.h"
#include "BKE_library.h"
#include "BKE_library_remap.h"
#include "BKE_linestyle.h"
@@ -92,9 +94,13 @@
#include "BKE_sequencer.h"
#include "BKE_sound.h"
#include "BKE_unit.h"
+#include "BKE_workspace.h"
#include "BKE_world.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_debug.h"
+#include "DEG_depsgraph_query.h"
#include "RE_engine.h"
@@ -107,6 +113,8 @@
const char *RE_engine_id_BLENDER_RENDER = "BLENDER_RENDER";
const char *RE_engine_id_BLENDER_GAME = "BLENDER_GAME";
+const char *RE_engine_id_BLENDER_CLAY = "BLENDER_CLAY";
+const char *RE_engine_id_BLENDER_EEVEE = "BLENDER_EEVEE";
const char *RE_engine_id_CYCLES = "CYCLES";
void free_avicodecdata(AviCodecData *acd)
@@ -157,25 +165,37 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons
const int flag_subdata = flag | LIB_ID_CREATE_NO_USER_REFCOUNT;
sce_dst->ed = NULL;
- sce_dst->theDag = NULL;
- sce_dst->depsgraph = NULL;
+ sce_dst->depsgraph_hash = NULL;
sce_dst->obedit = NULL;
- sce_dst->stats = NULL;
sce_dst->fps_info = NULL;
- BLI_duplicatelist(&(sce_dst->base), &(sce_src->base));
- for (Base *base_dst = sce_dst->base.first, *base_src = sce_src->base.first;
- base_dst;
- base_dst = base_dst->next, base_src = base_src->next)
+ /* layers and collections */
+ sce_dst->collection = MEM_dupallocN(sce_src->collection);
+ SceneCollection *mc_src = BKE_collection_master(&sce_src->id);
+ SceneCollection *mc_dst = BKE_collection_master(&sce_dst->id);
+
+ /* Recursively creates a new SceneCollection tree. */
+ BKE_collection_copy_data(mc_dst, mc_src, flag_subdata);
+
+ IDPropertyTemplate val = {0};
+ BLI_duplicatelist(&sce_dst->view_layers, &sce_src->view_layers);
+ for (ViewLayer *view_layer_src = sce_src->view_layers.first, *view_layer_dst = sce_dst->view_layers.first;
+ view_layer_src;
+ view_layer_src = view_layer_src->next, view_layer_dst = view_layer_dst->next)
{
- if (base_src == sce_src->basact) {
- sce_dst->basact = base_dst;
- }
+ BKE_view_layer_copy_data(view_layer_dst, view_layer_src, mc_dst, mc_src, flag_subdata);
+ }
+
+ sce_dst->collection_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ if (sce_src->collection_properties) {
+ IDP_MergeGroup_ex(sce_dst->collection_properties, sce_src->collection_properties, true, flag_subdata);
+ }
+ sce_dst->layer_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ if (sce_src->layer_properties) {
+ IDP_MergeGroup_ex(sce_dst->layer_properties, sce_src->layer_properties, true, flag_subdata);
}
BLI_duplicatelist(&(sce_dst->markers), &(sce_src->markers));
- BLI_duplicatelist(&(sce_dst->transform_spaces), &(sce_src->transform_spaces));
- BLI_duplicatelist(&(sce_dst->r.layers), &(sce_src->r.layers));
BLI_duplicatelist(&(sce_dst->r.views), &(sce_src->r.views));
BKE_keyingsets_copy(&(sce_dst->keyingsets), &(sce_src->keyingsets));
@@ -190,17 +210,6 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons
sce_dst->rigidbody_world = BKE_rigidbody_world_copy(sce_src->rigidbody_world, flag_subdata);
}
- /* copy Freestyle settings */
- for (SceneRenderLayer *srl_dst = sce_dst->r.layers.first, *srl_src = sce_src->r.layers.first;
- srl_src;
- srl_dst = srl_dst->next, srl_src = srl_src->next)
- {
- if (srl_dst->prop != NULL) {
- srl_dst->prop = IDP_CopyProperty_ex(srl_dst->prop, flag_subdata);
- }
- BKE_freestyle_config_copy(&srl_dst->freestyleConfig, &srl_src->freestyleConfig, flag_subdata);
- }
-
/* copy color management settings */
BKE_color_managed_display_settings_copy(&sce_dst->display_settings, &sce_src->display_settings);
BKE_color_managed_view_settings_copy(&sce_dst->view_settings, &sce_src->view_settings);
@@ -289,16 +298,14 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
* But for now, let's keep it well isolated here. */
if (type == SCE_COPY_EMPTY) {
ToolSettings *ts;
- ListBase rl, rv;
+ ListBase rv;
sce_copy = BKE_scene_add(bmain, sce->id.name + 2);
- rl = sce_copy->r.layers;
rv = sce_copy->r.views;
curvemapping_free_data(&sce_copy->r.mblur_shutter_curve);
sce_copy->r = sce->r;
- sce_copy->r.layers = rl;
- sce_copy->r.actlay = 0;
+ sce_copy->active_view_layer = 0;
sce_copy->r.views = rv;
sce_copy->unit = sce->unit;
sce_copy->physics_settings = sce->physics_settings;
@@ -396,8 +403,8 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
if (type == SCE_COPY_FULL) {
/* Copy Freestyle LineStyle datablocks. */
- for (SceneRenderLayer *srl_dst = sce_copy->r.layers.first; srl_dst; srl_dst = srl_dst->next) {
- for (FreestyleLineSet *lineset = srl_dst->freestyleConfig.linesets.first; lineset; lineset = lineset->next) {
+ for (ViewLayer *view_layer_dst = sce_copy->view_layers.first; view_layer_dst; view_layer_dst = view_layer_dst->next) {
+ for (FreestyleLineSet *lineset = view_layer_dst->freestyle_config.linesets.first; lineset; lineset = lineset->next) {
if (lineset->linestyle) {
/* XXX Not copying anim/actions here? */
BKE_id_copy_ex(bmain, (ID *)lineset->linestyle, (ID **)&lineset->linestyle, 0, false);
@@ -449,17 +456,13 @@ void BKE_scene_make_local(Main *bmain, Scene *sce, const bool lib_local)
}
/** Free (or release) any data used by this scene (does not free the scene itself). */
-void BKE_scene_free(Scene *sce)
+void BKE_scene_free_ex(Scene *sce, const bool do_id_user)
{
- SceneRenderLayer *srl;
-
BKE_animdata_free((ID *)sce, false);
/* check all sequences */
BKE_sequencer_clear_scene_in_allseqs(G.main, sce);
- sce->basact = NULL;
- BLI_freelistN(&sce->base);
BKE_sequencer_editing_free(sce);
BKE_keyingsets_free(&sce->keyingsets);
@@ -487,17 +490,7 @@ void BKE_scene_free(Scene *sce)
sce->r.ffcodecdata.properties = NULL;
}
- for (srl = sce->r.layers.first; srl; srl = srl->next) {
- if (srl->prop != NULL) {
- IDP_FreeProperty(srl->prop);
- MEM_freeN(srl->prop);
- }
- BKE_freestyle_config_free(&srl->freestyleConfig);
- }
-
BLI_freelistN(&sce->markers);
- BLI_freelistN(&sce->transform_spaces);
- BLI_freelistN(&sce->r.layers);
BLI_freelistN(&sce->r.views);
if (sce->toolsettings) {
@@ -532,11 +525,8 @@ void BKE_scene_free(Scene *sce)
sce->toolsettings = NULL;
}
- DAG_scene_free(sce);
- if (sce->depsgraph)
- DEG_graph_free(sce->depsgraph);
-
- MEM_SAFE_FREE(sce->stats);
+ BKE_scene_free_depsgraph_hash(sce);
+
MEM_SAFE_FREE(sce->fps_info);
BKE_sound_destroy_scene(sce);
@@ -545,6 +535,37 @@ void BKE_scene_free(Scene *sce)
BKE_previewimg_free(&sce->preview);
curvemapping_free_data(&sce->r.mblur_shutter_curve);
+
+ for (ViewLayer *view_layer = sce->view_layers.first, *view_layer_next; view_layer; view_layer = view_layer_next) {
+ view_layer_next = view_layer->next;
+
+ BLI_remlink(&sce->view_layers, view_layer);
+ BKE_view_layer_free_ex(view_layer, do_id_user);
+ }
+
+ /* Master Collection */
+ BKE_collection_master_free(&sce->id, do_id_user);
+ MEM_freeN(sce->collection);
+ sce->collection = NULL;
+
+ /* LayerCollection engine settings. */
+ if (sce->collection_properties) {
+ IDP_FreeProperty(sce->collection_properties);
+ MEM_freeN(sce->collection_properties);
+ sce->collection_properties = NULL;
+ }
+
+ /* Render engine setting. */
+ if (sce->layer_properties) {
+ IDP_FreeProperty(sce->layer_properties);
+ MEM_freeN(sce->layer_properties);
+ sce->layer_properties = NULL;
+ }
+}
+
+void BKE_scene_free(Scene *sce)
+{
+ BKE_scene_free_ex(sce, true);
}
void BKE_scene_init(Scene *sce)
@@ -748,7 +769,7 @@ void BKE_scene_init(Scene *sce)
sce->r.ffcodecdata.audio_bitrate = 192;
sce->r.ffcodecdata.audio_channels = 2;
- BLI_strncpy(sce->r.engine, RE_engine_id_BLENDER_RENDER, sizeof(sce->r.engine));
+ BKE_viewrender_init(&sce->view_render);
sce->audio.distance_model = 2.0f;
sce->audio.doppler_factor = 1.0f;
@@ -761,7 +782,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);
@@ -800,7 +820,7 @@ void BKE_scene_init(Scene *sce)
sce->gm.angulardeactthreshold = 1.0f;
sce->gm.deactivationtime = 0.0f;
- sce->gm.flag = GAME_DISPLAY_LISTS;
+ sce->gm.flag = 0;
sce->gm.matmode = GAME_MAT_MULTITEX;
sce->gm.obstacleSimulation = OBSTSIMULATION_NONE;
@@ -894,6 +914,20 @@ void BKE_scene_init(Scene *sce)
sce->toolsettings->gpencil_v2d_align = GP_PROJECT_VIEWSPACE;
sce->toolsettings->gpencil_seq_align = GP_PROJECT_VIEWSPACE;
sce->toolsettings->gpencil_ima_align = GP_PROJECT_VIEWSPACE;
+
+ /* Master Collection */
+ sce->collection = MEM_callocN(sizeof(SceneCollection), "Master Collection");
+ BLI_strncpy(sce->collection->name, "Master Collection", sizeof(sce->collection->name));
+
+ /* Engine settings */
+ IDPropertyTemplate val = {0};
+ sce->collection_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ BKE_layer_collection_engine_settings_create(sce->collection_properties);
+
+ sce->layer_properties = IDP_New(IDP_GROUP, &val, ROOT_PROP);
+ BKE_view_layer_engine_settings_create(sce->layer_properties);
+
+ BKE_view_layer_add(sce, "View Layer");
}
Scene *BKE_scene_add(Main *bmain, const char *name)
@@ -909,37 +943,40 @@ 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);
@@ -954,30 +991,20 @@ void BKE_scene_set_background(Main *bmain, Scene *scene)
/* group flags again */
for (group = bmain->group.first; group; group = group->id.next) {
- for (go = group->gobject.first; go; go = go->next) {
- if (go->ob) {
- go->ob->flag |= OB_FROMGROUP;
- }
+ FOREACH_GROUP_OBJECT(group, object)
+ {
+ object->flag |= OB_FROMGROUP;
}
+ FOREACH_GROUP_OBJECT_END
}
- /* sort baselist for scene and sets */
- for (sce = scene; sce; sce = sce->set)
- DAG_scene_relations_rebuild(bmain, sce);
-
/* copy layers and flags from bases to objects */
- for (base = scene->base.first; base; base = base->next) {
- ob = base->object;
- ob->lay = base->lay;
-
- /* group patch... */
- base->flag &= ~(OB_FROMGROUP);
- flag = ob->flag & (OB_FROMGROUP);
- base->flag |= flag;
-
- /* not too nice... for recovering objects with lost data */
- //if (ob->pose == NULL) base->flag &= ~OB_POSEMODE;
- ob->flag = base->flag;
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ ob = base->object;
+ /* group patch... */
+ BKE_scene_object_base_flag_sync_from_base(base);
+ }
}
/* no full animation update, this to enable render code to work (render code calls own animation updates) */
}
@@ -997,8 +1024,9 @@ Scene *BKE_scene_set_name(Main *bmain, const char *name)
}
/* Used by metaballs, return *all* objects (including duplis) existing in the scene (including scene's sets) */
-int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
- Scene **scene, int val, Base **base, Object **ob)
+int BKE_scene_base_iter_next(
+ const EvaluationContext *eval_ctx, SceneBaseIter *iter,
+ Scene **scene, int val, Base **base, Object **ob)
{
bool run_again = true;
@@ -1016,17 +1044,19 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
/* the first base */
if (iter->phase == F_START) {
- *base = (*scene)->base.first;
+ ViewLayer *view_layer = eval_ctx->view_layer;
+ *base = view_layer->object_bases.first;
if (*base) {
*ob = (*base)->object;
iter->phase = F_SCENE;
}
else {
- /* exception: empty scene */
+ /* exception: empty scene layer */
while ((*scene)->set) {
(*scene) = (*scene)->set;
- if ((*scene)->base.first) {
- *base = (*scene)->base.first;
+ ViewLayer *view_layer_set = BKE_view_layer_from_scene_get((*scene));
+ if (view_layer_set->object_bases.first) {
+ *base = view_layer_set->object_bases.first;
*ob = (*base)->object;
iter->phase = F_SCENE;
break;
@@ -1045,8 +1075,9 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
/* (*scene) is finished, now do the set */
while ((*scene)->set) {
(*scene) = (*scene)->set;
- if ((*scene)->base.first) {
- *base = (*scene)->base.first;
+ ViewLayer *view_layer_set = BKE_view_layer_from_scene_get((*scene));
+ if (view_layer_set->object_bases.first) {
+ *base = view_layer_set->object_bases.first;
*ob = (*base)->object;
break;
}
@@ -1080,7 +1111,7 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
}
/* handle dupli's */
if (iter->dupob) {
- (*base)->flag |= OB_FROMDUPLI;
+ (*base)->flag_legacy |= OB_FROMDUPLI;
*ob = iter->dupob->ob;
iter->phase = F_DUPLI;
@@ -1099,7 +1130,7 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
}
else if (iter->phase == F_DUPLI) {
iter->phase = F_SCENE;
- (*base)->flag &= ~OB_FROMDUPLI;
+ (*base)->flag_legacy &= ~OB_FROMDUPLI;
if (iter->dupli_refob) {
/* Restore last object's real matrix. */
@@ -1124,13 +1155,15 @@ int BKE_scene_base_iter_next(EvaluationContext *eval_ctx, SceneBaseIter *iter,
return iter->phase;
}
-Object *BKE_scene_camera_find(Scene *sc)
+Scene *BKE_scene_find_from_collection(const Main *bmain, const SceneCollection *scene_collection)
{
- Base *base;
-
- for (base = sc->base.first; base; base = base->next)
- if (base->object->type == OB_CAMERA)
- return base->object;
+ for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
+ for (ViewLayer *layer = scene->view_layers.first; layer; layer = layer->next) {
+ if (BKE_view_layer_has_collection(layer, scene_collection)) {
+ return scene;
+ }
+ }
+ }
return NULL;
}
@@ -1228,49 +1261,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 */
@@ -1322,109 +1320,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
@@ -1440,7 +1335,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) {
@@ -1453,372 +1348,27 @@ static void scene_armature_depsgraph_workaround(Main *bmain)
}
#endif
-#ifdef WITH_LEGACY_DEPSGRAPH
-static void scene_rebuild_rbw_recursive(Scene *scene, float ctime)
-{
- if (scene->set)
- scene_rebuild_rbw_recursive(scene->set, ctime);
-
- if (BKE_scene_check_rigidbody_active(scene))
- BKE_rigidbody_rebuild_world(scene, ctime);
-}
-
-static void scene_do_rb_simulation_recursive(Scene *scene, float ctime)
-{
- if (scene->set)
- scene_do_rb_simulation_recursive(scene->set, ctime);
-
- if (BKE_scene_check_rigidbody_active(scene))
- BKE_rigidbody_do_simulation(scene, ctime);
-}
-#endif
-
-/* Used to visualize CPU threads activity during threaded object update,
- * would pollute STDERR with whole bunch of timing information which then
- * could be parsed and nicely visualized.
- */
-#ifdef WITH_LEGACY_DEPSGRAPH
-# undef DETAILED_ANALYSIS_OUTPUT
-#else
-/* ALWAYS KEEY DISABLED! */
-# undef DETAILED_ANALYSIS_OUTPUT
-#endif
-
-/* Mballs evaluation uses BKE_scene_base_iter_next which calls
- * duplilist for all objects in the scene. This leads to conflict
- * accessing and writing same data from multiple threads.
- *
- * Ideally Mballs shouldn't do such an iteration and use DAG
- * queries instead. For the time being we've got new DAG
- * let's keep it simple and update mballs in a single thread.
- */
-#define MBALL_SINGLETHREAD_HACK
-
-#ifdef WITH_LEGACY_DEPSGRAPH
-typedef struct StatisicsEntry {
- struct StatisicsEntry *next, *prev;
- Object *object;
- double start_time;
- double duration;
-} StatisicsEntry;
-
-typedef struct ThreadedObjectUpdateState {
- /* TODO(sergey): We might want this to be per-thread object. */
- EvaluationContext *eval_ctx;
- Scene *scene;
- Scene *scene_parent;
- double base_time;
-
-#ifdef MBALL_SINGLETHREAD_HACK
- bool has_mballs;
-#endif
-
- /* Execution statistics */
- bool has_updated_objects;
- ListBase *statistics;
-} ThreadedObjectUpdateState;
-
-static void scene_update_object_add_task(void *node, void *user_data);
-
-static void scene_update_all_bases(EvaluationContext *eval_ctx, Scene *scene, Scene *scene_parent)
-{
- Base *base;
-
- for (base = scene->base.first; base; base = base->next) {
- Object *object = base->object;
-
- BKE_object_handle_update_ex(eval_ctx, scene_parent, object, scene->rigidbody_world, true);
-
- if (object->dup_group && (object->transflag & OB_DUPLIGROUP))
- BKE_group_handle_recalc_and_update(eval_ctx, scene_parent, object, object->dup_group);
-
- /* always update layer, so that animating layers works (joshua july 2010) */
- /* XXX commented out, this has depsgraph issues anyway - and this breaks setting scenes
- * (on scene-set, the base-lay is copied to ob-lay (ton nov 2012) */
- // base->lay = ob->lay;
- }
-}
-
-static void scene_update_object_func(TaskPool * __restrict pool, void *taskdata, int threadid)
-{
-/* Disable print for now in favor of summary statistics at the end of update. */
-#define PRINT if (false) printf
-
- ThreadedObjectUpdateState *state = (ThreadedObjectUpdateState *) BLI_task_pool_userdata(pool);
- void *node = taskdata;
- Object *object = DAG_get_node_object(node);
- EvaluationContext *eval_ctx = state->eval_ctx;
- Scene *scene = state->scene;
- Scene *scene_parent = state->scene_parent;
-
-#ifdef MBALL_SINGLETHREAD_HACK
- if (object && object->type == OB_MBALL) {
- state->has_mballs = true;
- }
- else
-#endif
- if (object) {
- double start_time = 0.0;
- bool add_to_stats = false;
-
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- if (object->recalc & OB_RECALC_ALL) {
- printf("Thread %d: update object %s\n", threadid, object->id.name);
- }
-
- start_time = PIL_check_seconds_timer();
-
- if (object->recalc & OB_RECALC_ALL) {
- state->has_updated_objects = true;
- add_to_stats = true;
- }
- }
-
- /* We only update object itself here, dupli-group will be updated
- * separately from main thread because of we've got no idea about
- * dependencies inside the group.
- */
- BKE_object_handle_update_ex(eval_ctx, scene_parent, object, scene->rigidbody_world, false);
-
- /* Calculate statistics. */
- if (add_to_stats) {
- StatisicsEntry *entry;
-
- entry = MEM_mallocN(sizeof(StatisicsEntry), "update thread statistics");
- entry->object = object;
- entry->start_time = start_time;
- entry->duration = PIL_check_seconds_timer() - start_time;
-
- BLI_addtail(&state->statistics[threadid], entry);
- }
- }
- else {
- PRINT("Threda %d: update node %s\n", threadid,
- DAG_get_node_name(scene, node));
- }
-
- /* Update will decrease child's valency and schedule child with zero valency. */
- DAG_threaded_update_handle_node_updated(node, scene_update_object_add_task, pool);
-
-#undef PRINT
-}
-
-static void scene_update_object_add_task(void *node, void *user_data)
-{
- TaskPool *task_pool = user_data;
-
- BLI_task_pool_push(task_pool, scene_update_object_func, node, false, TASK_PRIORITY_LOW);
-}
-
-static void print_threads_statistics(ThreadedObjectUpdateState *state)
-{
- int i, tot_thread;
- double finish_time;
-
- if ((G.debug & G_DEBUG_DEPSGRAPH) == 0) {
- return;
- }
-
-#ifdef DETAILED_ANALYSIS_OUTPUT
- if (state->has_updated_objects) {
- tot_thread = BLI_system_thread_count();
-
- fprintf(stderr, "objects update base time %f\n", state->base_time);
-
- for (i = 0; i < tot_thread; i++) {
- StatisicsEntry *entry;
- for (entry = state->statistics[i].first;
- entry;
- entry = entry->next)
- {
- fprintf(stderr, "thread %d object %s start_time %f duration %f\n",
- i, entry->object->id.name + 2,
- entry->start_time, entry->duration);
- }
- BLI_freelistN(&state->statistics[i]);
- }
- }
-#else
- finish_time = PIL_check_seconds_timer();
- tot_thread = BLI_system_thread_count();
- int total_objects = 0;
-
- for (i = 0; i < tot_thread; i++) {
- int thread_total_objects = 0;
- double thread_total_time = 0.0;
- StatisicsEntry *entry;
-
- if (state->has_updated_objects) {
- /* Don't pollute output if no objects were updated. */
- for (entry = state->statistics[i].first;
- entry;
- entry = entry->next)
- {
- thread_total_objects++;
- thread_total_time += entry->duration;
- }
-
- printf("Thread %d: total %d objects in %f sec.\n",
- i,
- thread_total_objects,
- thread_total_time);
-
- for (entry = state->statistics[i].first;
- entry;
- entry = entry->next)
- {
- printf(" %s in %f sec\n", entry->object->id.name + 2, entry->duration);
- }
-
- total_objects += thread_total_objects;
- }
-
- BLI_freelistN(&state->statistics[i]);
- }
- if (state->has_updated_objects) {
- printf("Scene updated %d objects in %f sec\n",
- total_objects,
- finish_time - state->base_time);
- }
-#endif
-}
-
-static bool scene_need_update_objects(Main *bmain)
-{
- return
- /* Object datablocks themselves (for OB_RECALC_OB) */
- DAG_id_type_tagged(bmain, ID_OB) ||
-
- /* Objects data datablocks (for OB_RECALC_DATA) */
- DAG_id_type_tagged(bmain, ID_ME) || /* Mesh */
- DAG_id_type_tagged(bmain, ID_CU) || /* Curve */
- DAG_id_type_tagged(bmain, ID_MB) || /* MetaBall */
- DAG_id_type_tagged(bmain, ID_LA) || /* Lamp */
- DAG_id_type_tagged(bmain, ID_LT) || /* Lattice */
- DAG_id_type_tagged(bmain, ID_CA) || /* Camera */
- DAG_id_type_tagged(bmain, ID_KE) || /* KE */
- DAG_id_type_tagged(bmain, ID_SPK) || /* Speaker */
- DAG_id_type_tagged(bmain, ID_AR); /* Armature */
-}
-
-static void scene_update_objects(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, Scene *scene_parent)
-{
- TaskScheduler *task_scheduler;
- TaskPool *task_pool;
- ThreadedObjectUpdateState state;
- bool need_singlethread_pass;
- bool need_free_scheduler;
-
- /* Early check for whether we need to invoke all the task-based
- * things (spawn new ppol, traverse dependency graph and so on).
- *
- * Basically if there's no ID datablocks tagged for update which
- * corresponds to object->recalc flags (which are checked in
- * BKE_object_handle_update() then we do nothing here.
- */
- if (!scene_need_update_objects(bmain)) {
- return;
- }
-
- state.eval_ctx = eval_ctx;
- state.scene = scene;
- state.scene_parent = scene_parent;
-
- if (G.debug & G_DEBUG_DEPSGRAPH_NO_THREADS) {
- task_scheduler = BLI_task_scheduler_create(1);
- need_free_scheduler = true;
- }
- else {
- task_scheduler = BLI_task_scheduler_get();
- need_free_scheduler = false;
- }
-
- /* Those are only needed when blender is run with --debug argument. */
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- const int tot_thread = BLI_task_scheduler_num_threads(task_scheduler);
- state.statistics = MEM_callocN(tot_thread * sizeof(*state.statistics),
- "scene update objects stats");
- state.has_updated_objects = false;
- state.base_time = PIL_check_seconds_timer();
- }
-
-#ifdef MBALL_SINGLETHREAD_HACK
- state.has_mballs = false;
-#endif
-
- task_pool = BLI_task_pool_create(task_scheduler, &state);
-
- DAG_threaded_update_begin(scene, scene_update_object_add_task, task_pool);
- BLI_task_pool_work_and_wait(task_pool);
- BLI_task_pool_free(task_pool);
-
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- print_threads_statistics(&state);
- MEM_freeN(state.statistics);
- }
-
- /* We do single thread pass to update all the objects which are in cyclic dependency.
- * Such objects can not be handled by a generic DAG traverse and it's really tricky
- * to detect whether cycle could be solved or not.
- *
- * In this situation we simply update all remaining objects in a single thread and
- * it'll happen in the same exact order as it was in single-threaded DAG.
- *
- * We couldn't use threaded update for objects which are in cycle because they might
- * access data of each other which is being re-evaluated.
- *
- * Also, as was explained above, for now we also update all the mballs in single thread.
- *
- * - sergey -
- */
- need_singlethread_pass = DAG_is_acyclic(scene) == false;
-#ifdef MBALL_SINGLETHREAD_HACK
- need_singlethread_pass |= state.has_mballs;
-#endif
-
- if (need_singlethread_pass) {
- scene_update_all_bases(eval_ctx, scene, scene_parent);
- }
-
- if (need_free_scheduler) {
- BLI_task_scheduler_free(task_scheduler);
- }
-}
-
-static void scene_update_tagged_recursive(EvaluationContext *eval_ctx, Main *bmain, Scene *scene, Scene *scene_parent)
-{
- scene->customdata_mask = scene_parent->customdata_mask;
-
- /* sets first, we allow per definition current scene to have
- * dependencies on sets, but not the other way around. */
- if (scene->set)
- scene_update_tagged_recursive(eval_ctx, bmain, scene->set, scene_parent);
-
- /* scene objects */
- scene_update_objects(eval_ctx, bmain, scene, scene_parent);
-
- /* scene drivers... */
- scene_update_drivers(bmain, scene);
-
- /* update masking curves */
- BKE_mask_update_scene(bmain, scene);
-
-}
-#endif /* WITH_LEGACY_DEPSGRAPH */
-
static bool check_rendered_viewport_visible(Main *bmain)
{
wmWindowManager *wm = bmain->wm.first;
wmWindow *window;
for (window = wm->windows.first; window != NULL; window = window->next) {
- bScreen *screen = window->screen;
+ const bScreen *screen = BKE_workspace_active_screen_get(window->workspace_hook);
+ WorkSpace *workspace = BKE_workspace_active_get(window->workspace_hook);
+ Scene *scene = window->scene;
+ ViewRender *view_render = BKE_viewrender_get(scene, workspace);
ScrArea *area;
+ RenderEngineType *type = RE_engines_find(view_render->engine_id);
+ if ((type->draw_engine != NULL) || (type->render_to_view == NULL)) {
+ continue;
+ }
+ const bool use_legacy = (type->flag & RE_USE_LEGACY_PIPELINE) != 0;
for (area = screen->areabase.first; area != NULL; area = area->next) {
View3D *v3d = area->spacedata.first;
if (area->spacetype != SPACE_VIEW3D) {
continue;
}
- if (v3d->drawtype == OB_RENDER) {
+ if (v3d->drawtype == OB_RENDER || !use_legacy) {
return true;
}
}
@@ -1847,318 +1397,94 @@ static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene)
if (check_rendered_viewport_visible(bmain)) {
BMesh *bm = mesh->edit_btmesh->bm;
BM_mesh_bm_to_me(bm, mesh, (&(struct BMeshToMeshParams){0}));
- DAG_id_tag_update(&mesh->id, 0);
+ DEG_id_tag_update(&mesh->id, 0);
}
}
}
}
-void BKE_scene_update_tagged(EvaluationContext *eval_ctx, Main *bmain, Scene *scene)
-{
- Scene *sce_iter;
-#ifdef WITH_LEGACY_DEPSGRAPH
- bool use_new_eval = !DEG_depsgraph_use_legacy();
-#endif
-
- /* keep this first */
- BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_PRE);
-
- /* (re-)build dependency graph if needed */
- for (sce_iter = scene; sce_iter; sce_iter = sce_iter->set) {
- DAG_scene_relations_update(bmain, sce_iter);
- /* Uncomment this to check if dependency graph was properly tagged for update. */
-#if 0
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (use_new_eval)
-#endif
- {
- DAG_scene_relations_validate(bmain, sce_iter);
- }
-#endif
- }
-
- /* flush editing data if needed */
+/* TODO(sergey): This actually should become view_layer_graph or so.
+ * Same applies to update_for_newframe.
+ */
+void BKE_scene_graph_update_tagged(EvaluationContext *eval_ctx,
+ Depsgraph *depsgraph,
+ Main *bmain,
+ Scene *scene,
+ ViewLayer *view_layer)
+{
+ /* TODO(sergey): Temporary solution for until pipeline.c is ported. */
+ if (view_layer == NULL) {
+ view_layer = DEG_get_evaluated_view_layer(depsgraph);
+ BLI_assert(view_layer != NULL);
+ }
+ /* TODO(sergey): Some functions here are changing global state,
+ * for example, clearing update tags from bmain.
+ */
+ /* (Re-)build dependency graph if needed. */
+ DEG_graph_relations_update(depsgraph, bmain, scene, view_layer);
+ /* Uncomment this to check if graph was properly tagged for update. */
+ // DEG_debug_graph_relations_validate(depsgraph, bmain, scene);
+ /* Flush editing data if needed. */
prepare_mesh_for_viewport_render(bmain, scene);
-
- /* flush recalc flags to dependencies */
- DAG_ids_flush_tagged(bmain);
-
- /* removed calls to quick_cache, see pointcache.c */
-
- /* clear "LIB_TAG_DOIT" flag from all materials, to prevent infinite recursion problems later
- * when trying to find materials with drivers that need evaluating [#32017]
+ /* Flush recalc flags to dependencies. */
+ DEG_graph_flush_update(bmain, depsgraph);
+ /* Update all objects: drivers, matrices, displists, etc. flags set
+ * by depgraph or manual, no layer check here, gets correct flushed.
*/
- BKE_main_id_tag_idcode(bmain, ID_MA, LIB_TAG_DOIT, false);
- BKE_main_id_tag_idcode(bmain, ID_LA, LIB_TAG_DOIT, false);
-
- /* update all objects: drivers, matrices, displists, etc. flags set
- * by depgraph or manual, no layer check here, gets correct flushed
- *
- * in the future this should handle updates for all datablocks, not
- * only objects and scenes. - brecht */
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!use_new_eval) {
- scene_update_tagged_recursive(eval_ctx, bmain, scene, scene);
- }
- else
-#endif
- {
- DEG_evaluate_on_refresh(eval_ctx, scene->depsgraph, scene);
- }
-
- /* update sound system animation (TODO, move to depsgraph) */
+ DEG_evaluate_on_refresh(eval_ctx, depsgraph);
+ /* Update sound system animation (TODO, move to depsgraph). */
BKE_sound_update_scene(bmain, scene);
-
- /* extra call here to recalc scene animation (for sequencer) */
- {
- AnimData *adt = BKE_animdata_from_id(&scene->id);
- float ctime = BKE_scene_frame_get(scene);
-
- if (adt && (adt->recalc & ADT_RECALC_ANIM))
- BKE_animsys_evaluate_animdata(scene, &scene->id, adt, ctime, 0);
- }
-
- /* Extra call here to recalc material animation.
- *
- * Need to do this so changing material settings from the graph/dopesheet
- * will update stuff in the viewport.
- */
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!use_new_eval && DAG_id_type_tagged(bmain, ID_MA)) {
- Material *material;
- float ctime = BKE_scene_frame_get(scene);
-
- for (material = bmain->mat.first;
- material;
- material = material->id.next)
- {
- AnimData *adt = BKE_animdata_from_id(&material->id);
- if (adt && (adt->recalc & ADT_RECALC_ANIM))
- BKE_animsys_evaluate_animdata(scene, &material->id, adt, ctime, 0);
- }
- }
-
- /* Also do the same for node trees. */
- if (!use_new_eval && DAG_id_type_tagged(bmain, ID_NT)) {
- float ctime = BKE_scene_frame_get(scene);
-
- FOREACH_NODETREE(bmain, ntree, id)
- {
- AnimData *adt = BKE_animdata_from_id(&ntree->id);
- if (adt && (adt->recalc & ADT_RECALC_ANIM))
- BKE_animsys_evaluate_animdata(scene, &ntree->id, adt, ctime, 0);
- }
- FOREACH_NODETREE_END
- }
-#endif
-
- /* notify editors and python about recalc */
- BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_SCENE_UPDATE_POST);
-
/* Inform editors about possible changes. */
- DAG_ids_check_recalc(bmain, scene, false);
-
- /* clear recalc flags */
- DAG_ids_clear_recalc(bmain);
+ DEG_ids_check_recalc(bmain, depsgraph, scene, view_layer, false);
+ /* Clear recalc flags. */
+ DEG_ids_clear_recalc(bmain);
}
/* applies changes right away, does all sets too */
-void BKE_scene_update_for_newframe(EvaluationContext *eval_ctx, Main *bmain, Scene *sce, unsigned int lay)
-{
- BKE_scene_update_for_newframe_ex(eval_ctx, bmain, sce, lay, false);
-}
-
-void BKE_scene_update_for_newframe_ex(EvaluationContext *eval_ctx, Main *bmain, Scene *sce, unsigned int lay, bool do_invisible_flush)
-{
- float ctime = BKE_scene_frame_get(sce);
- Scene *sce_iter;
-#ifdef DETAILED_ANALYSIS_OUTPUT
- double start_time = PIL_check_seconds_timer();
-#endif
-#ifdef WITH_LEGACY_DEPSGRAPH
- bool use_new_eval = !DEG_depsgraph_use_legacy();
-#else
- /* TODO(sergey): Pass to evaluation routines instead of storing layer in the dependency graph? */
- (void) do_invisible_flush;
-#endif
-
- DAG_editors_update_pre(bmain, sce, true);
-
- /* keep this first */
- BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_FRAME_CHANGE_PRE);
- BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_SCENE_UPDATE_PRE);
-
- /* update animated image textures for particles, modifiers, gpu, etc,
- * call this at the start so modifiers with textures don't lag 1 frame */
- BKE_image_update_frame(bmain, sce->r.cfra);
-
-#ifdef WITH_LEGACY_DEPSGRAPH
- /* rebuild rigid body worlds before doing the actual frame update
- * this needs to be done on start frame but animation playback usually starts one frame later
- * we need to do it here to avoid rebuilding the world on every simulation change, which can be very expensive
+void BKE_scene_graph_update_for_newframe(EvaluationContext *eval_ctx,
+ Depsgraph *depsgraph,
+ Main *bmain,
+ Scene *scene,
+ ViewLayer *view_layer)
+{
+ /* TODO(sergey): Temporary solution for until pipeline.c is ported. */
+ if (view_layer == NULL) {
+ view_layer = DEG_get_evaluated_view_layer(depsgraph);
+ BLI_assert(view_layer != NULL);
+ }
+ /* TODO(sergey): Some functions here are changing global state,
+ * for example, clearing update tags from bmain.
*/
- if (!use_new_eval) {
- scene_rebuild_rbw_recursive(sce, ctime);
- }
-#endif
-
- BKE_sound_set_cfra(sce->r.cfra);
-
- /* clear animation overrides */
- /* XXX TODO... */
-
- for (sce_iter = sce; sce_iter; sce_iter = sce_iter->set)
- DAG_scene_relations_update(bmain, sce_iter);
-
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!use_new_eval) {
- /* flush recalc flags to dependencies, if we were only changing a frame
- * this would not be necessary, but if a user or a script has modified
- * some datablock before BKE_scene_update_tagged was called, we need the flush */
- DAG_ids_flush_tagged(bmain);
-
- /* Following 2 functions are recursive
- * so don't call within 'scene_update_tagged_recursive' */
- DAG_scene_update_flags(bmain, sce, lay, true, do_invisible_flush); // only stuff that moves or needs display still
- BKE_mask_evaluate_all_masks(bmain, ctime, true);
- }
-#endif
-
- /* Update animated cache files for modifiers. */
- BKE_cachefile_update_frame(bmain, sce, ctime, (((double)sce->r.frs_sec) / (double)sce->r.frs_sec_base));
-
+ const float ctime = BKE_scene_frame_get(scene);
+ /* Keep this first. */
+ BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_FRAME_CHANGE_PRE);
+ /* Update animated image textures for particles, modifiers, gpu, etc,
+ * call this at the start so modifiers with textures don't lag 1 frame.
+ */
+ BKE_image_update_frame(bmain, scene->r.cfra);
+ BKE_sound_set_cfra(scene->r.cfra);
+ DEG_graph_relations_update(depsgraph, bmain, scene, view_layer);
+ /* Update animated cache files for modifiers.
+ *
+ * TODO(sergey): Make this a depsgraph node?
+ */
+ BKE_cachefile_update_frame(bmain, scene, ctime,
+ (((double)scene->r.frs_sec) / (double)scene->r.frs_sec_base));
#ifdef POSE_ANIMATION_WORKAROUND
scene_armature_depsgraph_workaround(bmain);
#endif
-
- /* All 'standard' (i.e. without any dependencies) animation is handled here,
- * with an 'local' to 'macro' order of evaluation. This should ensure that
- * settings stored nestled within a hierarchy (i.e. settings in a Texture block
- * can be overridden by settings from Scene, which owns the Texture through a hierarchy
- * such as Scene->World->MTex/Texture) can still get correctly overridden.
+ /* Update all objects: drivers, matrices, displists, etc. flags set
+ * by depgraph or manual, no layer check here, gets correct flushed.
*/
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!use_new_eval) {
- BKE_animsys_evaluate_all_animation(bmain, sce, ctime);
- /*...done with recursive funcs */
- }
-#endif
-
- /* clear "LIB_TAG_DOIT" flag from all materials, to prevent infinite recursion problems later
- * when trying to find materials with drivers that need evaluating [#32017]
- */
- BKE_main_id_tag_idcode(bmain, ID_MA, LIB_TAG_DOIT, false);
- BKE_main_id_tag_idcode(bmain, ID_LA, LIB_TAG_DOIT, false);
-
- /* run rigidbody sim */
- /* NOTE: current position is so that rigidbody sim affects other objects, might change in the future */
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!use_new_eval) {
- scene_do_rb_simulation_recursive(sce, ctime);
- }
-#endif
-
- /* BKE_object_handle_update() on all objects, groups and sets */
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (use_new_eval) {
- DEG_evaluate_on_framechange(eval_ctx, bmain, sce->depsgraph, ctime, lay);
- }
- else {
- scene_update_tagged_recursive(eval_ctx, bmain, sce, sce);
- }
-#else
- DEG_evaluate_on_framechange(eval_ctx, bmain, sce->depsgraph, ctime, lay);
-#endif
-
- /* update sound system animation (TODO, move to depsgraph) */
- BKE_sound_update_scene(bmain, sce);
-
-#ifdef WITH_LEGACY_DEPSGRAPH
- if (!use_new_eval) {
- scene_depsgraph_hack(eval_ctx, sce, sce);
- }
-#endif
-
- /* notify editors and python about recalc */
- BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_SCENE_UPDATE_POST);
- BLI_callback_exec(bmain, &sce->id, BLI_CB_EVT_FRAME_CHANGE_POST);
-
+ DEG_evaluate_on_framechange(eval_ctx, bmain, depsgraph, ctime);
+ /* Update sound system animation (TODO, move to depsgraph). */
+ BKE_sound_update_scene(bmain, scene);
+ /* Notify editors and python about recalc. */
+ BLI_callback_exec(bmain, &scene->id, BLI_CB_EVT_FRAME_CHANGE_POST);
/* Inform editors about possible changes. */
- DAG_ids_check_recalc(bmain, sce, true);
-
+ DEG_ids_check_recalc(bmain, depsgraph, scene, view_layer, true);
/* clear recalc flags */
- DAG_ids_clear_recalc(bmain);
-
-#ifdef DETAILED_ANALYSIS_OUTPUT
- fprintf(stderr, "frame update start_time %f duration %f\n", start_time, PIL_check_seconds_timer() - start_time);
-#endif
-}
-
-/* return default layer, also used to patch old files */
-SceneRenderLayer *BKE_scene_add_render_layer(Scene *sce, const char *name)
-{
- SceneRenderLayer *srl;
-
- if (!name)
- name = DATA_("RenderLayer");
-
- srl = MEM_callocN(sizeof(SceneRenderLayer), "new render layer");
- BLI_strncpy(srl->name, name, sizeof(srl->name));
- BLI_uniquename(&sce->r.layers, srl, DATA_("RenderLayer"), '.', offsetof(SceneRenderLayer, name), sizeof(srl->name));
- BLI_addtail(&sce->r.layers, srl);
-
- /* note, this is also in render, pipeline.c, to make layer when scenedata doesnt have it */
- srl->lay = (1 << 20) - 1;
- srl->layflag = 0x7FFF; /* solid ztra halo edge strand */
- srl->passflag = SCE_PASS_COMBINED | SCE_PASS_Z;
- srl->pass_alpha_threshold = 0.5f;
- BKE_freestyle_config_init(&srl->freestyleConfig);
-
- return srl;
-}
-
-bool BKE_scene_remove_render_layer(Main *bmain, Scene *scene, SceneRenderLayer *srl)
-{
- const int act = BLI_findindex(&scene->r.layers, srl);
- Scene *sce;
-
- if (act == -1) {
- return false;
- }
- else if ( (scene->r.layers.first == scene->r.layers.last) &&
- (scene->r.layers.first == srl))
- {
- /* ensure 1 layer is kept */
- return false;
- }
-
- BKE_freestyle_config_free(&srl->freestyleConfig);
-
- if (srl->prop) {
- IDP_FreeProperty(srl->prop);
- MEM_freeN(srl->prop);
- }
-
- BLI_remlink(&scene->r.layers, srl);
- MEM_freeN(srl);
-
- scene->r.actlay = 0;
-
- for (sce = bmain->scene.first; sce; sce = sce->id.next) {
- if (sce->nodetree) {
- bNode *node;
- for (node = sce->nodetree->nodes.first; node; node = node->next) {
- if (node->type == CMP_NODE_R_LAYERS && (Scene *)node->id == scene) {
- if (node->custom1 == act)
- node->custom1 = 0;
- else if (node->custom1 > act)
- node->custom1--;
- }
- }
- }
- }
-
- return true;
+ DEG_ids_clear_recalc(bmain);
}
/* return default view */
@@ -2241,21 +1567,34 @@ float get_render_aosss_error(const RenderData *r, float error)
return error;
}
-/* helper function for the SETLOOPER macro */
-Base *_setlooper_base_step(Scene **sce_iter, Base *base)
+/**
+ * Helper function for the SETLOOPER and SETLOOPER_VIEW_LAYER macros
+ *
+ * It iterates over the bases of the active layer and then the bases
+ * of the active layer of the background (set) scenes recursively.
+ */
+Base *_setlooper_base_step(Scene **sce_iter, ViewLayer *view_layer, Base *base)
{
if (base && base->next) {
- /* common case, step to the next */
+ /* Common case, step to the next. */
return base->next;
}
- else if (base == NULL && (*sce_iter)->base.first) {
- /* first time looping, return the scenes first base */
- return (Base *)(*sce_iter)->base.first;
+ else if ((base == NULL) && (view_layer != NULL)) {
+ /* First time looping, return the scenes first base. */
+ /* For the first loop we should get the layer from workspace when available. */
+ if (view_layer->object_bases.first) {
+ return (Base *)view_layer->object_bases.first;
+ }
+ /* No base on this scene layer. */
+ goto next_set;
}
else {
- /* reached the end, get the next base in the set */
+next_set:
+ /* Reached the end, get the next base in the set. */
while ((*sce_iter = (*sce_iter)->set)) {
- base = (Base *)(*sce_iter)->base.first;
+ ViewLayer *view_layer_set = BKE_view_layer_from_scene_get((*sce_iter));
+ base = (Base *)view_layer_set->object_bases.first;
+
if (base) {
return base;
}
@@ -2267,56 +1606,80 @@ Base *_setlooper_base_step(Scene **sce_iter, Base *base)
bool BKE_scene_use_new_shading_nodes(const Scene *scene)
{
- const RenderEngineType *type = RE_engines_find(scene->r.engine);
- return (type && type->flag & RE_USE_SHADING_NODES);
+ return BKE_viewrender_use_new_shading_nodes(&scene->view_render);
}
bool BKE_scene_use_shading_nodes_custom(Scene *scene)
{
- RenderEngineType *type = RE_engines_find(scene->r.engine);
- return (type && type->flag & RE_USE_SHADING_NODES_CUSTOM);
+ return BKE_viewrender_use_shading_nodes_custom(&scene->view_render);
}
bool BKE_scene_use_world_space_shading(Scene *scene)
{
- const RenderEngineType *type = RE_engines_find(scene->r.engine);
+ RenderEngineType *type = RE_engines_find(scene->view_render.engine_id);
return ((scene->r.mode & R_USE_WS_SHADING) ||
(type && (type->flag & RE_USE_SHADING_NODES)));
}
bool BKE_scene_use_spherical_stereo(Scene *scene)
{
- RenderEngineType *type = RE_engines_find(scene->r.engine);
- return (type && type->flag & RE_USE_SPHERICAL_STEREO);
+ return BKE_viewrender_use_spherical_stereo(&scene->view_render);
}
-bool BKE_scene_uses_blender_internal(const Scene *scene)
+bool BKE_scene_uses_blender_internal(const Scene *scene)
{
- return STREQ(scene->r.engine, RE_engine_id_BLENDER_RENDER);
+ return BKE_viewrender_uses_blender_internal(&scene->view_render);
}
bool BKE_scene_uses_blender_game(const Scene *scene)
{
- return STREQ(scene->r.engine, RE_engine_id_BLENDER_GAME);
+ return BKE_viewrender_uses_blender_game(&scene->view_render);
+}
+
+bool BKE_scene_uses_blender_eevee(const Scene *scene)
+{
+ return BKE_viewrender_uses_blender_eevee(&scene->view_render);
}
-void BKE_scene_base_flag_to_objects(struct Scene *scene)
+void BKE_scene_base_flag_to_objects(ViewLayer *view_layer)
{
- Base *base = scene->base.first;
+ Base *base = view_layer->object_bases.first;
while (base) {
- base->object->flag = base->flag;
+ BKE_scene_object_base_flag_sync_from_base(base);
base = base->next;
}
}
-void BKE_scene_base_flag_from_objects(struct Scene *scene)
+void BKE_scene_object_base_flag_sync_from_base(Base *base)
{
- Base *base = scene->base.first;
+ Object *ob = base->object;
- while (base) {
- base->flag = base->object->flag;
- base = base->next;
+ /* keep the object only flags untouched */
+ int flag = ob->flag & OB_FROMGROUP;
+
+ ob->flag = base->flag;
+ ob->flag |= flag;
+
+ if ((base->flag & BASE_SELECTED) != 0) {
+ ob->flag |= SELECT;
+ }
+ else {
+ ob->flag &= ~SELECT;
+ }
+}
+
+void BKE_scene_object_base_flag_sync_from_object(Base *base)
+{
+ Object *ob = base->object;
+ base->flag = ob->flag;
+
+ if ((ob->flag & SELECT) != 0) {
+ base->flag |= BASE_SELECTED;
+ BLI_assert((base->flag & BASE_SELECTABLED) != 0);
+ }
+ else {
+ base->flag &= ~BASE_SELECTED;
}
}
@@ -2380,6 +1743,81 @@ int BKE_render_preview_pixel_size(const RenderData *r)
return r->preview_pixel_size;
}
+/* ***************************************************** */
+/* render engine settings */
+
+ViewRender *BKE_viewrender_get(Scene *scene, WorkSpace *workspace)
+{
+ if (workspace == NULL || BKE_workspace_use_scene_settings_get(workspace)) {
+ return &scene->view_render;
+ }
+ return BKE_workspace_view_render_get(workspace);
+}
+
+/**
+ * Initialize a static created struct for WorkSpace and Scene to store the viewport
+ * related drawing data.
+ */
+void BKE_viewrender_init(ViewRender *view_render)
+{
+ BLI_strncpy(view_render->engine_id, RE_engine_id_BLENDER_EEVEE, sizeof(view_render->engine_id));
+}
+
+/**
+ * Do not free ViewRender itself since it's not even allocated.
+ */
+void BKE_viewrender_free(ViewRender *UNUSED(view_render))
+{
+ /* Do nothing. */
+}
+
+/**
+ * Copy used by libblock copying.
+ */
+void BKE_viewrender_copy(ViewRender *to, const ViewRender *from)
+{
+ *to = *from;
+}
+
+bool BKE_viewrender_use_new_shading_nodes(const ViewRender *view_render)
+{
+ RenderEngineType *type = RE_engines_find(view_render->engine_id);
+ return (type && type->flag & RE_USE_SHADING_NODES);
+}
+
+bool BKE_viewrender_use_shading_nodes_custom(const ViewRender *view_render)
+{
+ RenderEngineType *type = RE_engines_find(view_render->engine_id);
+ return (type && type->flag & RE_USE_SHADING_NODES_CUSTOM);
+}
+
+bool BKE_viewrender_use_spherical_stereo(const ViewRender *view_render)
+{
+ const char *engine_id = view_render->engine_id;
+ RenderEngineType *type = RE_engines_find(engine_id);
+ return (type && type->flag & RE_USE_SPHERICAL_STEREO);
+}
+
+bool BKE_viewrender_uses_blender_internal(const ViewRender *view_render)
+{
+ const char *engine_id = view_render->engine_id;
+ return STREQ(engine_id, RE_engine_id_BLENDER_RENDER);
+}
+
+bool BKE_viewrender_uses_blender_game(const ViewRender *view_render)
+{
+ const char *engine_id = view_render->engine_id;
+ return STREQ(engine_id, RE_engine_id_BLENDER_GAME);
+}
+
+bool BKE_viewrender_uses_blender_eevee(const ViewRender *view_render)
+{
+ const char *engine_id = view_render->engine_id;
+ return STREQ(engine_id, RE_engine_id_BLENDER_EEVEE);
+}
+
+/* ***************************************************** */
+
/* Apply the needed correction factor to value, based on unit_type (only length-related are affected currently)
* and unit->scale_length.
*/
@@ -2685,3 +2123,106 @@ int BKE_scene_multiview_num_videos_get(const RenderData *rd)
return BKE_scene_multiview_num_views_get(rd);
}
}
+
+/* Manipulation of depsgraph storage. */
+
+/* This is a key which identifies depsgraph. */
+typedef struct DepsgraphKey {
+ ViewLayer *view_layer;
+ /* TODO(sergey): Need to include window somehow (same layer might be in a
+ * different states in different windows).
+ */
+} DepsgraphKey;
+
+static unsigned int depsgraph_key_hash(const void *key_v)
+{
+ const DepsgraphKey *key = key_v;
+ unsigned int hash = BLI_ghashutil_ptrhash(key->view_layer);
+ /* TODO(sergey): Include hash from other fields in the key. */
+ return hash;
+}
+
+static bool depsgraph_key_compare(const void *key_a_v, const void *key_b_v)
+{
+ const DepsgraphKey *key_a = key_a_v;
+ const DepsgraphKey *key_b = key_b_v;
+ /* TODO(sergey): Compare rest of */
+ return !(key_a->view_layer == key_b->view_layer);
+}
+
+static void depsgraph_key_free(void *key_v)
+{
+ DepsgraphKey *key = key_v;
+ MEM_freeN(key);
+}
+
+static void depsgraph_key_value_free(void *value)
+{
+ Depsgraph *depsgraph = value;
+ DEG_graph_free(depsgraph);
+}
+
+void BKE_scene_allocate_depsgraph_hash(Scene *scene)
+{
+ scene->depsgraph_hash = BLI_ghash_new(depsgraph_key_hash,
+ depsgraph_key_compare,
+ "Scene Depsgraph Hash");
+}
+
+void BKE_scene_ensure_depsgraph_hash(Scene *scene)
+{
+ if (scene->depsgraph_hash == NULL) {
+ BKE_scene_allocate_depsgraph_hash(scene);
+ }
+}
+
+void BKE_scene_free_depsgraph_hash(Scene *scene)
+{
+ if (scene->depsgraph_hash == NULL) {
+ return;
+ }
+ BLI_ghash_free(scene->depsgraph_hash,
+ depsgraph_key_free,
+ depsgraph_key_value_free);
+}
+
+/* Query depsgraph for a specific contexts. */
+
+Depsgraph *BKE_scene_get_depsgraph(Scene *scene,
+ ViewLayer *view_layer,
+ bool allocate)
+{
+ BLI_assert(scene != NULL);
+ BLI_assert(view_layer != NULL);
+ /* Make sure hash itself exists. */
+ if (allocate) {
+ BKE_scene_ensure_depsgraph_hash(scene);
+ }
+ if (scene->depsgraph_hash == NULL) {
+ return NULL;
+ }
+ /* Either ensure item is in the hash or simply return NULL if it's not,
+ * depending on whether caller wants us to create depsgraph or not.
+ */
+ DepsgraphKey key;
+ key.view_layer = view_layer;
+ Depsgraph *depsgraph;
+ if (allocate) {
+ DepsgraphKey **key_ptr;
+ Depsgraph **depsgraph_ptr;
+ if (!BLI_ghash_ensure_p_ex(scene->depsgraph_hash,
+ &key,
+ (void ***)&key_ptr,
+ (void ***)&depsgraph_ptr))
+ {
+ *key_ptr = MEM_mallocN(sizeof(DepsgraphKey), __func__);
+ **key_ptr = key;
+ *depsgraph_ptr = DEG_graph_new();
+ }
+ depsgraph = *depsgraph_ptr;
+ }
+ else {
+ depsgraph = BLI_ghash_lookup(scene->depsgraph_hash, &key);
+ }
+ return depsgraph;
+}
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index df47b89fadc..6bd88099792 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -45,13 +45,16 @@
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
#include "DNA_view3d_types.h"
+#include "DNA_workspace_types.h"
#include "BLI_listbase.h"
#include "BLI_utildefines.h"
#include "BLI_rect.h"
+#include "BKE_icons.h"
#include "BKE_idprop.h"
#include "BKE_screen.h"
+#include "BKE_workspace.h"
/* ************ Spacetype/regiontype handling ************** */
@@ -180,6 +183,7 @@ ARegion *BKE_area_region_copy(SpaceType *st, ARegion *ar)
BLI_listbase_clear(&newar->panels_category_active);
BLI_listbase_clear(&newar->ui_lists);
newar->swinid = 0;
+ newar->manipulator_map = NULL;
newar->regiontimer = NULL;
newar->headerstr = NULL;
@@ -289,6 +293,43 @@ void BKE_spacedata_id_unref(struct ScrArea *sa, struct SpaceLink *sl, struct ID
}
}
+/**
+ * Avoid bad-level calls to #WM_manipulatormap_tag_refresh.
+ */
+static void (*region_refresh_tag_manipulatormap_callback)(struct wmManipulatorMap *) = NULL;
+
+void BKE_region_callback_refresh_tag_manipulatormap_set(void (*callback)(struct wmManipulatorMap *))
+{
+ region_refresh_tag_manipulatormap_callback = callback;
+}
+
+void BKE_screen_manipulator_tag_refresh(struct bScreen *sc)
+{
+ if (region_refresh_tag_manipulatormap_callback == NULL) {
+ return;
+ }
+
+ ScrArea *sa;
+ ARegion *ar;
+ for (sa = sc->areabase.first; sa; sa = sa->next) {
+ for (ar = sa->regionbase.first; ar; ar = ar->next) {
+ if (ar->manipulator_map != NULL) {
+ region_refresh_tag_manipulatormap_callback(ar->manipulator_map);
+ }
+ }
+ }
+}
+
+/**
+ * Avoid bad-level calls to #WM_manipulatormap_delete.
+ */
+static void (*region_free_manipulatormap_callback)(struct wmManipulatorMap *) = NULL;
+
+void BKE_region_callback_free_manipulatormap_set(void (*callback)(struct wmManipulatorMap *))
+{
+ region_free_manipulatormap_callback = callback;
+}
+
/* not region itself */
void BKE_area_region_free(SpaceType *st, ARegion *ar)
{
@@ -338,6 +379,11 @@ void BKE_area_region_free(SpaceType *st, ARegion *ar)
MEM_freeN(uilst->properties);
}
}
+
+ if (ar->manipulator_map != NULL) {
+ region_free_manipulatormap_callback(ar->manipulator_map);
+ }
+
BLI_freelistN(&ar->ui_lists);
BLI_freelistN(&ar->ui_previews);
BLI_freelistN(&ar->panels_category);
@@ -381,6 +427,8 @@ void BKE_screen_free(bScreen *sc)
BLI_freelistN(&sc->vertbase);
BLI_freelistN(&sc->edgebase);
BLI_freelistN(&sc->areabase);
+
+ BKE_previewimg_free(&sc->preview);
}
/* for depsgraph */
@@ -580,7 +628,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;
@@ -589,55 +637,26 @@ void BKE_screen_view3d_scene_sync(bScreen *sc)
for (sl = sa->spacedata.first; sl; sl = sl->next) {
if (sl->spacetype == SPACE_VIEW3D) {
View3D *v3d = (View3D *) sl;
- BKE_screen_view3d_sync(v3d, sc->scene);
+ BKE_screen_view3d_sync(v3d, scene);
}
}
}
}
-void BKE_screen_view3d_main_sync(ListBase *screen_lb, Scene *scene)
+void BKE_screen_transform_orientation_remove(
+ const bScreen *screen, const WorkSpace *workspace, const TransformOrientation *orientation)
{
- bScreen *sc;
- ScrArea *sa;
- SpaceLink *sl;
+ const int orientation_index = BKE_workspace_transform_orientation_get_index(workspace, orientation);
- /* from scene copy to the other views */
- for (sc = screen_lb->first; sc; sc = sc->id.next) {
- if (sc->scene != scene)
- continue;
-
- for (sa = sc->areabase.first; sa; sa = sa->next)
- for (sl = sa->spacedata.first; sl; sl = sl->next)
- if (sl->spacetype == SPACE_VIEW3D)
- BKE_screen_view3d_sync((View3D *)sl, scene);
- }
-}
-
-void BKE_screen_view3d_twmode_remove(View3D *v3d, const int i)
-{
- const int selected_index = (v3d->twmode - V3D_MANIP_CUSTOM);
- if (selected_index == i) {
- v3d->twmode = V3D_MANIP_GLOBAL; /* fallback to global */
- }
- else if (selected_index > i) {
- v3d->twmode--;
- }
-}
-
-void BKE_screen_view3d_main_twmode_remove(ListBase *screen_lb, Scene *scene, const int i)
-{
- bScreen *sc;
+ for (ScrArea *area = screen->areabase.first; area; area = area->next) {
+ for (SpaceLink *sl = area->spacedata.first; sl; sl = sl->next) {
+ if (sl->spacetype == SPACE_VIEW3D) {
+ View3D *v3d = (View3D *)sl;
- for (sc = screen_lb->first; sc; sc = sc->id.next) {
- if (sc->scene == scene) {
- ScrArea *sa;
- for (sa = sc->areabase.first; sa; sa = sa->next) {
- SpaceLink *sl;
- for (sl = sa->spacedata.first; sl; sl = sl->next) {
- if (sl->spacetype == SPACE_VIEW3D) {
- View3D *v3d = (View3D *)sl;
- BKE_screen_view3d_twmode_remove(v3d, i);
- }
+ if (v3d->custom_orientation_index == orientation_index) {
+ /* could also use orientation_index-- */
+ v3d->twmode = V3D_MANIP_GLOBAL;
+ v3d->custom_orientation_index = -1;
}
}
}
@@ -684,3 +703,13 @@ void BKE_screen_gpu_fx_validate(GPUFXSettings *fx_settings)
GPU_fx_compositor_init_ssao_settings(fx_ssao);
}
}
+
+bool BKE_screen_is_fullscreen_area(const bScreen *screen)
+{
+ return ELEM(screen->state, SCREENMAXIMIZED, SCREENFULL);
+}
+
+bool BKE_screen_is_used(const bScreen *screen)
+{
+ return (screen->winid != 0);
+}
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index b3db2080cb8..ee11a9806f3 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -63,9 +63,9 @@
#include "BLT_translation.h"
#include "BKE_animsys.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_image.h"
+#include "BKE_layer.h"
#include "BKE_main.h"
#include "BKE_sequencer.h"
#include "BKE_movieclip.h"
@@ -75,6 +75,8 @@
#include "BKE_library.h"
#include "BKE_idprop.h"
+#include "DEG_depsgraph.h"
+
#include "RNA_access.h"
#include "RE_pipeline.h"
@@ -88,8 +90,10 @@
#include "BKE_context.h"
#include "BKE_sound.h"
+#include "RE_engine.h"
+
#ifdef WITH_AUDASPACE
-# include AUD_SPECIAL_H
+# include <AUD_Special.h>
#endif
/* mutable state for sequencer */
@@ -3259,6 +3263,10 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
// have_seq = (scene->r.scemode & R_DOSEQ) && scene->ed && scene->ed->seqbase.first); /* UNUSED */
have_comp = (scene->r.scemode & R_DOCOMP) && scene->use_nodes && scene->nodetree;
+ /* Get depsgraph and scene layer for the strip. */
+ ViewLayer *view_layer = BKE_view_layer_from_scene_get(scene);
+ Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
+
orig_data.scemode = scene->r.scemode;
orig_data.cfra = scene->r.cfra;
orig_data.subframe = scene->r.subframe;
@@ -3314,10 +3322,12 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
context->scene->r.seq_prev_type = 3 /* == OB_SOLID */;
/* opengl offscreen render */
- BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay);
+ context->eval_ctx->engine_type = RE_engines_find(scene->view_render.engine_id);
+ BKE_scene_graph_update_for_newframe(context->eval_ctx, depsgraph, context->bmain, scene, view_layer);
ibuf = sequencer_view3d_cb(
/* set for OpenGL render (NULL when scrubbing) */
- scene, camera, width, height, IB_rect, draw_flags, context->scene->r.seq_prev_type,
+ context->eval_ctx, scene, view_layer, camera, width, height, IB_rect,
+ draw_flags, context->scene->r.seq_prev_type,
scene->r.alphamode, context->gpu_samples, viewname,
context->gpu_fx, context->gpu_offscreen, err_out);
if (ibuf == NULL) {
@@ -3344,7 +3354,14 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
if (re == NULL)
re = RE_NewSceneRender(scene);
- BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay);
+ /* NOTE: Without this tag rendering from command line fails.
+ * TODO(sergey): Need some proper solution with ported
+ * BKE_scene_set_background() or DEG_on_visible_change() ?
+ */
+ RE_SetDepsgraph(re, depsgraph);
+ DEG_graph_id_tag_update(context->bmain, depsgraph, &scene->id, 0);
+
+ BKE_scene_graph_update_for_newframe(context->eval_ctx, depsgraph, context->bmain, scene, view_layer);
RE_BlenderFrame(re, context->bmain, scene, NULL, camera, scene->lay, frame, false);
/* restore previous state after it was toggled on & off by RE_BlenderFrame */
@@ -3404,7 +3421,7 @@ finally:
scene->r.subframe = orig_data.subframe;
if (is_frame_update) {
- BKE_scene_update_for_newframe(context->eval_ctx, context->bmain, scene, scene->lay);
+ BKE_scene_graph_update_for_newframe(context->eval_ctx, depsgraph, context->bmain, scene, view_layer);
}
#ifdef DURIAN_CAMERA_SWITCH
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index 3cf98b284b1..9f9818127bc 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -83,6 +83,8 @@
#include "BKE_smoke.h"
#include "BKE_texture.h"
+#include "DEG_depsgraph.h"
+
#include "RE_shader_ext.h"
#include "GPU_glew.h"
@@ -126,7 +128,7 @@ void smoke_initWaveletBlenderRNA(struct WTURBULENCE *UNUSED(wt), float *UNUSED(s
void smoke_initBlenderRNA(struct FLUID_3D *UNUSED(fluid), float *UNUSED(alpha), float *UNUSED(beta), float *UNUSED(dt_factor), float *UNUSED(vorticity),
int *UNUSED(border_colli), float *UNUSED(burning_rate), float *UNUSED(flame_smoke), float *UNUSED(flame_smoke_color),
float *UNUSED(flame_vorticity), float *UNUSED(flame_ignition_temp), float *UNUSED(flame_max_temp)) {}
-struct DerivedMesh *smokeModifier_do(SmokeModifierData *UNUSED(smd), Scene *UNUSED(scene), Object *UNUSED(ob), DerivedMesh *UNUSED(dm)) { return NULL; }
+struct DerivedMesh *smokeModifier_do(SmokeModifierData *UNUSED(smd), const struct EvaluationContext *UNUSED(eval_ctx), Scene *UNUSED(scene), Object *UNUSED(ob), DerivedMesh *UNUSED(dm)) { return NULL; }
float smoke_get_velocity_at(struct Object *UNUSED(ob), float UNUSED(position[3]), float UNUSED(velocity[3])) { return 0.0f; }
#endif /* WITH_SMOKE */
@@ -693,16 +695,16 @@ void smokeModifier_copy(struct SmokeModifierData *smd, struct SmokeModifierData
#ifdef WITH_SMOKE
// forward decleration
-static void smoke_calc_transparency(SmokeDomainSettings *sds, Scene *scene);
+static void smoke_calc_transparency(SmokeDomainSettings *sds, ViewLayer *view_layer);
static float calc_voxel_transp(float *result, float *input, int res[3], int *pixel, float *tRay, float correct);
-static int get_lamp(Scene *scene, float *light)
+static int get_lamp(ViewLayer *view_layer, float *light)
{
Base *base_tmp = NULL;
int found_lamp = 0;
// try to find a lamp, preferably local
- for (base_tmp = scene->base.first; base_tmp; base_tmp = base_tmp->next) {
+ for (base_tmp = FIRSTBASE(view_layer); base_tmp; base_tmp = base_tmp->next) {
if (base_tmp->object->type == OB_LAMP) {
Lamp *la = base_tmp->object->data;
@@ -2097,7 +2099,7 @@ BLI_INLINE void apply_inflow_fields(SmokeFlowSettings *sfs, float emission_value
}
}
-static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sds, float dt)
+static void update_flowsfluids(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, SmokeDomainSettings *sds, float dt)
{
Object **flowobjs = NULL;
EmissionMap *emaps = NULL;
@@ -2204,7 +2206,7 @@ static void update_flowsfluids(Scene *scene, Object *ob, SmokeDomainSettings *sd
else { /* MOD_SMOKE_FLOW_SOURCE_MESH */
/* update flow object frame */
BLI_mutex_lock(&object_update_lock);
- BKE_object_modifier_update_subframe(scene, collob, true, 5, BKE_scene_frame_get(scene), eModifierType_Smoke);
+ BKE_object_modifier_update_subframe(eval_ctx, scene, collob, true, 5, BKE_scene_frame_get(scene), eModifierType_Smoke);
BLI_mutex_unlock(&object_update_lock);
/* apply flow */
@@ -2516,12 +2518,12 @@ static void update_effectors_task_cb(
}
}
-static void update_effectors(Scene *scene, Object *ob, SmokeDomainSettings *sds, float UNUSED(dt))
+static void update_effectors(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, SmokeDomainSettings *sds, float UNUSED(dt))
{
ListBase *effectors;
/* make sure smoke flow influence is 0.0f */
sds->effector_weights->weight[PFIELD_SMOKEFLOW] = 0.0f;
- effectors = pdInitEffectors(scene, ob, NULL, sds->effector_weights, true);
+ effectors = pdInitEffectors(eval_ctx, scene, ob, NULL, sds->effector_weights, true);
if (effectors) {
// precalculate wind forces
@@ -2551,7 +2553,7 @@ static void update_effectors(Scene *scene, Object *ob, SmokeDomainSettings *sds,
pdEndEffectors(&effectors);
}
-static void step(Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh *domain_dm, float fps)
+static void step(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh *domain_dm, float fps)
{
SmokeDomainSettings *sds = smd->domain;
/* stability values copied from wturbulence.cpp */
@@ -2621,11 +2623,11 @@ static void step(Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh *
for (substep = 0; substep < totalSubsteps; substep++)
{
// calc animated obstacle velocities
- update_flowsfluids(scene, ob, sds, dtSubdiv);
+ update_flowsfluids(eval_ctx, scene, ob, sds, dtSubdiv);
update_obstacles(scene, ob, sds, dtSubdiv, substep, totalSubsteps);
if (sds->total_cells > 1) {
- update_effectors(scene, ob, sds, dtSubdiv); // DG TODO? problem --> uses forces instead of velocity, need to check how they need to be changed with variable dt
+ update_effectors(eval_ctx, scene, ob, sds, dtSubdiv); // DG TODO? problem --> uses forces instead of velocity, need to check how they need to be changed with variable dt
smoke_step(sds->fluid, gravity, dtSubdiv);
}
}
@@ -2718,7 +2720,8 @@ static DerivedMesh *createDomainGeometry(SmokeDomainSettings *sds, Object *ob)
return result;
}
-static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm)
+static void smokeModifier_process(
+ SmokeModifierData *smd, const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, DerivedMesh *dm)
{
if ((smd->type & MOD_SMOKE_TYPE_FLOW))
{
@@ -2839,11 +2842,11 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object *
}
- step(scene, ob, smd, dm, scene->r.frs_sec / scene->r.frs_sec_base);
+ step(eval_ctx, scene, ob, smd, dm, scene->r.frs_sec / scene->r.frs_sec_base);
}
// create shadows before writing cache so they get stored
- smoke_calc_transparency(sds, scene);
+ smoke_calc_transparency(sds, eval_ctx->view_layer);
if (sds->wt && sds->total_cells > 1) {
smoke_turbulence_step(sds->wt, sds->fluid);
@@ -2860,13 +2863,14 @@ static void smokeModifier_process(SmokeModifierData *smd, Scene *scene, Object *
}
}
-struct DerivedMesh *smokeModifier_do(SmokeModifierData *smd, Scene *scene, Object *ob, DerivedMesh *dm)
+struct DerivedMesh *smokeModifier_do(
+ SmokeModifierData *smd, const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, DerivedMesh *dm)
{
/* lock so preview render does not read smoke data while it gets modified */
if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain)
BLI_rw_mutex_lock(smd->domain->fluid_mutex, THREAD_LOCK_WRITE);
- smokeModifier_process(smd, scene, ob, dm);
+ smokeModifier_process(smd, eval_ctx, scene, ob, dm);
if ((smd->type & MOD_SMOKE_TYPE_DOMAIN) && smd->domain)
BLI_rw_mutex_unlock(smd->domain->fluid_mutex);
@@ -2981,7 +2985,7 @@ static void bresenham_linie_3D(int x1, int y1, int z1, int x2, int y2, int z2, f
cb(result, input, res, pixel, tRay, correct);
}
-static void smoke_calc_transparency(SmokeDomainSettings *sds, Scene *scene)
+static void smoke_calc_transparency(SmokeDomainSettings *sds, ViewLayer *view_layer)
{
float bv[6] = {0};
float light[3];
@@ -2989,7 +2993,7 @@ static void smoke_calc_transparency(SmokeDomainSettings *sds, Scene *scene)
float *density = smoke_get_density(sds->fluid);
float correct = -7.0f * sds->dx;
- if (!get_lamp(scene, light)) return;
+ if (!get_lamp(view_layer, light)) return;
/* convert light pos to sim cell space */
mul_m4_v3(sds->imat, light);
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 563148992d9..3cfa8787f4b 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -74,6 +74,7 @@ variables on the UI for now
#include "BKE_curve.h"
#include "BKE_effect.h"
#include "BKE_global.h"
+#include "BKE_group.h"
#include "BKE_modifier.h"
#include "BKE_softbody.h"
#include "BKE_pointcache.h"
@@ -81,6 +82,8 @@ variables on the UI for now
#include "BKE_mesh.h"
#include "BKE_scene.h"
+#include "DEG_depsgraph.h"
+
#include "PIL_time.h"
/* callbacks for errors and interrupts and some goo */
@@ -512,35 +515,26 @@ static void ccd_build_deflector_hash_single(GHash *hash, Object *ob)
/**
* \note group overrides scene when not NULL.
*/
-static void ccd_build_deflector_hash(Scene *scene, Group *group, Object *vertexowner, GHash *hash)
+static void ccd_build_deflector_hash(ViewLayer *view_layer, Group *group, Object *vertexowner, GHash *hash)
{
Object *ob;
if (!hash) return;
+ /* Explicit collision group. */
if (group) {
- /* Explicit collision group */
- for (GroupObject *go = group->gobject.first; go; go = go->next) {
- ob = go->ob;
-
- if (ob == vertexowner || ob->type != OB_MESH)
- continue;
-
- ccd_build_deflector_hash_single(hash, ob);
- }
+ view_layer = group->view_layer;
}
- else {
- for (Base *base = scene->base.first; base; base = base->next) {
- /*Only proceed for mesh object in same layer */
- if (base->object->type == OB_MESH && (base->lay & vertexowner->lay)) {
- ob= base->object;
- if ((vertexowner) && (ob == vertexowner)) {
- /* if vertexowner is given we don't want to check collision with owner object */
- continue;
- }
- ccd_build_deflector_hash_single(hash, ob);
+ for (Base *base = FIRSTBASE(view_layer); base; base = base->next) {
+ /* Only proceed for mesh object in same layer. */
+ if (base->object->type == OB_MESH) {
+ ob = base->object;
+ if (ob == vertexowner) {
+ /* If vertexowner is given we don't want to check collision with owner object. */
+ continue;
}
+ ccd_build_deflector_hash_single(hash, ob);
}
}
}
@@ -558,37 +552,29 @@ static void ccd_update_deflector_hash_single(GHash *hash, Object *ob)
/**
* \note group overrides scene when not NULL.
*/
-static void ccd_update_deflector_hash(Scene *scene, Group *group, Object *vertexowner, GHash *hash)
+static void ccd_update_deflector_hash(ViewLayer *view_layer, Group *group, Object *vertexowner, GHash *hash)
{
Object *ob;
if ((!hash) || (!vertexowner)) return;
+ /* Explicit collision group. */
if (group) {
- /* Explicit collision group */
- for (GroupObject *go = group->gobject.first; go; go = go->next) {
- ob = go->ob;
+ view_layer = group->view_layer;
+ }
- if (ob == vertexowner || ob->type != OB_MESH)
+ for (Base *base = FIRSTBASE(view_layer); base; base = base->next) {
+ /* Only proceed for mesh object in same layer. */
+ if (base->object->type == OB_MESH) {
+ ob = base->object;
+ if (ob == vertexowner) {
+ /* If vertexowner is given we don't want to check collision with owner object. */
continue;
+ }
ccd_update_deflector_hash_single(hash, ob);
}
}
- else {
- for (Base *base = scene->base.first; base; base = base->next) {
- /*Only proceed for mesh object in same layer */
- if (base->object->type == OB_MESH && (base->lay & vertexowner->lay)) {
- ob= base->object;
- if (ob == vertexowner) {
- /* if vertexowner is given we don't want to check collision with owner object */
- continue;
- }
-
- ccd_update_deflector_hash_single(hash, ob);
- }
- }
- }
}
@@ -977,29 +963,21 @@ static void free_softbody_intern(SoftBody *sb)
/**
* \note group overrides scene when not NULL.
*/
-static bool are_there_deflectors(Scene *scene, Group *group, unsigned int layer)
+static bool are_there_deflectors(ViewLayer *view_layer)
{
- if (group) {
- for (GroupObject *go = group->gobject.first; go; go = go->next) {
- if (go->ob->pd && go->ob->pd->deflect)
+ for (Base *base = FIRSTBASE(view_layer); base; base = base->next) {
+ if (base->object->pd) {
+ if (base->object->pd->deflect)
return 1;
}
}
- else {
- for (Base *base = scene->base.first; base; base= base->next) {
- if ( (base->lay & layer) && base->object->pd) {
- if (base->object->pd->deflect)
- return 1;
- }
- }
- }
return 0;
}
-static int query_external_colliders(Scene *scene, Group *group, Object *me)
+static int query_external_colliders(ViewLayer *view_layer, Group *group)
{
- return(are_there_deflectors(scene, group, me->lay));
+ return(are_there_deflectors(group != NULL ? group->view_layer : view_layer));
}
/* --- dependency information functions*/
@@ -1544,12 +1522,12 @@ static void _scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow,
}
-static void scan_for_ext_spring_forces(Scene *scene, Object *ob, float timenow)
+static void scan_for_ext_spring_forces(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float timenow)
{
SoftBody *sb = ob->soft;
ListBase *do_effector = NULL;
- do_effector = pdInitEffectors(scene, ob, NULL, sb->effector_weights, true);
+ do_effector = pdInitEffectors(eval_ctx, scene, ob, NULL, sb->effector_weights, true);
_scan_for_ext_spring_forces(scene, ob, timenow, 0, sb->totspring, do_effector);
pdEndEffectors(&do_effector);
}
@@ -1561,7 +1539,7 @@ static void *exec_scan_for_ext_spring_forces(void *data)
return NULL;
}
-static void sb_sfesf_threads_run(Scene *scene, struct Object *ob, float timenow, int totsprings, int *UNUSED(ptr_to_break_func(void)))
+static void sb_sfesf_threads_run(const struct EvaluationContext *eval_ctx, Scene *scene, struct Object *ob, float timenow, int totsprings, int *UNUSED(ptr_to_break_func(void)))
{
ListBase *do_effector = NULL;
ListBase threads;
@@ -1569,7 +1547,7 @@ static void sb_sfesf_threads_run(Scene *scene, struct Object *ob, float timenow,
int i, totthread, left, dec;
int lowsprings =100; /* wild guess .. may increase with better thread management 'above' or even be UI option sb->spawn_cf_threads_nopts */
- do_effector= pdInitEffectors(scene, ob, NULL, ob->soft->effector_weights, true);
+ do_effector= pdInitEffectors(eval_ctx, scene, ob, NULL, ob->soft->effector_weights, true);
/* figure the number of threads while preventing pretty pointless threading overhead */
totthread= BKE_scene_num_threads(scene);
@@ -2227,7 +2205,7 @@ static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float t
MEM_freeN(sb_threads);
}
-static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, float timenow)
+static void softbody_calc_forcesEx(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float forcetime, float timenow)
{
/* rule we never alter free variables :bp->vec bp->pos in here !
* this will ruin adaptive stepsize AKA heun! (BM)
@@ -2243,7 +2221,7 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl
/* gravity = sb->grav * sb_grav_force_scale(ob); */ /* UNUSED */
/* check conditions for various options */
- do_deflector= query_external_colliders(scene, sb->collision_group, ob);
+ do_deflector= query_external_colliders(eval_ctx->view_layer, sb->collision_group);
/* do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF)); */ /* UNUSED */
do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL);
do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES));
@@ -2252,10 +2230,10 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl
/* bproot= sb->bpoint; */ /* need this for proper spring addressing */ /* UNUSED */
if (do_springcollision || do_aero)
- sb_sfesf_threads_run(scene, ob, timenow, sb->totspring, NULL);
+ sb_sfesf_threads_run(eval_ctx, scene, ob, timenow, sb->totspring, NULL);
/* after spring scan because it uses Effoctors too */
- do_effector= pdInitEffectors(scene, ob, NULL, sb->effector_weights, true);
+ do_effector= pdInitEffectors(eval_ctx, scene, ob, NULL, sb->effector_weights, true);
if (do_deflector) {
float defforce[3];
@@ -2272,11 +2250,11 @@ static void softbody_calc_forcesEx(Scene *scene, Object *ob, float forcetime, fl
}
-static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, float timenow)
+static void softbody_calc_forces(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float forcetime, float timenow)
{
/* redirection to the new threaded Version */
if (!(G.debug_value & 0x10)) { // 16
- softbody_calc_forcesEx(scene, ob, forcetime, timenow);
+ softbody_calc_forcesEx(eval_ctx, scene, ob, forcetime, timenow);
return;
}
else {
@@ -2307,7 +2285,7 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
}
/* check conditions for various options */
- do_deflector= query_external_colliders(scene, sb->collision_group, ob);
+ do_deflector= query_external_colliders(eval_ctx->view_layer, sb->collision_group);
do_selfcollision=((ob->softflag & OB_SB_EDGES) && (sb->bspring)&& (ob->softflag & OB_SB_SELF));
do_springcollision=do_deflector && (ob->softflag & OB_SB_EDGES) &&(ob->softflag & OB_SB_EDGECOLL);
do_aero=((sb->aeroedge)&& (ob->softflag & OB_SB_EDGES));
@@ -2315,9 +2293,9 @@ static void softbody_calc_forces(Scene *scene, Object *ob, float forcetime, floa
iks = 1.0f/(1.0f-sb->inspring)-1.0f ;/* inner spring constants function */
/* bproot= sb->bpoint; */ /* need this for proper spring addressing */ /* UNUSED */
- if (do_springcollision || do_aero) scan_for_ext_spring_forces(scene, ob, timenow);
+ if (do_springcollision || do_aero) scan_for_ext_spring_forces(eval_ctx, scene, ob, timenow);
/* after spring scan because it uses Effoctors too */
- do_effector= pdInitEffectors(scene, ob, NULL, ob->soft->effector_weights, true);
+ do_effector= pdInitEffectors(eval_ctx, scene, ob, NULL, ob->soft->effector_weights, true);
if (do_deflector) {
float defforce[3];
@@ -3504,7 +3482,7 @@ static void softbody_reset(Object *ob, SoftBody *sb, float (*vertexCos)[3], int
}
}
-static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
+static void softbody_step(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, SoftBody *sb, float dtime)
{
/* the simulator */
float forcetime;
@@ -3518,11 +3496,11 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
*/
if (dtime < 0 || dtime > 10.5f) return;
- ccd_update_deflector_hash(scene, sb->collision_group, ob, sb->scratch->colliderhash);
+ ccd_update_deflector_hash(eval_ctx->view_layer, sb->collision_group, ob, sb->scratch->colliderhash);
if (sb->scratch->needstobuildcollider) {
- if (query_external_colliders(scene, sb->collision_group, ob)) {
- ccd_build_deflector_hash(scene, sb->collision_group, ob, sb->scratch->colliderhash);
+ if (query_external_colliders(eval_ctx->view_layer, sb->collision_group)) {
+ ccd_build_deflector_hash(eval_ctx->view_layer, sb->collision_group, ob, sb->scratch->colliderhash);
}
sb->scratch->needstobuildcollider=0;
}
@@ -3552,12 +3530,12 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
sb->scratch->flag &= ~SBF_DOFUZZY;
/* do predictive euler step */
- softbody_calc_forces(scene, ob, forcetime, timedone/dtime);
+ softbody_calc_forces(eval_ctx, scene, ob, forcetime, timedone/dtime);
softbody_apply_forces(ob, forcetime, 1, NULL, mid_flags);
/* crop new slope values to do averaged slope step */
- softbody_calc_forces(scene, ob, forcetime, timedone/dtime);
+ softbody_calc_forces(eval_ctx, scene, ob, forcetime, timedone/dtime);
softbody_apply_forces(ob, forcetime, 2, &err, mid_flags);
softbody_apply_goalsnap(ob);
@@ -3638,7 +3616,7 @@ static void softbody_step(Scene *scene, Object *ob, SoftBody *sb, float dtime)
}
/* simulates one step. framenr is in frames */
-void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], int numVerts)
+void sbObjectStep(const struct EvaluationContext *eval_ctx, Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], int numVerts)
{
SoftBody *sb= ob->soft;
PointCache *cache;
@@ -3646,7 +3624,6 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
float dtime, timescale;
int framedelta, framenr, startframe, endframe;
int cache_result;
-
cache= sb->pointcache;
framenr= (int)cfra;
@@ -3715,7 +3692,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
}
/* try to read from cache */
- bool can_simulate = (framenr == sb->last_frame+1) && !(cache->flag & PTCACHE_BAKED);
+ bool can_simulate = (framenr == sb->last_frame + 1) && !(cache->flag & PTCACHE_BAKED);
cache_result = BKE_ptcache_read(&pid, (float)framenr+scene->r.subframe, can_simulate);
@@ -3754,7 +3731,7 @@ void sbObjectStep(Scene *scene, Object *ob, float cfra, float (*vertexCos)[3], i
dtime = framedelta*timescale;
/* do simulation */
- softbody_step(scene, ob, sb, dtime);
+ softbody_step(eval_ctx, scene, ob, sb, dtime);
softbody_to_object(ob, vertexCos, numVerts, 0);
diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c
index 45d1f969d64..747ffdafe8b 100644
--- a/source/blender/blenkernel/intern/sound.c
+++ b/source/blender/blenkernel/intern/sound.c
@@ -48,13 +48,11 @@
#include "DNA_speaker_types.h"
#ifdef WITH_AUDASPACE
-# include AUD_SOUND_H
-# include AUD_SEQUENCE_H
-# include AUD_HANDLE_H
-# include AUD_SPECIAL_H
-# ifdef WITH_SYSTEM_AUDASPACE
-# include "../../../intern/audaspace/intern/AUD_Set.h"
-# endif
+# include <AUD_Sound.h>
+# include <AUD_Sequence.h>
+# include <AUD_Handle.h>
+# include <AUD_Special.h>
+# include "../../../intern/audaspace/intern/AUD_Set.h"
#endif
#include "BKE_global.h"
@@ -228,7 +226,7 @@ void BKE_sound_init_once(void)
atexit(BKE_sound_exit_once);
}
-static AUD_Device *sound_device;
+static AUD_Device *sound_device = NULL;
void *BKE_sound_get_device(void)
{
@@ -237,6 +235,9 @@ void *BKE_sound_get_device(void)
void BKE_sound_init(struct Main *bmain)
{
+ /* Make sure no instance of the sound system is running, otherwise we get leaks. */
+ BKE_sound_exit();
+
AUD_DeviceSpecs specs;
int device, buffersize;
const char *device_name;
@@ -302,7 +303,6 @@ void BKE_sound_exit_once(void)
sound_device = NULL;
AUD_exitOnce();
-#ifdef WITH_SYSTEM_AUDASPACE
if (audio_device_names != NULL) {
int i;
for (i = 0; audio_device_names[i]; i++) {
@@ -311,7 +311,6 @@ void BKE_sound_exit_once(void)
free(audio_device_names);
audio_device_names = NULL;
}
-#endif
}
/* XXX unused currently */
@@ -807,13 +806,76 @@ void BKE_sound_read_waveform(bSound *sound, short *stop)
BLI_spin_unlock(sound->spinlock);
}
-void BKE_sound_update_scene(Main *bmain, struct Scene *scene)
+static void sound_update_base(Scene *scene, Base *base, void *new_set)
{
- Object *ob;
- Base *base;
+ Object *ob = base->object;
NlaTrack *track;
NlaStrip *strip;
Speaker *speaker;
+ float quat[4];
+
+ if ((ob->id.tag & LIB_TAG_DOIT) == 0) {
+ return;
+ }
+
+ ob->id.tag &= ~LIB_TAG_DOIT;
+
+ if ((ob->type != OB_SPEAKER) || !ob->adt) {
+ return;
+ }
+
+ for (track = ob->adt->nla_tracks.first; track; track = track->next) {
+ for (strip = track->strips.first; strip; strip = strip->next) {
+ if (strip->type != NLASTRIP_TYPE_SOUND) {
+ continue;
+ }
+ speaker = (Speaker *)ob->data;
+
+ if (AUD_removeSet(scene->speaker_handles, strip->speaker_handle)) {
+ if (speaker->sound) {
+ AUD_SequenceEntry_move(strip->speaker_handle, (double)strip->start / FPS, FLT_MAX, 0);
+ }
+ else {
+ AUD_Sequence_remove(scene->sound_scene, strip->speaker_handle);
+ strip->speaker_handle = NULL;
+ }
+ }
+ else {
+ if (speaker->sound) {
+ strip->speaker_handle = AUD_Sequence_add(scene->sound_scene,
+ speaker->sound->playback_handle,
+ (double)strip->start / FPS, FLT_MAX, 0);
+ AUD_SequenceEntry_setRelative(strip->speaker_handle, 0);
+ }
+ }
+
+ if (strip->speaker_handle) {
+ const bool mute = ((strip->flag & NLASTRIP_FLAG_MUTED) || (speaker->flag & SPK_MUTED));
+ AUD_addSet(new_set, strip->speaker_handle);
+ AUD_SequenceEntry_setVolumeMaximum(strip->speaker_handle, speaker->volume_max);
+ AUD_SequenceEntry_setVolumeMinimum(strip->speaker_handle, speaker->volume_min);
+ AUD_SequenceEntry_setDistanceMaximum(strip->speaker_handle, speaker->distance_max);
+ AUD_SequenceEntry_setDistanceReference(strip->speaker_handle, speaker->distance_reference);
+ AUD_SequenceEntry_setAttenuation(strip->speaker_handle, speaker->attenuation);
+ AUD_SequenceEntry_setConeAngleOuter(strip->speaker_handle, speaker->cone_angle_outer);
+ AUD_SequenceEntry_setConeAngleInner(strip->speaker_handle, speaker->cone_angle_inner);
+ AUD_SequenceEntry_setConeVolumeOuter(strip->speaker_handle, speaker->cone_volume_outer);
+
+ mat4_to_quat(quat, ob->obmat);
+ AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_LOCATION, CFRA, ob->obmat[3], 1);
+ AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_ORIENTATION, CFRA, quat, 1);
+ AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_VOLUME, CFRA, &speaker->volume, 1);
+ AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_PITCH, CFRA, &speaker->pitch, 1);
+ AUD_SequenceEntry_setSound(strip->speaker_handle, speaker->sound->playback_handle);
+ AUD_SequenceEntry_setMuted(strip->speaker_handle, mute);
+ }
+ }
+ }
+}
+
+void BKE_sound_update_scene(Main *bmain, Scene *scene)
+{
+ Base *base;
Scene *sce_it;
void *new_set = AUD_createSet();
@@ -822,59 +884,18 @@ void BKE_sound_update_scene(Main *bmain, struct Scene *scene)
/* cheap test to skip looping over all objects (no speakers is a common case) */
if (!BLI_listbase_is_empty(&bmain->speaker)) {
- for (SETLOOPER(scene, sce_it, base)) {
- ob = base->object;
- if ((ob->type != OB_SPEAKER) || !ob->adt) {
- continue;
- }
- for (track = ob->adt->nla_tracks.first; track; track = track->next) {
- for (strip = track->strips.first; strip; strip = strip->next) {
- if (strip->type != NLASTRIP_TYPE_SOUND) {
- continue;
- }
- speaker = (Speaker *)ob->data;
-
- if (AUD_removeSet(scene->speaker_handles, strip->speaker_handle)) {
- if (speaker->sound) {
- AUD_SequenceEntry_move(strip->speaker_handle, (double)strip->start / FPS, FLT_MAX, 0);
- }
- else {
- AUD_Sequence_remove(scene->sound_scene, strip->speaker_handle);
- strip->speaker_handle = NULL;
- }
- }
- else {
- if (speaker->sound) {
- strip->speaker_handle = AUD_Sequence_add(scene->sound_scene,
- speaker->sound->playback_handle,
- (double)strip->start / FPS, FLT_MAX, 0);
- AUD_SequenceEntry_setRelative(strip->speaker_handle, 0);
- }
- }
-
- if (strip->speaker_handle) {
- const bool mute = ((strip->flag & NLASTRIP_FLAG_MUTED) || (speaker->flag & SPK_MUTED));
- AUD_addSet(new_set, strip->speaker_handle);
- AUD_SequenceEntry_setVolumeMaximum(strip->speaker_handle, speaker->volume_max);
- AUD_SequenceEntry_setVolumeMinimum(strip->speaker_handle, speaker->volume_min);
- AUD_SequenceEntry_setDistanceMaximum(strip->speaker_handle, speaker->distance_max);
- AUD_SequenceEntry_setDistanceReference(strip->speaker_handle, speaker->distance_reference);
- AUD_SequenceEntry_setAttenuation(strip->speaker_handle, speaker->attenuation);
- AUD_SequenceEntry_setConeAngleOuter(strip->speaker_handle, speaker->cone_angle_outer);
- AUD_SequenceEntry_setConeAngleInner(strip->speaker_handle, speaker->cone_angle_inner);
- AUD_SequenceEntry_setConeVolumeOuter(strip->speaker_handle, speaker->cone_volume_outer);
-
- mat4_to_quat(quat, ob->obmat);
- AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_LOCATION, CFRA, ob->obmat[3], 1);
- AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_ORIENTATION, CFRA, quat, 1);
- AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_VOLUME, CFRA, &speaker->volume, 1);
- AUD_SequenceEntry_setAnimationData(strip->speaker_handle, AUD_AP_PITCH, CFRA, &speaker->pitch, 1);
- AUD_SequenceEntry_setSound(strip->speaker_handle, speaker->sound->playback_handle);
- AUD_SequenceEntry_setMuted(strip->speaker_handle, mute);
- }
- }
+ BKE_main_id_tag_listbase(&bmain->object, LIB_TAG_DOIT, true);
+
+ for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
+ for (base = view_layer->object_bases.first; base; base = base->next) {
+ sound_update_base(scene, base, new_set);
}
}
+
+ for (SETLOOPER_SET_ONLY(scene, sce_it, base)) {
+ sound_update_base(scene, base, new_set);
+ }
+
}
while ((handle = AUD_getSet(scene->speaker_handles))) {
@@ -907,28 +928,12 @@ float BKE_sound_get_length(bSound *sound)
char **BKE_sound_get_device_names(void)
{
if (audio_device_names == NULL) {
-#ifdef WITH_SYSTEM_AUDASPACE
audio_device_names = AUD_getDeviceNames();
-#else
- static const char *names[] = {
- "Null", "SDL", "OpenAL", "JACK", NULL
- };
- audio_device_names = (char **)names;
-#endif
}
return audio_device_names;
}
-bool BKE_sound_is_jack_supported(void)
-{
-#ifdef WITH_SYSTEM_AUDASPACE
- return 1;
-#else
- return (bool)AUD_isJackSupported();
-#endif
-}
-
#else /* WITH_AUDASPACE */
#include "BLI_utildefines.h"
@@ -975,5 +980,6 @@ void BKE_sound_set_scene_sound_pan(void *UNUSED(handle), float UNUSED(pan), char
void BKE_sound_set_scene_volume(struct Scene *UNUSED(scene), float UNUSED(volume)) {}
void BKE_sound_set_scene_sound_pitch(void *UNUSED(handle), float UNUSED(pitch), char UNUSED(animated)) {}
float BKE_sound_get_length(struct bSound *UNUSED(sound)) { return 0; }
-bool BKE_sound_is_jack_supported(void) { return false; }
+char **BKE_sound_get_device_names(void) { static char *names[1] = {NULL}; return names; }
+
#endif /* WITH_AUDASPACE */
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 8bace2a8d65..5e2fb220327 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -1931,7 +1931,8 @@ static void ccgDM_glNormalFast(float *a, float *b, float *c, float *d)
no[1] = b_dZ * a_cX - b_dX * a_cZ;
no[2] = b_dX * a_cY - b_dY * a_cX;
- /* don't normalize, GL_NORMALIZE is enabled */
+ normalize_v3(no); /* we no longer rely on GL_NORMALIZE */
+
glNormal3fv(no);
}
@@ -3439,261 +3440,6 @@ static void ccgDM_drawMappedFacesMat(DerivedMesh *dm,
#undef PASSATTRIB
}
-static void ccgDM_drawFacesTex_common(DerivedMesh *dm,
- DMSetDrawOptionsTex drawParams,
- DMSetDrawOptionsMappedTex drawParamsMapped,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag flag)
-{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh *) dm;
- CCGSubSurf *ss = ccgdm->ss;
- CCGKey key;
- int colType;
- const MLoopCol *mloopcol = NULL;
- MTexPoly *mtexpoly = DM_get_poly_data_layer(dm, CD_MTEXPOLY);
- DMFlagMat *faceFlags = ccgdm->faceFlags;
- DMDrawOption draw_option;
- int i, totpoly;
- bool flush;
- const bool use_tface = (flag & DM_DRAW_USE_ACTIVE_UV) != 0;
- const bool use_colors = (flag & DM_DRAW_USE_COLORS) != 0;
- unsigned int next_actualFace;
- unsigned int gridFaces = ccgSubSurf_getGridSize(ss) - 1;
- int mat_index;
- int tot_element, start_element, tot_drawn;
-
- if (use_colors) {
- colType = CD_TEXTURE_MLOOPCOL;
- mloopcol = dm->getLoopDataArray(dm, colType);
- if (!mloopcol) {
- colType = CD_PREVIEW_MLOOPCOL;
- mloopcol = dm->getLoopDataArray(dm, colType);
- }
- if (!mloopcol) {
- colType = CD_MLOOPCOL;
- mloopcol = dm->getLoopDataArray(dm, colType);
- }
- }
-
-#ifdef WITH_OPENSUBDIV
- if (ccgdm->useGpuBackend) {
- const int active_uv_layer = CustomData_get_active_layer_index(&dm->loopData, CD_MLOOPUV);
- if (UNLIKELY(ccgSubSurf_prepareGLMesh(ss, true, active_uv_layer) == false)) {
- return;
- }
- if (drawParams == NULL) {
- ccgSubSurf_drawGLMesh(ss, true, -1, -1);
- return;
- }
- const int level = ccgSubSurf_getSubdivisionLevels(ss);
- const int face_side = 1 << level;
- const int grid_side = 1 << (level - 1);
- const int face_patches = face_side * face_side;
- const int grid_patches = grid_side * grid_side;
- const int num_base_faces = ccgSubSurf_getNumGLMeshBaseFaces(ss);
- int current_patch = 0;
- int mat_nr = -1;
- int start_draw_patch = 0, num_draw_patches = 0;
- bool draw_smooth = false;
- for (i = 0; i < num_base_faces; ++i) {
- const int num_face_verts = ccgSubSurf_getNumGLMeshBaseFaceVerts(ss, i);
- const int num_patches = (num_face_verts == 4) ? face_patches
- : num_face_verts * grid_patches;
- if (faceFlags) {
- mat_nr = faceFlags[i].mat_nr;
- draw_smooth = (faceFlags[i].flag & ME_SMOOTH);
- }
- else {
- mat_nr = 0;
- draw_smooth = false;
- }
-
- if (drawParams != NULL) {
- MTexPoly *tp = (use_tface && mtexpoly) ? &mtexpoly[i] : NULL;
- draw_option = drawParams(tp, (mloopcol != NULL), mat_nr);
- }
- else {
- draw_option = (drawParamsMapped)
- ? drawParamsMapped(userData, i, mat_nr)
- : DM_DRAW_OPTION_NORMAL;
- }
-
- flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == num_base_faces - 1);
-
- const int next_face = min_ii(i + 1, num_base_faces - 1);
- if (!flush && compareDrawOptions) {
- flush |= compareDrawOptions(userData, i, next_face) == 0;
- }
- if (!flush && faceFlags) {
- bool new_draw_smooth = (faceFlags[next_face].flag & ME_SMOOTH);
- flush |= (new_draw_smooth != draw_smooth);
- }
-
- current_patch += num_patches;
-
- if (flush) {
- if (draw_option != DM_DRAW_OPTION_SKIP) {
- num_draw_patches += num_patches;
- }
- if (num_draw_patches != 0) {
- glShadeModel(draw_smooth ? GL_SMOOTH : GL_FLAT);
- ccgSubSurf_drawGLMesh(ss,
- true,
- start_draw_patch,
- num_draw_patches);
- }
- start_draw_patch = current_patch;
- num_draw_patches = 0;
- }
- else {
- num_draw_patches += num_patches;
- }
- }
- glShadeModel(GL_SMOOTH);
- return;
- }
-#endif
-
- CCG_key_top_level(&key, ss);
- ccgdm_pbvh_update(ccgdm);
-
- GPU_vertex_setup(dm);
- GPU_normal_setup(dm);
- GPU_triangle_setup(dm);
- if (flag & DM_DRAW_USE_TEXPAINT_UV)
- GPU_texpaint_uv_setup(dm);
- else
- GPU_uv_setup(dm);
- if (mloopcol) {
- GPU_color_setup(dm, colType);
- }
-
- next_actualFace = 0;
-
- /* lastFlag = 0; */ /* UNUSED */
- for (mat_index = 0; mat_index < dm->drawObject->totmaterial; mat_index++) {
- GPUBufferMaterial *bufmat = dm->drawObject->materials + mat_index;
- next_actualFace = bufmat->polys[0];
- totpoly = bufmat->totpolys;
-
- tot_element = 0;
- tot_drawn = 0;
- start_element = 0;
-
- for (i = 0; i < totpoly; i++) {
- int polyindex = bufmat->polys[i];
- CCGFace *f = ccgdm->faceMap[polyindex].face;
- int numVerts = ccgSubSurf_getFaceNumVerts(f);
- int index = ccgDM_getFaceMapIndex(ss, f);
- int orig_index = GET_INT_FROM_POINTER(ccgSubSurf_getFaceFaceHandle(f));
- int mat_nr;
- int facequads = numVerts * gridFaces * gridFaces;
- int actualFace = ccgdm->faceMap[polyindex].startFace;
-
- if (i != totpoly - 1) {
- polyindex = bufmat->polys[i + 1];
- next_actualFace = ccgdm->faceMap[polyindex].startFace;
- }
-
- if (faceFlags) {
- mat_nr = faceFlags[orig_index].mat_nr;
- }
- else {
- mat_nr = 0;
- }
-
- if (drawParams) {
- MTexPoly *tp = (use_tface && mtexpoly) ? &mtexpoly[actualFace] : NULL;
- draw_option = drawParams(tp, (mloopcol != NULL), mat_nr);
- }
- else if (index != ORIGINDEX_NONE)
- draw_option = (drawParamsMapped) ? drawParamsMapped(userData, index, mat_nr) : DM_DRAW_OPTION_NORMAL;
- else
- draw_option = DM_DRAW_OPTION_NORMAL;
-
- /* flush buffer if current triangle isn't drawable or it's last triangle */
- flush = (draw_option == DM_DRAW_OPTION_SKIP) || (i == totpoly - 1);
-
- if (!flush && compareDrawOptions) {
- /* also compare draw options and flush buffer if they're different
- * need for face selection highlight in edit mode */
- flush |= compareDrawOptions(userData, actualFace, next_actualFace) == 0;
- }
-
- tot_element += facequads * 6;
-
- if (flush) {
- if (draw_option != DM_DRAW_OPTION_SKIP)
- tot_drawn += facequads * 6;
-
- if (tot_drawn) {
- if (mloopcol && draw_option != DM_DRAW_OPTION_NO_MCOL)
- GPU_color_switch(1);
- else
- GPU_color_switch(0);
-
- GPU_buffer_draw_elements(dm->drawObject->triangles, GL_TRIANGLES, bufmat->start + start_element, tot_drawn);
- tot_drawn = 0;
- }
-
- start_element = tot_element;
- }
- else {
- tot_drawn += facequads * 6;
- }
- }
- }
-
-
- GPU_buffers_unbind();
-}
-
-static void ccgDM_drawFacesTex(DerivedMesh *dm,
- DMSetDrawOptionsTex setDrawOptions,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag flag)
-{
- ccgDM_drawFacesTex_common(dm, setDrawOptions, NULL, compareDrawOptions, userData, flag);
-}
-
-static void ccgDM_drawMappedFacesTex(DerivedMesh *dm,
- DMSetDrawOptionsMappedTex setDrawOptions,
- DMCompareDrawOptions compareDrawOptions,
- void *userData, DMDrawFlag flag)
-{
- ccgDM_drawFacesTex_common(dm, NULL, setDrawOptions, compareDrawOptions, userData, flag);
-}
-
-/* same as cdDM_drawUVEdges */
-static void ccgDM_drawUVEdges(DerivedMesh *dm)
-{
- MPoly *mpoly = dm->getPolyArray(dm);
- int totpoly = dm->getNumPolys(dm);
- int prevstart = 0;
- bool prevdraw = true;
- int curpos = 0;
- int i;
-
- GPU_uvedge_setup(dm);
- for (i = 0; i < totpoly; i++, mpoly++) {
- const bool draw = (mpoly->flag & ME_HIDE) == 0;
-
- if (prevdraw != draw) {
- if (prevdraw && (curpos != prevstart)) {
- glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
- }
- prevstart = curpos;
- }
-
- curpos += 2 * mpoly->totloop;
- prevdraw = draw;
- }
- if (prevdraw && (curpos != prevstart)) {
- glDrawArrays(GL_LINES, prevstart, curpos - prevstart);
- }
- GPU_buffers_unbind();
-}
-
static void ccgDM_drawMappedFaces(DerivedMesh *dm,
DMSetDrawOptions setDrawOptions,
DMSetMaterial setMaterial,
@@ -4628,13 +4374,10 @@ static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm)
ccgdm->dm.drawEdges = ccgDM_drawEdges;
ccgdm->dm.drawLooseEdges = ccgDM_drawLooseEdges;
ccgdm->dm.drawFacesSolid = ccgDM_drawFacesSolid;
- ccgdm->dm.drawFacesTex = ccgDM_drawFacesTex;
ccgdm->dm.drawFacesGLSL = ccgDM_drawFacesGLSL;
ccgdm->dm.drawMappedFaces = ccgDM_drawMappedFaces;
- ccgdm->dm.drawMappedFacesTex = ccgDM_drawMappedFacesTex;
ccgdm->dm.drawMappedFacesGLSL = ccgDM_drawMappedFacesGLSL;
ccgdm->dm.drawMappedFacesMat = ccgDM_drawMappedFacesMat;
- ccgdm->dm.drawUVEdges = ccgDM_drawUVEdges;
ccgdm->dm.drawMappedEdgesInterp = ccgDM_drawMappedEdgesInterp;
ccgdm->dm.drawMappedEdges = ccgDM_drawMappedEdges;
@@ -5092,8 +4835,7 @@ static bool subsurf_use_gpu_backend(SubsurfFlags flags)
*/
return
(flags & SUBSURF_USE_GPU_BACKEND) != 0 &&
- (U.opensubdiv_compute_type != USER_OPENSUBDIV_COMPUTE_NONE) &&
- (openSubdiv_supportGPUDisplay());
+ (U.opensubdiv_compute_type != USER_OPENSUBDIV_COMPUTE_NONE);
#else
(void)flags;
return false;
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 7c4aa81ee46..4ae9818f891 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -58,7 +58,6 @@
#include "DNA_node_types.h"
#include "DNA_material_types.h"
-#include "BKE_depsgraph.h"
#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
diff --git a/source/blender/blenkernel/intern/tracking.c b/source/blender/blenkernel/intern/tracking.c
index f9d34534a45..ebd4c04e8ce 100644
--- a/source/blender/blenkernel/intern/tracking.c
+++ b/source/blender/blenkernel/intern/tracking.c
@@ -61,6 +61,7 @@
#include "BKE_movieclip.h"
#include "BKE_object.h"
#include "BKE_scene.h"
+#include "BKE_layer.h"
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
@@ -400,7 +401,7 @@ void BKE_tracking_get_camera_object_matrix(Scene *scene, Object *ob, float mat[4
if (scene->camera)
ob = scene->camera;
else
- ob = BKE_scene_camera_find(scene);
+ ob = BKE_view_layer_camera_find(BKE_view_layer_from_scene_get(scene));
}
if (ob)
diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c
new file mode 100644
index 00000000000..8554cf0fb28
--- /dev/null
+++ b/source/blender/blenkernel/intern/workspace.c
@@ -0,0 +1,523 @@
+/*
+ * ***** BEGIN GPL LICENSE BLOCK *****
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/blenkernel/intern/workspace.c
+ * \ingroup bke
+ */
+
+/* allow accessing private members of DNA_workspace_types.h */
+#define DNA_PRIVATE_WORKSPACE_ALLOW
+
+#include <stdlib.h>
+
+#include "BLI_utildefines.h"
+#include "BLI_string.h"
+#include "BLI_string_utf8.h"
+#include "BLI_string_utils.h"
+#include "BLI_listbase.h"
+
+#include "BKE_global.h"
+#include "BKE_library.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
+#include "BKE_screen.h"
+#include "BKE_workspace.h"
+
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_workspace_types.h"
+
+#include "MEM_guardedalloc.h"
+
+
+/* -------------------------------------------------------------------- */
+/* Internal utils */
+
+static void workspace_layout_name_set(
+ WorkSpace *workspace, WorkSpaceLayout *layout, const char *new_name)
+{
+ BLI_strncpy(layout->name, new_name, sizeof(layout->name));
+ BLI_uniquename(&workspace->layouts, layout, "Layout", '.', offsetof(WorkSpaceLayout, name), sizeof(layout->name));
+}
+
+/**
+ * This should only be used directly when it is to be expected that there isn't
+ * a layout within \a workspace that wraps \a screen. Usually - especially outside
+ * of BKE_workspace - #BKE_workspace_layout_find should be used!
+ */
+static WorkSpaceLayout *workspace_layout_find_exec(
+ const WorkSpace *workspace, const bScreen *screen)
+{
+ return BLI_findptr(&workspace->layouts, screen, offsetof(WorkSpaceLayout, screen));
+}
+
+static void workspace_relation_add(
+ ListBase *relation_list, void *parent, void *data)
+{
+ WorkSpaceDataRelation *relation = MEM_callocN(sizeof(*relation), __func__);
+ relation->parent = parent;
+ relation->value = data;
+ /* add to head, if we switch back to it soon we find it faster. */
+ BLI_addhead(relation_list, relation);
+}
+static void workspace_relation_remove(
+ ListBase *relation_list, WorkSpaceDataRelation *relation)
+{
+ BLI_remlink(relation_list, relation);
+ MEM_freeN(relation);
+}
+
+static void workspace_relation_ensure_updated(
+ ListBase *relation_list, void *parent, void *data)
+{
+ WorkSpaceDataRelation *relation = BLI_findptr(relation_list, parent, offsetof(WorkSpaceDataRelation, parent));
+ if (relation != NULL) {
+ relation->value = data;
+ /* reinsert at the head of the list, so that more commonly used relations are found faster. */
+ BLI_remlink(relation_list, relation);
+ BLI_addhead(relation_list, relation);
+ }
+ else {
+ /* no matching relation found, add new one */
+ workspace_relation_add(relation_list, parent, data);
+ }
+}
+
+static void *workspace_relation_get_data_matching_parent(
+ const ListBase *relation_list, const void *parent)
+{
+ WorkSpaceDataRelation *relation = BLI_findptr(relation_list, parent, offsetof(WorkSpaceDataRelation, parent));
+ if (relation != NULL) {
+ return relation->value;
+ }
+ else {
+ return NULL;
+ }
+}
+
+static void workspace_relation_remove_from_value(
+ ListBase *relation_list, const void *value)
+{
+ for (WorkSpaceDataRelation *relation = relation_list->first, *relation_next; relation; relation = relation_next) {
+ relation_next = relation->next;
+
+ if (relation->value == value) {
+ workspace_relation_remove(relation_list, relation);
+ }
+ }
+}
+
+/**
+ * Checks if \a screen is already used within any workspace. A screen should never be assigned to multiple
+ * WorkSpaceLayouts, but that should be ensured outside of the BKE_workspace module and without such checks.
+ * Hence, this should only be used as assert check before assigining a screen to a workspace.
+ */
+#ifndef NDEBUG
+static bool workspaces_is_screen_used
+#else
+static bool UNUSED_FUNCTION(workspaces_is_screen_used)
+#endif
+ (const Main *bmain, bScreen *screen)
+{
+ for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
+ if (workspace_layout_find_exec(workspace, screen)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/* -------------------------------------------------------------------- */
+/* Create, delete, init */
+
+WorkSpace *BKE_workspace_add(Main *bmain, const char *name)
+{
+ WorkSpace *new_workspace = BKE_libblock_alloc(bmain, ID_WS, name, 0);
+ return new_workspace;
+}
+
+/**
+ * The function that actually frees the workspace data (not workspace itself). It shouldn't be called
+ * directly, instead #BKE_workspace_remove should be, which calls this through #BKE_libblock_free then.
+ *
+ * Should something like a bke_internal.h be added, this should go there!
+ */
+void BKE_workspace_free(WorkSpace *workspace)
+{
+ BKE_workspace_relations_free(&workspace->hook_layout_relations);
+ BKE_workspace_relations_free(&workspace->scene_viewlayer_relations);
+
+ BLI_freelistN(&workspace->layouts);
+ BLI_freelistN(&workspace->transform_orientations);
+
+ BKE_viewrender_free(&workspace->view_render);
+}
+
+/**
+ * Remove \a workspace by freeing itself and its data. This is a higher-level wrapper that
+ * calls #BKE_workspace_free (through #BKE_libblock_free) to free the workspace data, and frees
+ * other data-blocks owned by \a workspace and its layouts (currently that is screens only).
+ *
+ * Always use this to remove (and free) workspaces. Don't free non-ID workspace members here.
+ */
+void BKE_workspace_remove(Main *bmain, WorkSpace *workspace)
+{
+ for (WorkSpaceLayout *layout = workspace->layouts.first, *layout_next; layout; layout = layout_next) {
+ layout_next = layout->next;
+ BKE_workspace_layout_remove(bmain, workspace, layout);
+ }
+ BKE_libblock_free(bmain, workspace);
+}
+
+WorkSpaceInstanceHook *BKE_workspace_instance_hook_create(const Main *bmain)
+{
+ WorkSpaceInstanceHook *hook = MEM_callocN(sizeof(WorkSpaceInstanceHook), __func__);
+
+ /* set an active screen-layout for each possible window/workspace combination */
+ for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
+ BKE_workspace_hook_layout_for_workspace_set(hook, workspace, workspace->layouts.first);
+ }
+
+ return hook;
+}
+void BKE_workspace_instance_hook_free(const Main *bmain, WorkSpaceInstanceHook *hook)
+{
+ /* workspaces should never be freed before wm (during which we call this function) */
+ BLI_assert(!BLI_listbase_is_empty(&bmain->workspaces));
+
+ /* Free relations for this hook */
+ for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
+ for (WorkSpaceDataRelation *relation = workspace->hook_layout_relations.first, *relation_next;
+ relation;
+ relation = relation_next)
+ {
+ relation_next = relation->next;
+ if (relation->parent == hook) {
+ workspace_relation_remove(&workspace->hook_layout_relations, relation);
+ }
+ }
+ }
+
+ MEM_freeN(hook);
+}
+
+/**
+ * Add a new layout to \a workspace for \a screen.
+ */
+WorkSpaceLayout *BKE_workspace_layout_add(
+ WorkSpace *workspace,
+ bScreen *screen,
+ const char *name)
+{
+ WorkSpaceLayout *layout = MEM_callocN(sizeof(*layout), __func__);
+
+ BLI_assert(!workspaces_is_screen_used(G.main, screen));
+ layout->screen = screen;
+ workspace_layout_name_set(workspace, layout, name);
+ BLI_addtail(&workspace->layouts, layout);
+
+ return layout;
+}
+
+void BKE_workspace_layout_remove(
+ Main *bmain,
+ WorkSpace *workspace, WorkSpaceLayout *layout)
+{
+ BKE_libblock_free(bmain, BKE_workspace_layout_screen_get(layout));
+ BLI_freelinkN(&workspace->layouts, layout);
+}
+
+void BKE_workspace_relations_free(
+ ListBase *relation_list)
+{
+ for (WorkSpaceDataRelation *relation = relation_list->first, *relation_next; relation; relation = relation_next) {
+ relation_next = relation->next;
+ workspace_relation_remove(relation_list, relation);
+ }
+}
+
+
+/* -------------------------------------------------------------------- */
+/* General Utils */
+
+void BKE_workspace_view_layer_remove_references(
+ const Main *bmain,
+ const ViewLayer *view_layer)
+{
+ for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
+ workspace_relation_remove_from_value(&workspace->scene_viewlayer_relations, view_layer);
+ }
+}
+
+void BKE_workspace_transform_orientation_remove(
+ WorkSpace *workspace, TransformOrientation *orientation)
+{
+ for (WorkSpaceLayout *layout = workspace->layouts.first; layout; layout = layout->next) {
+ BKE_screen_transform_orientation_remove(BKE_workspace_layout_screen_get(layout), workspace, orientation);
+ }
+
+ BLI_freelinkN(&workspace->transform_orientations, orientation);
+}
+
+TransformOrientation *BKE_workspace_transform_orientation_find(
+ const WorkSpace *workspace, const int index)
+{
+ return BLI_findlink(&workspace->transform_orientations, index);
+}
+
+/**
+ * \return the index that \a orientation has within \a workspace's transform-orientation list or -1 if not found.
+ */
+int BKE_workspace_transform_orientation_get_index(
+ const WorkSpace *workspace, const TransformOrientation *orientation)
+{
+ return BLI_findindex(&workspace->transform_orientations, orientation);
+}
+
+WorkSpaceLayout *BKE_workspace_layout_find(
+ const WorkSpace *workspace, const bScreen *screen)
+{
+ WorkSpaceLayout *layout = workspace_layout_find_exec(workspace, screen);
+ if (layout) {
+ return layout;
+ }
+
+ printf("%s: Couldn't find layout in this workspace: '%s' screen: '%s'. "
+ "This should not happen!\n",
+ __func__, workspace->id.name + 2, screen->id.name + 2);
+
+ return NULL;
+}
+
+/**
+ * Find the layout for \a screen without knowing which workspace to look in.
+ * Can also be used to find the workspace that contains \a screen.
+ *
+ * \param r_workspace: Optionally return the workspace that contains the looked up layout (if found).
+ */
+WorkSpaceLayout *BKE_workspace_layout_find_global(
+ const Main *bmain, const bScreen *screen,
+ WorkSpace **r_workspace)
+{
+ WorkSpaceLayout *layout;
+
+ if (r_workspace) {
+ *r_workspace = NULL;
+ }
+
+ for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
+ if ((layout = workspace_layout_find_exec(workspace, screen))) {
+ if (r_workspace) {
+ *r_workspace = workspace;
+ }
+
+ return layout;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Circular workspace layout iterator.
+ *
+ * \param callback: Custom function which gets executed for each layout. Can return false to stop iterating.
+ * \param arg: Custom data passed to each \a callback call.
+ *
+ * \return the layout at which \a callback returned false.
+ */
+WorkSpaceLayout *BKE_workspace_layout_iter_circular(
+ const WorkSpace *workspace, WorkSpaceLayout *start,
+ bool (*callback)(const WorkSpaceLayout *layout, void *arg),
+ void *arg, const bool iter_backward)
+{
+ WorkSpaceLayout *iter_layout;
+
+ if (iter_backward) {
+ BLI_LISTBASE_CIRCULAR_BACKWARD_BEGIN(&workspace->layouts, iter_layout, start)
+ {
+ if (!callback(iter_layout, arg)) {
+ return iter_layout;
+ }
+ }
+ BLI_LISTBASE_CIRCULAR_BACKWARD_END(&workspace->layouts, iter_layout, start);
+ }
+ else {
+ BLI_LISTBASE_CIRCULAR_FORWARD_BEGIN(&workspace->layouts, iter_layout, start)
+ {
+ if (!callback(iter_layout, arg)) {
+ return iter_layout;
+ }
+ }
+ BLI_LISTBASE_CIRCULAR_FORWARD_END(&workspace->layouts, iter_layout, start)
+ }
+
+ return NULL;
+}
+
+
+/* -------------------------------------------------------------------- */
+/* Getters/Setters */
+
+WorkSpace *BKE_workspace_active_get(WorkSpaceInstanceHook *hook)
+{
+ return hook->active;
+}
+void BKE_workspace_active_set(WorkSpaceInstanceHook *hook, WorkSpace *workspace)
+{
+ hook->active = workspace;
+ if (workspace) {
+ WorkSpaceLayout *layout = workspace_relation_get_data_matching_parent(&workspace->hook_layout_relations, hook);
+ if (layout) {
+ hook->act_layout = layout;
+ }
+ }
+}
+
+WorkSpaceLayout *BKE_workspace_active_layout_get(const WorkSpaceInstanceHook *hook)
+{
+ return hook->act_layout;
+}
+void BKE_workspace_active_layout_set(WorkSpaceInstanceHook *hook, WorkSpaceLayout *layout)
+{
+ hook->act_layout = layout;
+}
+
+bScreen *BKE_workspace_active_screen_get(const WorkSpaceInstanceHook *hook)
+{
+ return hook->act_layout->screen;
+}
+void BKE_workspace_active_screen_set(WorkSpaceInstanceHook *hook, WorkSpace *workspace, bScreen *screen)
+{
+ /* we need to find the WorkspaceLayout that wraps this screen */
+ WorkSpaceLayout *layout = BKE_workspace_layout_find(hook->active, screen);
+ BKE_workspace_hook_layout_for_workspace_set(hook, workspace, layout);
+}
+
+#ifdef USE_WORKSPACE_MODE
+eObjectMode BKE_workspace_object_mode_get(const WorkSpace *workspace, const Scene *scene)
+{
+ Base *active_base = BKE_workspace_active_base_get(workspace, scene);
+ return active_base ? active_base->object->mode : OB_MODE_OBJECT;
+}
+void BKE_workspace_object_mode_set(WorkSpace *workspace, Scene *scene, const eObjectMode mode)
+{
+ Base *active_base = BKE_workspace_active_base_get(workspace, scene);
+ if (active_base) {
+ active_base->object->mode = mode;
+ }
+}
+#endif
+
+Base *BKE_workspace_active_base_get(const WorkSpace *workspace, const Scene *scene)
+{
+ ViewLayer *view_layer = BKE_workspace_view_layer_get(workspace, scene);
+ return view_layer->basact;
+}
+
+ListBase *BKE_workspace_transform_orientations_get(WorkSpace *workspace)
+{
+ return &workspace->transform_orientations;
+}
+
+ViewLayer *BKE_workspace_view_layer_get(const WorkSpace *workspace, const Scene *scene)
+{
+ return workspace_relation_get_data_matching_parent(&workspace->scene_viewlayer_relations, scene);
+}
+void BKE_workspace_view_layer_set(WorkSpace *workspace, ViewLayer *layer, Scene *scene)
+{
+ workspace_relation_ensure_updated(&workspace->scene_viewlayer_relations, scene, layer);
+}
+
+ListBase *BKE_workspace_layouts_get(WorkSpace *workspace)
+{
+ return &workspace->layouts;
+}
+
+
+const char *BKE_workspace_layout_name_get(const WorkSpaceLayout *layout)
+{
+ return layout->name;
+}
+void BKE_workspace_layout_name_set(WorkSpace *workspace, WorkSpaceLayout *layout, const char *new_name)
+{
+ workspace_layout_name_set(workspace, layout, new_name);
+}
+
+bScreen *BKE_workspace_layout_screen_get(const WorkSpaceLayout *layout)
+{
+ return layout->screen;
+}
+void BKE_workspace_layout_screen_set(WorkSpaceLayout *layout, bScreen *screen)
+{
+ layout->screen = screen;
+}
+
+WorkSpaceLayout *BKE_workspace_hook_layout_for_workspace_get(
+ const WorkSpaceInstanceHook *hook, const WorkSpace *workspace)
+{
+ return workspace_relation_get_data_matching_parent(&workspace->hook_layout_relations, hook);
+}
+void BKE_workspace_hook_layout_for_workspace_set(
+ WorkSpaceInstanceHook *hook, WorkSpace *workspace, WorkSpaceLayout *layout)
+{
+ hook->act_layout = layout;
+ workspace_relation_ensure_updated(&workspace->hook_layout_relations, hook, layout);
+}
+
+/**
+ * Get the render engine of a workspace, to be used in the viewport.
+ */
+ViewRender *BKE_workspace_view_render_get(WorkSpace *workspace)
+{
+ return &workspace->view_render;
+}
+
+/* Flags */
+bool BKE_workspace_use_scene_settings_get(const WorkSpace *workspace)
+{
+ return (workspace->flags & WORKSPACE_USE_SCENE_SETTINGS) != 0;
+}
+
+void BKE_workspace_use_scene_settings_set(WorkSpace *workspace, bool value)
+{
+ if (value) {
+ workspace->flags |= WORKSPACE_USE_SCENE_SETTINGS;
+ }
+ else {
+ workspace->flags &= ~WORKSPACE_USE_SCENE_SETTINGS;
+ }
+}
+
+/* Update / evaluate */
+
+void BKE_workspace_update_tagged(struct EvaluationContext *eval_ctx,
+ Main *bmain,
+ WorkSpace *workspace,
+ Scene *scene)
+{
+ ViewLayer *view_layer = BKE_workspace_view_layer_get(workspace, scene);
+ struct Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene,
+ view_layer,
+ true);
+ BKE_scene_graph_update_tagged(eval_ctx, depsgraph, bmain, scene, view_layer);
+}
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index 10fcfaa444f..5da8dc563e2 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -193,3 +193,14 @@ void BKE_world_make_local(Main *bmain, World *wrld, const bool lib_local)
{
BKE_id_make_local_generic(bmain, &wrld->id, true, lib_local);
}
+
+void BKE_world_eval(const struct EvaluationContext *UNUSED(eval_ctx), World *world)
+{
+ if (G.debug & G_DEBUG_DEPSGRAPH) {
+ printf("%s on %s (%p)\n", __func__, world->id.name, world);
+ }
+ if (!BLI_listbase_is_empty(&world->gpumaterial)) {
+ world->update_flag = 1;
+ GPU_material_uniform_buffer_tag_dirty(&world->gpumaterial);
+ }
+}
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index 5415fbb8ae1..f745a840cea 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -45,8 +45,8 @@
#include "BLI_blenlib.h"
#ifdef WITH_AUDASPACE
-# include AUD_DEVICE_H
-# include AUD_SPECIAL_H
+# include <AUD_Device.h>
+# include <AUD_Special.h>
#endif
#include "BLI_utildefines.h"