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/intern')
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.c23
-rw-r--r--source/blender/blenkernel/intern/addon.c47
-rw-r--r--source/blender/blenkernel/intern/anim.c8
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c47
-rw-r--r--source/blender/blenkernel/intern/armature.c1
-rw-r--r--source/blender/blenkernel/intern/armature_update.c114
-rw-r--r--source/blender/blenkernel/intern/blender.c13
-rw-r--r--source/blender/blenkernel/intern/blender_undo.c315
-rw-r--r--source/blender/blenkernel/intern/boids.c2
-rw-r--r--source/blender/blenkernel/intern/bpath.c4
-rw-r--r--source/blender/blenkernel/intern/brush.c4
-rw-r--r--source/blender/blenkernel/intern/bullet.c2
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c12
-rw-r--r--source/blender/blenkernel/intern/cachefile.c2
-rw-r--r--source/blender/blenkernel/intern/camera.c5
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c4
-rw-r--r--source/blender/blenkernel/intern/cloth.c6
-rw-r--r--source/blender/blenkernel/intern/collection.c238
-rw-r--r--source/blender/blenkernel/intern/collision.c22
-rw-r--r--source/blender/blenkernel/intern/colorband.c2
-rw-r--r--source/blender/blenkernel/intern/constraint.c7
-rw-r--r--source/blender/blenkernel/intern/context.c24
-rw-r--r--source/blender/blenkernel/intern/curve.c4
-rw-r--r--source/blender/blenkernel/intern/curve_decimate.c2
-rw-r--r--source/blender/blenkernel/intern/displist.c5
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c16
-rw-r--r--source/blender/blenkernel/intern/editderivedmesh.c2
-rw-r--r--source/blender/blenkernel/intern/editlattice.c147
-rw-r--r--source/blender/blenkernel/intern/effect.c5
-rw-r--r--source/blender/blenkernel/intern/fcurve.c10
-rw-r--r--source/blender/blenkernel/intern/fluidsim.c5
-rw-r--r--source/blender/blenkernel/intern/font.c9
-rw-r--r--source/blender/blenkernel/intern/group.c42
-rw-r--r--source/blender/blenkernel/intern/icons.c27
-rw-r--r--source/blender/blenkernel/intern/idprop.c5
-rw-r--r--source/blender/blenkernel/intern/image.c214
-rw-r--r--source/blender/blenkernel/intern/ipo.c2
-rw-r--r--source/blender/blenkernel/intern/lamp.c1
-rw-r--r--source/blender/blenkernel/intern/lattice.c1
-rw-r--r--source/blender/blenkernel/intern/layer.c354
-rw-r--r--source/blender/blenkernel/intern/library.c5
-rw-r--r--source/blender/blenkernel/intern/library_query.c15
-rw-r--r--source/blender/blenkernel/intern/library_remap.c33
-rw-r--r--source/blender/blenkernel/intern/linestyle.c1
-rw-r--r--source/blender/blenkernel/intern/mask.c2
-rw-r--r--source/blender/blenkernel/intern/mask_evaluate.c8
-rw-r--r--source/blender/blenkernel/intern/material.c19
-rw-r--r--source/blender/blenkernel/intern/mball.c6
-rw-r--r--source/blender/blenkernel/intern/mesh.c32
-rw-r--r--source/blender/blenkernel/intern/mesh_evaluate.c323
-rw-r--r--source/blender/blenkernel/intern/mesh_remap.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c20
-rw-r--r--source/blender/blenkernel/intern/modifier.c30
-rw-r--r--source/blender/blenkernel/intern/modifiers_bmesh.c20
-rw-r--r--source/blender/blenkernel/intern/movieclip.c43
-rw-r--r--source/blender/blenkernel/intern/nla.c85
-rw-r--r--source/blender/blenkernel/intern/node.c11
-rw-r--r--source/blender/blenkernel/intern/object.c53
-rw-r--r--source/blender/blenkernel/intern/object_deform.c70
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c23
-rw-r--r--source/blender/blenkernel/intern/object_update.c36
-rw-r--r--source/blender/blenkernel/intern/ocean.c8
-rw-r--r--source/blender/blenkernel/intern/outliner_treehash.c4
-rw-r--r--source/blender/blenkernel/intern/packedFile.c11
-rw-r--r--source/blender/blenkernel/intern/paint.c47
-rw-r--r--source/blender/blenkernel/intern/particle.c327
-rw-r--r--source/blender/blenkernel/intern/particle_child.c330
-rw-r--r--source/blender/blenkernel/intern/particle_distribute.c291
-rw-r--r--source/blender/blenkernel/intern/particle_system.c96
-rw-r--r--source/blender/blenkernel/intern/pbvh.c6
-rw-r--r--source/blender/blenkernel/intern/pbvh_bmesh.c36
-rw-r--r--source/blender/blenkernel/intern/pointcache.c107
-rw-r--r--source/blender/blenkernel/intern/rigidbody.c122
-rw-r--r--source/blender/blenkernel/intern/scene.c250
-rw-r--r--source/blender/blenkernel/intern/screen.c27
-rw-r--r--source/blender/blenkernel/intern/seqeffects.c1
-rw-r--r--source/blender/blenkernel/intern/sequencer.c75
-rw-r--r--source/blender/blenkernel/intern/smoke.c13
-rw-r--r--source/blender/blenkernel/intern/softbody.c12
-rw-r--r--source/blender/blenkernel/intern/speaker.c1
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c10
-rw-r--r--source/blender/blenkernel/intern/text.c660
-rw-r--r--source/blender/blenkernel/intern/texture.c12
-rw-r--r--source/blender/blenkernel/intern/tracking_region_tracker.c2
-rw-r--r--source/blender/blenkernel/intern/tracking_util.c4
-rw-r--r--source/blender/blenkernel/intern/undo_system.c846
-rw-r--r--source/blender/blenkernel/intern/workspace.c48
-rw-r--r--source/blender/blenkernel/intern/world.c3
-rw-r--r--source/blender/blenkernel/intern/writeffmpeg.c59
89 files changed, 3720 insertions, 2278 deletions
diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c
index cfeca50a751..916e11dbd46 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.c
+++ b/source/blender/blenkernel/intern/DerivedMesh.c
@@ -350,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;
@@ -410,7 +410,6 @@ int DM_release(DerivedMesh *dm)
if (dm->needsFree) {
bvhcache_free(&dm->bvhCache);
GPU_drawobject_free(dm);
-
CustomData_free(&dm->vertData, dm->numVertData);
CustomData_free(&dm->edgeData, dm->numEdgeData);
CustomData_free(&dm->faceData, dm->numTessFaceData);
@@ -1660,7 +1659,7 @@ static void shapekey_layers_to_keyblocks(DerivedMesh *dm, Mesh *me, int actshape
cos = CustomData_get_layer_n(&dm->vertData, CD_SHAPEKEY, i);
kb->totelem = dm->numVertData;
- kb->data = kbcos = MEM_malloc_arrayN(kb->totelem, sizeof(float), "kbcos DerivedMesh.c");
+ kb->data = kbcos = MEM_malloc_arrayN(kb->totelem, 3 * sizeof(float), "kbcos DerivedMesh.c");
if (kb->uid == actshape_uid) {
MVert *mvert = dm->getVertArray(dm);
@@ -3483,17 +3482,25 @@ void DM_draw_attrib_vertex_uniforms(const DMVertexAttribs *attribs)
{
int i;
if (attribs->totorco) {
- glUniform1i(attribs->orco.gl_info_index, 0);
+ if (attribs->orco.gl_info_index != -1) {
+ glUniform1i(attribs->orco.gl_info_index, 0);
+ }
}
for (i = 0; i < attribs->tottface; i++) {
- glUniform1i(attribs->tface[i].gl_info_index, 0);
+ if (attribs->tface[i].gl_info_index != -1) {
+ glUniform1i(attribs->tface[i].gl_info_index, 0);
+ }
}
for (i = 0; i < attribs->totmcol; i++) {
- glUniform1i(attribs->mcol[i].gl_info_index, GPU_ATTR_INFO_SRGB);
+ if (attribs->mcol[i].gl_info_index != -1) {
+ glUniform1i(attribs->mcol[i].gl_info_index, GPU_ATTR_INFO_SRGB);
+ }
}
for (i = 0; i < attribs->tottang; i++) {
- glUniform1i(attribs->tang[i].gl_info_index, 0);
+ if (attribs->tang[i].gl_info_index != -1) {
+ glUniform1i(attribs->tang[i].gl_info_index, 0);
+ }
}
}
@@ -3719,7 +3726,7 @@ void DM_init_origspace(DerivedMesh *dm)
BKE_mesh_calc_poly_normal(mp, l, mv, p_nor);
axis_dominant_v3_to_m3(mat, p_nor);
- BLI_array_empty(vcos_2d);
+ BLI_array_clear(vcos_2d);
BLI_array_reserve(vcos_2d, mp->totloop);
for (j = 0; j < mp->totloop; j++, l++) {
mul_v3_m3v3(co, mat, mv[l->v].co);
diff --git a/source/blender/blenkernel/intern/addon.c b/source/blender/blenkernel/intern/addon.c
index 0ef12397fe7..689e0fb5ee6 100644
--- a/source/blender/blenkernel/intern/addon.c
+++ b/source/blender/blenkernel/intern/addon.c
@@ -27,13 +27,58 @@
#include <stddef.h>
#include <stdlib.h>
+#include "RNA_types.h"
+
#include "BLI_utildefines.h"
#include "BLI_ghash.h"
+#include "BLI_string.h"
+#include "BLI_listbase.h"
#include "BKE_addon.h" /* own include */
+#include "BKE_idprop.h"
+
+#include "DNA_listBase.h"
+#include "DNA_userdef_types.h"
+
#include "MEM_guardedalloc.h"
+/* -------------------------------------------------------------------- */
+/** \name Add-on New/Free
+ * \{ */
+
+bAddon *BKE_addon_new(void)
+{
+ bAddon *addon = MEM_callocN(sizeof(bAddon), "bAddon");
+ return addon;
+}
+
+bAddon *BKE_addon_ensure(ListBase *addon_list, const char *module)
+{
+ bAddon *addon = BLI_findstring(addon_list, module, offsetof(bAddon, module));
+ if (addon == NULL) {
+ addon = BKE_addon_new();
+ BLI_strncpy(addon->module, module, sizeof(addon->module));
+ BLI_addtail(addon_list, addon);
+ }
+ return addon;
+}
+
+void BKE_addon_free(bAddon *addon)
+{
+ if (addon->prop) {
+ IDP_FreeProperty(addon->prop);
+ MEM_freeN(addon->prop);
+ }
+ MEM_freeN(addon);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Add-on Preference API
+ * \{ */
+
static GHash *global_addonpreftype_hash = NULL;
@@ -81,3 +126,5 @@ void BKE_addon_pref_type_free(void)
BLI_ghash_free(global_addonpreftype_hash, NULL, MEM_freeN);
global_addonpreftype_hash = NULL;
}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c
index 62df97c6afa..0b964145c7f 100644
--- a/source/blender/blenkernel/intern/anim.c
+++ b/source/blender/blenkernel/intern/anim.c
@@ -278,8 +278,6 @@ void animviz_get_object_motionpaths(Object *ob, ListBase *targets)
/* update scene for current frame */
static void motionpaths_calc_update_scene(Main *bmain,
- Scene *scene,
- ViewLayer *view_layer,
struct Depsgraph *depsgraph)
{
/* Do all updates
@@ -292,7 +290,7 @@ static void motionpaths_calc_update_scene(Main *bmain,
*
* TODO(sergey): Use evaluation context dedicated to motion paths.
*/
- BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
}
/* ........ */
@@ -369,7 +367,7 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
/* calculate path over requested range */
for (CFRA = sfra; CFRA <= efra; CFRA++) {
/* update relevant data for new frame */
- motionpaths_calc_update_scene(bmain, scene, eval_ctx->view_layer, eval_ctx->depsgraph);
+ motionpaths_calc_update_scene(bmain, eval_ctx->depsgraph);
/* perform baking for targets */
motionpaths_calc_bake_targets(scene, targets);
@@ -377,7 +375,7 @@ static void motionpaths_calc_bake_targets(Scene *scene, ListBase *targets)
/* reset original environment */
CFRA = cfra;
- motionpaths_calc_update_scene(bmain, scene, eval_ctx->view_layer, eval_ctx->depsgraph);
+ motionpaths_calc_update_scene(bmain, 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 58b476d3da5..ecdb180d2ed 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -77,6 +77,8 @@
#include "atomic_ops.h"
+#include "DEG_depsgraph.h"
+
/* ***************************************** */
/* AnimData API */
@@ -245,7 +247,7 @@ void BKE_animdata_free(ID *id, const bool do_id_user)
}
/* free nla data */
- free_nladata(&adt->nla_tracks);
+ BKE_nla_tracks_free(&adt->nla_tracks);
/* free drivers - stored as a list of F-Curves */
free_fcurves(&adt->drivers);
@@ -284,7 +286,7 @@ AnimData *BKE_animdata_copy(Main *bmain, AnimData *adt, const bool do_action)
}
/* duplicate NLA data */
- copy_nladata(&dadt->nla_tracks, &adt->nla_tracks);
+ BKE_nla_tracks_copy(&dadt->nla_tracks, &adt->nla_tracks);
/* duplicate drivers (F-Curves) */
copy_fcurves(&dadt->drivers, &adt->drivers);
@@ -366,7 +368,7 @@ void BKE_animdata_merge_copy(ID *dst_id, ID *src_id, eAnimData_MergeCopy_Modes a
if (src->nla_tracks.first) {
ListBase tracks = {NULL, NULL};
- copy_nladata(&tracks, &src->nla_tracks);
+ BKE_nla_tracks_copy(&tracks, &src->nla_tracks);
BLI_movelisttolist(&dst->nla_tracks, &tracks);
}
@@ -820,7 +822,7 @@ char *BKE_animsys_fix_rna_path_rename(ID *owner_id, char *old_path, const char *
/* if no action, no need to proceed */
if (ELEM(NULL, owner_id, old_path)) {
- printf("early abort\n");
+ if (G.debug & G_DEBUG) printf("%s: early abort\n", __func__);
return old_path;
}
@@ -843,9 +845,9 @@ char *BKE_animsys_fix_rna_path_rename(ID *owner_id, char *old_path, const char *
}
/* fix given path */
- printf("%s | %s | oldpath = %p ", oldN, newN, old_path);
+ if (G.debug & G_DEBUG) printf("%s | %s | oldpath = %p ", oldN, newN, old_path);
result = rna_path_rename_fix(owner_id, prefix, oldN, newN, old_path, verify_paths);
- printf("result = %p\n", result);
+ if (G.debug & G_DEBUG) printf("path rename result = %p\n", result);
/* free the temp names */
MEM_freeN(oldN);
@@ -2879,18 +2881,34 @@ void BKE_animsys_evaluate_all_animation(Main *main, Scene *scene, float ctime)
/* ************** */
/* Evaluation API */
-#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
-
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,
* which should get handled as part of the dependency graph instead...
*/
- DEBUG_PRINT("%s on %s, time=%f\n\n", __func__, id->name, (double)eval_ctx->ctime);
+ DEG_debug_print_eval_time(__func__, id->name, id, eval_ctx->ctime);
BKE_animsys_evaluate_animdata(scene, id, adt, eval_ctx->ctime, ADT_RECALC_ANIM);
}
+/* TODO(sergey): This is slow lookup of driver from CoW datablock.
+ * Keep this for until we've got something smarter for depsgraph
+ * building.\
+ */
+static FCurve *find_driver_from_evaluated_id(ID *id, FCurve *fcu)
+{
+ /* We've got non-CoW datablock, can use f-curve as-is. */
+ if (id->orig_id == NULL) {
+ return fcu;
+ }
+ /*const*/ ID *id_orig = id->orig_id;
+ const AnimData *adt_orig = BKE_animdata_from_id(id_orig);
+ const AnimData *adt_cow = BKE_animdata_from_id(id);
+ const int fcu_index = BLI_findindex(&adt_orig->drivers, fcu);
+ BLI_assert(fcu_index != -1);
+ return BLI_findlink(&adt_cow->drivers, fcu_index);
+}
+
void BKE_animsys_eval_driver(const EvaluationContext *eval_ctx,
ID *id,
FCurve *fcu)
@@ -2900,11 +2918,10 @@ void BKE_animsys_eval_driver(const EvaluationContext *eval_ctx,
PointerRNA id_ptr;
bool ok = false;
- DEBUG_PRINT("%s on %s (%s[%d])\n",
- __func__,
- id->name,
- fcu->rna_path,
- fcu->array_index);
+ fcu = find_driver_from_evaluated_id(id, fcu);
+
+ DEG_debug_print_eval_subdata_index(
+ __func__, id->name, id, "fcu", fcu->rna_path, fcu, fcu->array_index);
RNA_id_pointer_create(id, &id_ptr);
@@ -2937,5 +2954,3 @@ void BKE_animsys_eval_driver(const EvaluationContext *eval_ctx,
}
}
}
-
-#undef DEBUG_PRINT
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 953fef067b4..0a8c97ff175 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -63,7 +63,6 @@
#include "BKE_DerivedMesh.h"
#include "BKE_deform.h"
#include "BKE_displist.h"
-#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
index 1b8bf3feb10..29baaff32ba 100644
--- a/source/blender/blenkernel/intern/armature_update.c
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -47,10 +47,9 @@
#include "BIK_api.h"
-#include "BKE_global.h"
#include "BKE_main.h"
-#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
+#include "DEG_depsgraph.h"
/* ********************** SPLINE IK SOLVER ******************* */
@@ -559,14 +558,23 @@ void BKE_splineik_execute_tree(
/* *************** Depsgraph evaluation callbacks ************ */
+BLI_INLINE bPoseChannel *pose_pchan_get_indexed(Object *ob, int pchan_index)
+{
+ bPose *pose = ob->pose;
+ BLI_assert(pose != NULL);
+ BLI_assert(pchan_index >= 0);
+ BLI_assert(pchan_index < MEM_allocN_len(pose->chan_array) / sizeof(bPoseChannel *));
+ return pose->chan_array[pchan_index];
+}
+
void BKE_pose_eval_init(const struct EvaluationContext *UNUSED(eval_ctx),
Scene *UNUSED(scene),
- Object *ob,
- bPose *pose)
+ Object *ob)
{
- bPoseChannel *pchan;
+ bPose *pose = ob->pose;
+ BLI_assert(pose != NULL);
- DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+ DEG_debug_print_eval(__func__, ob->id.name, ob);
BLI_assert(ob->type == OB_ARMATURE);
@@ -577,27 +585,34 @@ void BKE_pose_eval_init(const struct EvaluationContext *UNUSED(eval_ctx),
/* imat is needed for solvers. */
invert_m4_m4(ob->imat, ob->obmat);
- /* 1. clear flags */
- for (pchan = pose->chanbase.first; pchan != NULL; pchan = pchan->next) {
+ const int num_channels = BLI_listbase_count(&pose->chanbase);
+ pose->chan_array = MEM_malloc_arrayN(
+ num_channels, sizeof(bPoseChannel *), "pose->chan_array");
+
+ /* clear flags */
+ int pchan_index = 0;
+ for (bPoseChannel *pchan = pose->chanbase.first; pchan != NULL; pchan = pchan->next) {
pchan->flag &= ~(POSE_DONE | POSE_CHAIN | POSE_IKTREE | POSE_IKSPLINE);
+ pose->chan_array[pchan_index++] = pchan;
}
}
void BKE_pose_eval_init_ik(const struct EvaluationContext *eval_ctx,
Scene *scene,
- Object *ob,
- bPose *UNUSED(pose))
+ Object *ob)
{
- float ctime = BKE_scene_frame_get(scene); /* not accurate... */
-
- DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
-
- /* 2a. construct the IK tree (standard IK) */
+ DEG_debug_print_eval(__func__, ob->id.name, ob);
+ BLI_assert(ob->type == OB_ARMATURE);
+ const float ctime = BKE_scene_frame_get(scene); /* not accurate... */
+ bArmature *arm = (bArmature *)ob->data;
+ if (arm->flag & ARM_RESTPOS) {
+ return;
+ }
+ /* construct the IK tree (standard IK) */
BIK_initialize_tree(eval_ctx, scene, ob, ctime);
-
- /* 2b. construct the Spline IK trees
+ /* construct the Spline IK trees
* - this is not integrated as an IK plugin, since it should be able
- * to function in conjunction with standard IK
+ * to function in conjunction with standard IK
*/
BKE_pose_splineik_init_tree(scene, ob, ctime);
}
@@ -605,11 +620,13 @@ void BKE_pose_eval_init_ik(const struct EvaluationContext *eval_ctx,
void BKE_pose_eval_bone(const struct EvaluationContext *eval_ctx,
Scene *scene,
Object *ob,
- bPoseChannel *pchan)
+ int pchan_index)
{
- bArmature *arm = (bArmature *)ob->data;
- DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, pchan->name);
+ bPoseChannel *pchan = pose_pchan_get_indexed(ob, pchan_index);
+ DEG_debug_print_eval_subdata(
+ __func__, ob->id.name, ob, "pchan", pchan->name, pchan);
BLI_assert(ob->type == OB_ARMATURE);
+ bArmature *arm = (bArmature *)ob->data;
if (arm->edbo || (arm->flag & ARM_RESTPOS)) {
Bone *bone = pchan->bone;
if (bone) {
@@ -640,9 +657,11 @@ void BKE_pose_eval_bone(const struct EvaluationContext *eval_ctx,
void BKE_pose_constraints_evaluate(const struct EvaluationContext *eval_ctx,
Scene *scene,
Object *ob,
- bPoseChannel *pchan)
+ int pchan_index)
{
- DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, pchan->name);
+ bPoseChannel *pchan = pose_pchan_get_indexed(ob, pchan_index);
+ DEG_debug_print_eval_subdata(
+ __func__, ob->id.name, ob, "pchan", pchan->name, pchan);
bArmature *arm = (bArmature *)ob->data;
if (arm->flag & ARM_RESTPOS) {
return;
@@ -659,10 +678,12 @@ void BKE_pose_constraints_evaluate(const struct EvaluationContext *eval_ctx,
}
void BKE_pose_bone_done(const struct EvaluationContext *UNUSED(eval_ctx),
- bPoseChannel *pchan)
+ struct Object *ob,
+ int pchan_index)
{
+ bPoseChannel *pchan = pose_pchan_get_indexed(ob, pchan_index);
float imat[4][4];
- DEBUG_PRINT("%s on pchan %s\n", __func__, pchan->name);
+ DEG_debug_print_eval(__func__, pchan->name, pchan);
if (pchan->bone) {
invert_m4_m4(imat, pchan->bone->arm_mat);
mul_m4_m4m4(pchan->chan_mat, pchan->pose_mat, imat);
@@ -672,40 +693,61 @@ void BKE_pose_bone_done(const struct EvaluationContext *UNUSED(eval_ctx),
void BKE_pose_iktree_evaluate(const struct EvaluationContext *eval_ctx,
Scene *scene,
Object *ob,
- bPoseChannel *rootchan)
+ int rootchan_index)
{
- float ctime = BKE_scene_frame_get(scene); /* not accurate... */
- DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, rootchan->name);
+ bPoseChannel *rootchan = pose_pchan_get_indexed(ob, rootchan_index);
+ DEG_debug_print_eval_subdata(
+ __func__, ob->id.name, ob, "rootchan", rootchan->name, rootchan);
+ BLI_assert(ob->type == OB_ARMATURE);
+ const float ctime = BKE_scene_frame_get(scene); /* not accurate... */
+ bArmature *arm = (bArmature *)ob->data;
+ if (arm->flag & ARM_RESTPOS) {
+ return;
+ }
BIK_execute_tree(eval_ctx, scene, ob, rootchan, ctime);
}
void BKE_pose_splineik_evaluate(const struct EvaluationContext *eval_ctx,
Scene *scene,
Object *ob,
- bPoseChannel *rootchan)
+ int rootchan_index)
+
{
- float ctime = BKE_scene_frame_get(scene); /* not accurate... */
- DEBUG_PRINT("%s on %s pchan %s\n", __func__, ob->id.name, rootchan->name);
+ bPoseChannel *rootchan = pose_pchan_get_indexed(ob, rootchan_index);
+ DEG_debug_print_eval_subdata(
+ __func__, ob->id.name, ob, "rootchan", rootchan->name, rootchan);
+ BLI_assert(ob->type == OB_ARMATURE);
+ const float ctime = BKE_scene_frame_get(scene); /* not accurate... */
+ bArmature *arm = (bArmature *)ob->data;
+ if (arm->flag & ARM_RESTPOS) {
+ return;
+ }
BKE_splineik_execute_tree(eval_ctx, scene, ob, rootchan, ctime);
}
void BKE_pose_eval_flush(const struct EvaluationContext *UNUSED(eval_ctx),
Scene *scene,
- Object *ob,
- bPose *UNUSED(pose))
+ Object *ob)
{
+ bPose *pose = ob->pose;
+ BLI_assert(pose != NULL);
+
float ctime = BKE_scene_frame_get(scene); /* not accurate... */
- DEBUG_PRINT("%s on %s\n", __func__, ob->id.name);
+ DEG_debug_print_eval(__func__, ob->id.name, ob);
BLI_assert(ob->type == OB_ARMATURE);
- /* 6. release the IK tree */
+ /* release the IK tree */
BIK_release_tree(scene, ob, ctime);
+
+ BLI_assert(pose->chan_array != NULL);
+ MEM_freeN(pose->chan_array);
+ pose->chan_array = NULL;
}
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);
+ DEG_debug_print_eval(__func__, ob->id.name, ob);
if (BKE_pose_copy_result(ob->pose, ob->proxy_from->pose) == false) {
printf("Proxy copy error, lib Object: %s proxy Object: %s\n",
ob->id.name + 2, ob->proxy_from->id.name + 2);
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 182b88c1c57..236b965ec34 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -45,6 +45,7 @@
#include "IMB_imbuf.h"
#include "IMB_moviecache.h"
+#include "BKE_addon.h"
#include "BKE_blender.h" /* own include */
#include "BKE_blender_version.h" /* own include */
#include "BKE_blendfile.h"
@@ -84,6 +85,10 @@ void BKE_blender_free(void)
BKE_main_free(G.main);
G.main = NULL;
+ if (G.log.file != NULL) {
+ fclose(G.log.file);
+ }
+
BKE_spacetypes_free(); /* after free main, it uses space callbacks */
IMB_exit();
@@ -133,6 +138,8 @@ void BKE_blender_globals_init(void)
#else
G.f &= ~G_SCRIPT_AUTOEXEC;
#endif
+
+ G.log.level = 1;
}
void BKE_blender_globals_clear(void)
@@ -202,11 +209,7 @@ static void userdef_free_addons(UserDef *userdef)
{
for (bAddon *addon = userdef->addons.first, *addon_next; addon; addon = addon_next) {
addon_next = addon->next;
- if (addon->prop) {
- IDP_FreeProperty(addon->prop);
- MEM_freeN(addon->prop);
- }
- MEM_freeN(addon);
+ BKE_addon_free(addon);
}
BLI_listbase_clear(&userdef->addons);
}
diff --git a/source/blender/blenkernel/intern/blender_undo.c b/source/blender/blenkernel/intern/blender_undo.c
index b8f46756445..98482bcc8b1 100644
--- a/source/blender/blenkernel/intern/blender_undo.c
+++ b/source/blender/blenkernel/intern/blender_undo.c
@@ -42,27 +42,18 @@
#include "DNA_scene_types.h"
-#include "BLI_fileops.h"
-#include "BLI_listbase.h"
#include "BLI_path_util.h"
#include "BLI_string.h"
#include "BLI_utildefines.h"
-#include "IMB_imbuf.h"
-#include "IMB_moviecache.h"
-
#include "BKE_blender_undo.h" /* own include */
#include "BKE_blendfile.h"
#include "BKE_appdir.h"
-#include "BKE_brush.h"
#include "BKE_context.h"
#include "BKE_global.h"
-#include "BKE_image.h"
#include "BKE_main.h"
-#include "RE_pipeline.h"
#include "BLO_undofile.h"
-#include "BLO_readfile.h"
#include "BLO_writefile.h"
#include "DEG_depsgraph.h"
@@ -74,44 +65,22 @@
#define UNDO_DISK 0
-typedef struct UndoElem {
- struct UndoElem *next, *prev;
- char str[FILE_MAX];
- char name[BKE_UNDO_STR_MAX];
- MemFile memfile;
- uintptr_t undosize;
-} UndoElem;
-
-static ListBase undobase = {NULL, NULL};
-static UndoElem *curundo = NULL;
-
-/**
- * Avoid bad-level call to #WM_jobs_kill_all_except()
- */
-static void (*undo_wm_job_kill_callback)(struct bContext *C) = NULL;
-
-void BKE_undo_callback_wm_kill_jobs_set(void (*callback)(struct bContext *C))
-{
- undo_wm_job_kill_callback = callback;
-}
-
-static int read_undosave(bContext *C, UndoElem *uel)
+bool BKE_memfile_undo_decode(MemFileUndoData *mfu, bContext *C)
{
char mainstr[sizeof(G.main->name)];
int success = 0, fileflags;
- /* This is needed so undoing/redoing doesn't crash with threaded previews going */
- undo_wm_job_kill_callback(C);
-
BLI_strncpy(mainstr, G.main->name, sizeof(mainstr)); /* temporal store */
fileflags = G.fileflags;
G.fileflags |= G_FILE_NO_UI;
- if (UNDO_DISK)
- success = (BKE_blendfile_read(C, uel->str, NULL, 0) != BKE_BLENDFILE_READ_FAIL);
- else
- success = BKE_blendfile_read_from_memfile(C, &uel->memfile, NULL, 0);
+ if (UNDO_DISK) {
+ success = (BKE_blendfile_read(C, mfu->filename, NULL, 0) != BKE_BLENDFILE_READ_FAIL);
+ }
+ else {
+ success = BKE_blendfile_read_from_memfile(C, &mfu->memfile, NULL, 0);
+ }
/* restore */
BLI_strncpy(G.main->name, mainstr, sizeof(G.main->name)); /* restore */
@@ -125,283 +94,43 @@ static int read_undosave(bContext *C, UndoElem *uel)
return success;
}
-/* name can be a dynamic string */
-void BKE_undo_write(bContext *C, const char *name)
+MemFileUndoData *BKE_memfile_undo_encode(Main *bmain, MemFileUndoData *mfu_prev)
{
- uintptr_t maxmem, totmem, memused;
- int nr /*, success */ /* UNUSED */;
- UndoElem *uel;
-
- if ((U.uiflag & USER_GLOBALUNDO) == 0) {
- return;
- }
-
- if (U.undosteps == 0) {
- return;
- }
-
- /* remove all undos after (also when curundo == NULL) */
- while (undobase.last != curundo) {
- uel = undobase.last;
- BLI_remlink(&undobase, uel);
- BLO_memfile_free(&uel->memfile);
- MEM_freeN(uel);
- }
-
- /* make new */
- curundo = uel = MEM_callocN(sizeof(UndoElem), "undo file");
- BLI_strncpy(uel->name, name, sizeof(uel->name));
- BLI_addtail(&undobase, uel);
-
- /* and limit amount to the maximum */
- nr = 0;
- uel = undobase.last;
- while (uel) {
- nr++;
- if (nr == U.undosteps) break;
- uel = uel->prev;
- }
- if (uel) {
- while (undobase.first != uel) {
- UndoElem *first = undobase.first;
- BLI_remlink(&undobase, first);
- /* the merge is because of compression */
- BLO_memfile_merge(&first->memfile, &first->next->memfile);
- MEM_freeN(first);
- }
- }
-
+ MemFileUndoData *mfu = MEM_callocN(sizeof(MemFileUndoData), __func__);
/* disk save version */
if (UNDO_DISK) {
static int counter = 0;
- char filepath[FILE_MAX];
+ char filename[FILE_MAX];
char numstr[32];
int fileflags = G.fileflags & ~(G_FILE_HISTORY); /* don't do file history on undo */
- /* calculate current filepath */
+ /* Calculate current filename. */
counter++;
counter = counter % U.undosteps;
BLI_snprintf(numstr, sizeof(numstr), "%d.blend", counter);
- BLI_make_file_string("/", filepath, BKE_tempdir_session(), numstr);
-
- /* success = */ /* UNUSED */ BLO_write_file(CTX_data_main(C), filepath, fileflags, NULL, NULL);
-
- BLI_strncpy(curundo->str, filepath, sizeof(curundo->str));
- }
- else {
- MemFile *prevfile = NULL;
-
- if (curundo->prev) prevfile = &(curundo->prev->memfile);
-
- memused = MEM_get_memory_in_use();
- /* success = */ /* UNUSED */ BLO_write_file_mem(CTX_data_main(C), prevfile, &curundo->memfile, G.fileflags);
- curundo->undosize = MEM_get_memory_in_use() - memused;
- }
-
- if (U.undomemory != 0) {
- /* limit to maximum memory (afterwards, we can't know in advance) */
- totmem = 0;
- maxmem = ((uintptr_t)U.undomemory) * 1024 * 1024;
-
- /* keep at least two (original + other) */
- uel = undobase.last;
- while (uel && uel->prev) {
- totmem += uel->undosize;
- if (totmem > maxmem) break;
- uel = uel->prev;
- }
-
- if (uel) {
- if (uel->prev && uel->prev->prev)
- uel = uel->prev;
+ BLI_make_file_string("/", filename, BKE_tempdir_session(), numstr);
- while (undobase.first != uel) {
- UndoElem *first = undobase.first;
- BLI_remlink(&undobase, first);
- /* the merge is because of compression */
- BLO_memfile_merge(&first->memfile, &first->next->memfile);
- MEM_freeN(first);
- }
- }
- }
-}
-
-/* 1 = an undo, -1 is a redo. we have to make sure 'curundo' remains at current situation */
-void BKE_undo_step(bContext *C, int step)
-{
+ /* success = */ /* UNUSED */ BLO_write_file(bmain, filename, fileflags, NULL, NULL);
- if (step == 0) {
- read_undosave(C, curundo);
- }
- else if (step == 1) {
- /* curundo should never be NULL, after restart or load file it should call undo_save */
- if (curundo == NULL || curundo->prev == NULL) {
- // XXX error("No undo available");
- }
- else {
- if (G.debug & G_DEBUG) printf("undo %s\n", curundo->name);
- curundo = curundo->prev;
- read_undosave(C, curundo);
- }
+ BLI_strncpy(mfu->filename, filename, sizeof(mfu->filename));
}
else {
- /* curundo has to remain current situation! */
-
- if (curundo == NULL || curundo->next == NULL) {
- // XXX error("No redo available");
- }
- else {
- read_undosave(C, curundo->next);
- curundo = curundo->next;
- if (G.debug & G_DEBUG) printf("redo %s\n", curundo->name);
- }
- }
-}
-
-void BKE_undo_reset(void)
-{
- UndoElem *uel;
-
- uel = undobase.first;
- while (uel) {
- BLO_memfile_free(&uel->memfile);
- uel = uel->next;
+ MemFile *prevfile = (mfu_prev) ? &(mfu_prev->memfile) : NULL;
+ /* success = */ /* UNUSED */ BLO_write_file_mem(bmain, prevfile, &mfu->memfile, G.fileflags);
+ mfu->undo_size = mfu->memfile.size;
}
- BLI_freelistN(&undobase);
- curundo = NULL;
-}
-
-/* based on index nr it does a restore */
-void BKE_undo_number(bContext *C, int nr)
-{
- curundo = BLI_findlink(&undobase, nr);
- BKE_undo_step(C, 0);
-}
-
-/* go back to the last occurance of name in stack */
-void BKE_undo_name(bContext *C, const char *name)
-{
- UndoElem *uel = BLI_rfindstring(&undobase, name, offsetof(UndoElem, name));
-
- if (uel && uel->prev) {
- curundo = uel->prev;
- BKE_undo_step(C, 0);
- }
-}
-
-/* name optional */
-bool BKE_undo_is_valid(const char *name)
-{
- if (name) {
- UndoElem *uel = BLI_rfindstring(&undobase, name, offsetof(UndoElem, name));
- return uel && uel->prev;
- }
+ bmain->is_memfile_undo_written = true;
- return undobase.last != undobase.first;
+ return mfu;
}
-/* get name of undo item, return null if no item with this index */
-/* if active pointer, set it to 1 if true */
-const char *BKE_undo_get_name(int nr, bool *r_active)
-{
- UndoElem *uel = BLI_findlink(&undobase, nr);
-
- if (r_active) *r_active = false;
-
- if (uel) {
- if (r_active && (uel == curundo)) {
- *r_active = true;
- }
- return uel->name;
- }
- return NULL;
-}
-
-/* return the name of the last item */
-const char *BKE_undo_get_name_last(void)
-{
- UndoElem *uel = undobase.last;
- return (uel ? uel->name : NULL);
-}
-
-/**
- * Saves .blend using undo buffer.
- *
- * \return success.
- */
-bool BKE_undo_save_file(const char *filename)
+void BKE_memfile_undo_free(MemFileUndoData *mfu)
{
- UndoElem *uel;
- MemFileChunk *chunk;
- int file, oflags;
-
- if ((U.uiflag & USER_GLOBALUNDO) == 0) {
- return false;
- }
-
- uel = curundo;
- if (uel == NULL) {
- fprintf(stderr, "No undo buffer to save recovery file\n");
- return false;
- }
-
- /* note: This is currently used for autosave and 'quit.blend', where _not_ following symlinks is OK,
- * however if this is ever executed explicitly by the user, we may want to allow writing to symlinks.
- */
-
- oflags = O_BINARY | O_WRONLY | O_CREAT | O_TRUNC;
-#ifdef O_NOFOLLOW
- /* use O_NOFOLLOW to avoid writing to a symlink - use 'O_EXCL' (CVE-2008-1103) */
- oflags |= O_NOFOLLOW;
-#else
- /* TODO(sergey): How to deal with symlinks on windows? */
-# ifndef _MSC_VER
-# warning "Symbolic links will be followed on undo save, possibly causing CVE-2008-1103"
-# endif
-#endif
- file = BLI_open(filename, oflags, 0666);
-
- if (file == -1) {
- fprintf(stderr, "Unable to save '%s': %s\n",
- filename, errno ? strerror(errno) : "Unknown error opening file");
- return false;
- }
-
- for (chunk = uel->memfile.chunks.first; chunk; chunk = chunk->next) {
- if (write(file, chunk->buf, chunk->size) != chunk->size) {
- break;
- }
- }
-
- close(file);
-
- if (chunk) {
- fprintf(stderr, "Unable to save '%s': %s\n",
- filename, errno ? strerror(errno) : "Unknown error writing file");
- return false;
- }
- return true;
-}
-
-/* sets curscene */
-Main *BKE_undo_get_main(Scene **r_scene)
-{
- Main *mainp = NULL;
- BlendFileData *bfd = BLO_read_from_memfile(G.main, G.main->name, &curundo->memfile, NULL, BLO_READ_SKIP_NONE);
-
- if (bfd) {
- mainp = bfd->main;
- if (r_scene) {
- *r_scene = bfd->curscene;
- }
-
- MEM_freeN(bfd);
- }
-
- return mainp;
+ BLO_memfile_free(&mfu->memfile);
+ MEM_freeN(mfu);
}
/** \} */
diff --git a/source/blender/blenkernel/intern/boids.c b/source/blender/blenkernel/intern/boids.c
index 8c78787c259..f440ce711ff 100644
--- a/source/blender/blenkernel/intern/boids.c
+++ b/source/blender/blenkernel/intern/boids.c
@@ -35,7 +35,7 @@
#include "MEM_guardedalloc.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_scene_types.h"
#include "BLI_rand.h"
diff --git a/source/blender/blenkernel/intern/bpath.c b/source/blender/blenkernel/intern/bpath.c
index 158c6c31432..e9a8de4469d 100644
--- a/source/blender/blenkernel/intern/bpath.c
+++ b/source/blender/blenkernel/intern/bpath.c
@@ -53,8 +53,8 @@
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_movieclip_types.h"
-#include "DNA_object_fluidsim.h"
-#include "DNA_object_force.h"
+#include "DNA_object_fluidsim_types.h"
+#include "DNA_object_force_types.h"
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
#include "DNA_sequence_types.h"
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 8d63c1cfb44..d82c1ca56fe 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -151,7 +151,7 @@ void BKE_brush_init(Brush *brush)
/**
* \note Resulting brush will have two users: one as a fake user, another is assumed to be used by the caller.
*/
-Brush *BKE_brush_add(Main *bmain, const char *name, short ob_mode)
+Brush *BKE_brush_add(Main *bmain, const char *name, const eObjectMode ob_mode)
{
Brush *brush;
@@ -164,7 +164,7 @@ Brush *BKE_brush_add(Main *bmain, const char *name, short ob_mode)
return brush;
}
-struct Brush *BKE_brush_first_search(struct Main *bmain, short ob_mode)
+struct Brush *BKE_brush_first_search(struct Main *bmain, const eObjectMode ob_mode)
{
Brush *brush;
diff --git a/source/blender/blenkernel/intern/bullet.c b/source/blender/blenkernel/intern/bullet.c
index 088031e16a7..c16c0f7af31 100644
--- a/source/blender/blenkernel/intern/bullet.c
+++ b/source/blender/blenkernel/intern/bullet.c
@@ -33,7 +33,7 @@
#include "MEM_guardedalloc.h"
/* types */
-#include "DNA_object_force.h" /* here is the softbody struct */
+#include "DNA_object_force_types.h" /* here is the softbody struct */
#include "BKE_bullet.h"
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index 775499304d4..cd2c7194237 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -411,7 +411,7 @@ static BVHTree *bvhtree_from_editmesh_verts_create_tree(
BMVert *eve = BM_vert_at_index(em->bm, i);
BLI_bvhtree_insert(tree, i, eve->co, 1);
}
- BLI_assert(BLI_bvhtree_get_size(tree) == verts_num_active);
+ BLI_assert(BLI_bvhtree_get_len(tree) == verts_num_active);
BLI_bvhtree_balance(tree);
}
@@ -440,7 +440,7 @@ static BVHTree *bvhtree_from_mesh_verts_create_tree(
}
BLI_bvhtree_insert(tree, i, vert[i].co, 1);
}
- BLI_assert(BLI_bvhtree_get_size(tree) == verts_num_active);
+ BLI_assert(BLI_bvhtree_get_len(tree) == verts_num_active);
BLI_bvhtree_balance(tree);
}
@@ -612,7 +612,7 @@ static BVHTree *bvhtree_from_editmesh_edges_create_tree(
BLI_bvhtree_insert(tree, i, co[0], 2);
}
- BLI_assert(BLI_bvhtree_get_size(tree) == edges_num_active);
+ BLI_assert(BLI_bvhtree_get_len(tree) == edges_num_active);
BLI_bvhtree_balance(tree);
}
@@ -829,7 +829,7 @@ static BVHTree *bvhtree_from_mesh_faces_create_tree(
BLI_bvhtree_insert(tree, i, co[0], face[i].v4 ? 4 : 3);
}
}
- BLI_assert(BLI_bvhtree_get_size(tree) == faces_num_active);
+ BLI_assert(BLI_bvhtree_get_len(tree) == faces_num_active);
BLI_bvhtree_balance(tree);
}
}
@@ -990,7 +990,7 @@ static BVHTree *bvhtree_from_editmesh_looptri_create_tree(
}
}
}
- BLI_assert(BLI_bvhtree_get_size(tree) == looptri_num_active);
+ BLI_assert(BLI_bvhtree_get_len(tree) == looptri_num_active);
BLI_bvhtree_balance(tree);
}
}
@@ -1032,7 +1032,7 @@ static BVHTree *bvhtree_from_mesh_looptri_create_tree(
BLI_bvhtree_insert(tree, i, co[0], 3);
}
}
- BLI_assert(BLI_bvhtree_get_size(tree) == looptri_num_active);
+ BLI_assert(BLI_bvhtree_get_len(tree) == looptri_num_active);
BLI_bvhtree_balance(tree);
}
}
diff --git a/source/blender/blenkernel/intern/cachefile.c b/source/blender/blenkernel/intern/cachefile.c
index f8215668034..8f156e8f267 100644
--- a/source/blender/blenkernel/intern/cachefile.c
+++ b/source/blender/blenkernel/intern/cachefile.c
@@ -42,7 +42,6 @@
#include "BKE_animsys.h"
#include "BKE_cachefile.h"
-#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
@@ -181,7 +180,6 @@ void BKE_cachefile_update_frame(Main *bmain, Scene *scene, const float ctime, co
ABC_free_handle(cache_file->handle);
cache_file->handle = ABC_create_handle(filename, NULL);
#endif
- break;
}
}
}
diff --git a/source/blender/blenkernel/intern/camera.c b/source/blender/blenkernel/intern/camera.c
index 869e312614e..8c4bced1563 100644
--- a/source/blender/blenkernel/intern/camera.c
+++ b/source/blender/blenkernel/intern/camera.c
@@ -48,7 +48,6 @@
#include "BKE_animsys.h"
#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"
@@ -61,8 +60,6 @@
#include "MEM_guardedalloc.h"
-#include "GPU_compositing.h"
-
/****************************** Camera Datablock *****************************/
void BKE_camera_init(Camera *cam)
@@ -79,8 +76,6 @@ void BKE_camera_init(Camera *cam)
cam->flag |= CAM_SHOWPASSEPARTOUT;
cam->passepartalpha = 0.5f;
- GPU_fx_compositor_init_dof_settings(&cam->gpu_dof);
-
/* stereoscopy 3d */
cam->stereo.interocular_distance = 0.065f;
cam->stereo.convergence_distance = 30.f * 0.065f;
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index ea54548ab09..a6c6d360769 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -3307,7 +3307,7 @@ void CDDM_calc_edges_tessface(DerivedMesh *dm)
}
}
- numEdges = BLI_edgeset_size(eh);
+ numEdges = BLI_edgeset_len(eh);
/* write new edges into a temporary CustomData */
CustomData_reset(&edgeData);
@@ -3376,7 +3376,7 @@ void CDDM_calc_edges(DerivedMesh *dm)
}
}
- numEdges = BLI_edgehash_size(eh);
+ numEdges = BLI_edgehash_len(eh);
/* write new edges into a temporary CustomData */
CustomData_reset(&edgeData);
diff --git a/source/blender/blenkernel/intern/cloth.c b/source/blender/blenkernel/intern/cloth.c
index 09b793629f7..339dcc4a62e 100644
--- a/source/blender/blenkernel/intern/cloth.c
+++ b/source/blender/blenkernel/intern/cloth.c
@@ -40,6 +40,8 @@
#include "BLI_edgehash.h"
#include "BLI_linklist.h"
+#include "DEG_depsgraph.h"
+
#include "BKE_cdderivedmesh.h"
#include "BKE_cloth.h"
#include "BKE_effect.h"
@@ -478,8 +480,6 @@ void clothModifier_do(ClothModifierData *clmd, const struct EvaluationContext *e
return;
}
- return;
-
/* if on second frame, write cache for first frame */
if (cache->simframe == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
BKE_ptcache_write(&pid, startframe);
@@ -639,7 +639,7 @@ void cloth_free_modifier_extern(ClothModifierData *clmd )
**/
static void cloth_to_object (Object *ob, ClothModifierData *clmd, float (*vertexCos)[3])
{
- unsigned int i = 0;
+ unsigned int i = 0;
Cloth *cloth = clmd->clothObject;
if (clmd->clothObject) {
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index ca77969ccaa..15fda8a9786 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -68,44 +68,67 @@ static SceneCollection *collection_master_from_id(const ID *owner_id)
}
/**
- * 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
+ * The automatic/fallback name of a new collection.
*/
-SceneCollection *BKE_collection_add(ID *owner_id, SceneCollection *sc_parent, const int type, const char *name_custom)
+void BKE_collection_new_name_get(ID *owner_id, SceneCollection *sc_parent, char *rname)
+{
+ SceneCollection *sc_master = collection_master_from_id(owner_id);
+ char *name;
+
+ if (sc_parent == sc_master) {
+ name = BLI_sprintfN("Collection %d", BLI_listbase_count(&sc_master->scene_collections) + 1);
+ }
+ else {
+ const int number = BLI_listbase_count(&sc_parent->scene_collections) + 1;
+ const int digits = integer_digits_i(number);
+ const int max_len = sizeof(sc_parent->name) - 1 /* NULL terminator */ - (1 + digits) /* " %d" */;
+ name = BLI_sprintfN("%.*s %d", max_len, sc_parent->name, number);
+ }
+
+ BLI_strncpy(rname, name, MAX_NAME);
+ MEM_freeN(name);
+}
+
+/**
+ * Add a new collection, but don't handle syncing with layer collections
+ */
+static SceneCollection *collection_add(ID *owner_id, SceneCollection *sc_parent, const int type, const char *name_custom)
{
SceneCollection *sc_master = collection_master_from_id(owner_id);
SceneCollection *sc = MEM_callocN(sizeof(SceneCollection), "New Collection");
sc->type = type;
- const char *name = name_custom;
+ char name[MAX_NAME];
if (!sc_parent) {
sc_parent = sc_master;
}
- if (!name) {
- if (sc_parent == sc_master) {
- name = BLI_sprintfN("Collection %d", BLI_listbase_count(&sc_master->scene_collections) + 1);
- }
- else {
- const int number = BLI_listbase_count(&sc_parent->scene_collections) + 1;
- const int digits = integer_digits_i(number);
- const int max_len = sizeof(sc_parent->name)
- - 1 /* NULL terminator */
- - (1 + digits) /* " %d" */;
- name = BLI_sprintfN("%.*s %d", max_len, sc_parent->name, number);
- }
+ if (name_custom != NULL) {
+ BLI_strncpy(name, name_custom, MAX_NAME);
+ }
+ else {
+ BKE_collection_new_name_get(owner_id, sc_parent, name);
}
BLI_addtail(&sc_parent->scene_collections, sc);
- BKE_collection_rename((Scene *)owner_id, sc, name);
+ BKE_collection_rename(owner_id, sc, name);
- BKE_layer_sync_new_scene_collection(owner_id, sc_parent, sc);
+ return sc;
+}
- if (name != name_custom) {
- MEM_freeN((char *)name);
+/**
+ * Add a collection to a collection ListBase and syncronize all render layers
+ * The ListBase is NULL when the collection is to be added to the master collection
+ */
+SceneCollection *BKE_collection_add(ID *owner_id, SceneCollection *sc_parent, const int type, const char *name_custom)
+{
+ if (sc_parent == NULL) {
+ sc_parent = BKE_collection_master(owner_id);
}
- return sc;
+ SceneCollection *scene_collection = collection_add(owner_id, sc_parent, type, name_custom);
+ BKE_layer_sync_new_scene_collection(owner_id, sc_parent, scene_collection);
+ return scene_collection;
}
/**
@@ -208,7 +231,7 @@ bool BKE_collection_remove(ID *owner_id, SceneCollection *sc)
ListBase collection_objects;
BLI_duplicatelist(&collection_objects, &sc->objects);
- FOREACH_SCENE_COLLECTION(owner_id, scene_collection_iter)
+ FOREACH_SCENE_COLLECTION_BEGIN(owner_id, scene_collection_iter)
{
if (scene_collection_iter == sc) {
continue;
@@ -226,7 +249,7 @@ bool BKE_collection_remove(ID *owner_id, SceneCollection *sc)
link = link_next;
}
}
- FOREACH_SCENE_COLLECTION_END
+ FOREACH_SCENE_COLLECTION_END;
for (LinkData *link = collection_objects.first; link; link = link->next) {
BKE_collection_object_add(owner_id, sc_master, link->data);
@@ -270,6 +293,43 @@ void BKE_collection_copy_data(SceneCollection *sc_dst, SceneCollection *sc_src,
}
}
+/**
+ * Makes a shallow copy of a SceneCollection
+ *
+ * Add a new collection in the same level as the old one, copy any nested collections
+ * but link the objects to the new collection (as oppose to copy them).
+ */
+SceneCollection *BKE_collection_duplicate(ID *owner_id, SceneCollection *scene_collection)
+{
+ SceneCollection *scene_collection_master = BKE_collection_master(owner_id);
+ SceneCollection *scene_collection_parent = find_collection_parent(scene_collection, scene_collection_master);
+
+ /* It's not allowed to copy the master collection. */
+ if (scene_collection_master == scene_collection) {
+ return NULL;
+ }
+
+ SceneCollection *scene_collection_new = collection_add(
+ owner_id,
+ scene_collection_parent,
+ scene_collection->type,
+ scene_collection->name);
+
+ if (scene_collection_new != scene_collection->next) {
+ BLI_remlink(&scene_collection_parent->scene_collections, scene_collection_new);
+ BLI_insertlinkafter(&scene_collection_parent->scene_collections, scene_collection, scene_collection_new);
+ }
+
+ BKE_collection_copy_data(scene_collection_new, scene_collection, 0);
+ BKE_layer_sync_new_scene_collection(owner_id, scene_collection_parent, scene_collection_new);
+
+ /* Make sure every linked instance of the new collection has the same values (flags, overrides, ...) as the
+ * corresponding original collection. */
+ BKE_layer_collection_sync_flags(owner_id, scene_collection_new, scene_collection);
+
+ return scene_collection_new;
+}
+
static SceneCollection *master_collection_from_id(const ID *owner_id)
{
switch (GS(owner_id->name)) {
@@ -298,9 +358,9 @@ static void collection_rename(const ID *owner_id, SceneCollection *sc, const cha
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)
+void BKE_collection_rename(const ID *owner_id, SceneCollection *sc, const char *name)
{
- collection_rename(&scene->id, sc, name);
+ collection_rename(owner_id, sc, name);
}
/**
@@ -343,7 +403,7 @@ static void collection_object_add(const ID *owner_id, SceneCollection *sc, Objec
*/
bool BKE_collection_object_add(const ID *owner_id, SceneCollection *sc, Object *ob)
{
- if (BLI_findptr(&sc->objects, ob, offsetof(LinkData, data))) {
+ if (BKE_collection_object_exists(sc, ob)) {
/* don't add the same object twice */
return false;
}
@@ -358,13 +418,13 @@ bool BKE_collection_object_add(const ID *owner_id, SceneCollection *sc, Object *
*/
void BKE_collection_object_add_from(Scene *scene, Object *ob_src, Object *ob_dst)
{
- FOREACH_SCENE_COLLECTION(scene, sc)
+ FOREACH_SCENE_COLLECTION_BEGIN(scene, sc)
{
if (BLI_findptr(&sc->objects, ob_src, offsetof(LinkData, data))) {
collection_object_add(&scene->id, sc, ob_dst);
}
}
- FOREACH_SCENE_COLLECTION_END
+ 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);
@@ -411,13 +471,28 @@ bool BKE_collection_object_remove(Main *bmain, ID *owner_id, SceneCollection *sc
}
/**
- * Move object from a collection into another
+ * Remove object from all collections of scene
+ * \param scene_collection_skip: Don't remove base from this collection.
*/
-void BKE_collection_object_move(ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src, Object *ob)
+static bool collections_object_remove_ex(Main *bmain, ID *owner_id, Object *ob, const bool free_us,
+ SceneCollection *scene_collection_skip)
{
- if (BKE_collection_object_add(owner_id, sc_dst, ob)) {
- BKE_collection_object_remove(NULL, owner_id, sc_src, ob, false);
+ bool removed = false;
+ if (GS(owner_id->name) == ID_SCE) {
+ BKE_scene_remove_rigidbody_object((Scene *)owner_id, ob);
}
+ else {
+ BLI_assert(GS(owner_id->name) == ID_GR);
+ }
+
+ FOREACH_SCENE_COLLECTION_BEGIN(owner_id, sc)
+ {
+ if (sc != scene_collection_skip) {
+ removed |= BKE_collection_object_remove(bmain, owner_id, sc, ob, free_us);
+ }
+ }
+ FOREACH_SCENE_COLLECTION_END;
+ return removed;
}
/**
@@ -425,20 +500,72 @@ void BKE_collection_object_move(ID *owner_id, SceneCollection *sc_dst, SceneColl
*/
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);
+ return collections_object_remove_ex(bmain, owner_id, ob, free_us, NULL);
+}
+
+/**
+ * Move object from a collection into another
+ *
+ * If source collection is NULL move it from all the existing collections.
+ */
+void BKE_collection_object_move(ID *owner_id, SceneCollection *sc_dst, SceneCollection *sc_src, Object *ob)
+{
+ /* In both cases we first add the object, then remove it from the other collections.
+ * Otherwise we lose the original base and whether it was active and selected. */
+ if (sc_src != NULL) {
+ if (BKE_collection_object_add(owner_id, sc_dst, ob)) {
+ BKE_collection_object_remove(NULL, owner_id, sc_src, ob, false);
+ }
}
else {
- BLI_assert(GS(owner_id->name) == ID_GR);
+ /* Adding will fail if object is already in collection.
+ * However we still need to remove it from the other collections. */
+ BKE_collection_object_add(owner_id, sc_dst, ob);
+ collections_object_remove_ex(NULL, owner_id, ob, false, sc_dst);
+ }
+}
+
+/**
+ * Whether the object is directly inside the collection.
+ */
+bool BKE_collection_object_exists(struct SceneCollection *scene_collection, struct Object *ob)
+{
+ if (BLI_findptr(&scene_collection->objects, ob, offsetof(LinkData, data))) {
+ return true;
}
+ return false;
+}
- FOREACH_SCENE_COLLECTION(owner_id, sc)
+static SceneCollection *scene_collection_from_index_recursive(SceneCollection *scene_collection, const int index, int *index_current)
+{
+ if (index == (*index_current)) {
+ return scene_collection;
+ }
+
+ (*index_current)++;
+
+ for (SceneCollection *scene_collection_iter = scene_collection->scene_collections.first;
+ scene_collection_iter != NULL;
+ scene_collection_iter = scene_collection_iter->next)
{
- removed |= BKE_collection_object_remove(bmain, owner_id, sc, ob, free_us);
+ SceneCollection *nested = scene_collection_from_index_recursive(scene_collection_iter, index, index_current);
+ if (nested != NULL) {
+ return nested;
+ }
}
- FOREACH_SCENE_COLLECTION_END
- return removed;
+ return NULL;
+}
+
+/**
+ * Return Scene Collection for a given index.
+ *
+ * The index is calculated from top to bottom counting the children before the siblings.
+ */
+SceneCollection *BKE_collection_from_index(Scene *scene, const int index)
+{
+ int index_current = 0;
+ SceneCollection *master_collection = BKE_collection_master(&scene->id);
+ return scene_collection_from_index_recursive(master_collection, index, &index_current);
}
static void layer_collection_sync(LayerCollection *lc_dst, LayerCollection *lc_src)
@@ -460,6 +587,33 @@ static void layer_collection_sync(LayerCollection *lc_dst, LayerCollection *lc_s
}
/**
+ * Select all the objects in this SceneCollection (and its nested collections) for this ViewLayer.
+ * Return true if any object was selected.
+ */
+bool BKE_collection_objects_select(ViewLayer *view_layer, SceneCollection *scene_collection)
+{
+ LayerCollection *layer_collection = BKE_layer_collection_first_from_scene_collection(view_layer, scene_collection);
+ if (layer_collection != NULL) {
+ BKE_layer_collection_objects_select(layer_collection);
+ return true;
+ }
+ else {
+ /* Slower approach, we need to iterate over all the objects and for each one we see if there is a base. */
+ bool changed = false;
+ for (LinkData *link = scene_collection->objects.first; link; link = link->next) {
+ Base *base = BKE_view_layer_base_find(view_layer, link->data);
+ if (base != NULL) {
+ if (((base->flag & BASE_SELECTED) == 0) && ((base->flag & BASE_SELECTABLED) != 0)) {
+ base->flag |= BASE_SELECTED;
+ changed = true;
+ }
+ }
+ }
+ return changed;
+ }
+}
+
+/**
* Leave only the master collection in, remove everything else.
* @param group
*/
@@ -505,11 +659,11 @@ Group *BKE_collection_group_create(Main *bmain, Scene *scene, LayerCollection *l
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)
+ FOREACH_SCENE_COLLECTION_BEGIN(&group->id, sc_group)
{
sc_group->type = COLLECTION_TYPE_GROUP_INTERNAL;
}
- FOREACH_SCENE_COLLECTION_END
+ FOREACH_SCENE_COLLECTION_END;
lc_dst = BKE_collection_link(group->view_layer, sc_dst);
layer_collection_sync(lc_dst, lc_src);
diff --git a/source/blender/blenkernel/intern/collision.c b/source/blender/blenkernel/intern/collision.c
index 2f80fbbec46..ee3c38b9282 100644
--- a/source/blender/blenkernel/intern/collision.c
+++ b/source/blender/blenkernel/intern/collision.c
@@ -36,7 +36,7 @@
#include "DNA_effect_types.h"
#include "DNA_group_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_scene_types.h"
#include "DNA_meshdata_types.h"
@@ -180,8 +180,8 @@ static void collision_compute_barycentric ( float pv[3], float p1[3], float p2[3
/* dot_v3v3 */
#define INPR(v1, v2) ( (v1)[0] * (v2)[0] + (v1)[1] * (v2)[1] + (v1)[2] * (v2)[2])
- double tempV1[3], tempV2[3], tempV4[3];
- double a, b, c, d, e, f;
+ double tempV1[3], tempV2[3], tempV4[3];
+ double a, b, c, d, e, f;
VECSUB ( tempV1, p1, p3 );
VECSUB ( tempV2, p2, p3 );
@@ -506,11 +506,11 @@ static void add_collision_object(Object ***objs, unsigned int *numobj, unsigned
Group *group= ob->dup_group;
/* add objects */
- FOREACH_GROUP_OBJECT(group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(group, object)
{
add_collision_object(objs, numobj, maxobj, object, self, level+1, modifier_type);
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
}
@@ -527,11 +527,11 @@ Object **get_collisionobjects_ext(Scene *scene, Object *self, Group *group, unsi
/* gather all collision objects */
if (group) {
/* use specified group */
- FOREACH_GROUP_OBJECT(group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(group, object)
{
add_collision_object(&objs, &numobj, &maxobj, object, self, level, modifier_type);
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
else {
Scene *sce_iter;
@@ -584,11 +584,11 @@ static void add_collider_cache_object(ListBase **objs, Object *ob, Object *self,
Group *group= ob->dup_group;
/* add objects */
- FOREACH_GROUP_OBJECT(group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(group, object)
{
add_collider_cache_object(objs, object, self, level+1);
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
}
@@ -598,11 +598,11 @@ ListBase *get_collider_cache(Scene *scene, Object *self, Group *group)
/* add object in same layer in scene */
if (group) {
- FOREACH_GROUP_OBJECT(group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(group, object)
{
add_collider_cache_object(&objs, object, self, 0);
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
else {
Scene *sce_iter;
diff --git a/source/blender/blenkernel/intern/colorband.c b/source/blender/blenkernel/intern/colorband.c
index d35e797ddac..f72d4df725a 100644
--- a/source/blender/blenkernel/intern/colorband.c
+++ b/source/blender/blenkernel/intern/colorband.c
@@ -210,7 +210,7 @@ static void colorband_init_from_table_rgba_resample(
while ((carr_len > 1 && !BLI_heap_is_empty(heap)) &&
((carr_len >= MAXCOLORBAND) || (BLI_heap_node_value(BLI_heap_top(heap)) <= eps_2x)))
{
- c = BLI_heap_popmin(heap);
+ c = BLI_heap_pop_min(heap);
struct ColorResampleElem *c_next = c->next, *c_prev = c->prev;
c_prev->next = c_next;
c_next->prev = c_prev;
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index b8dc7944a75..b070ccdd4eb 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -1917,14 +1917,15 @@ static void samevolume_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *
bSameVolumeConstraint *data = con->data;
float volume = data->volume;
- float fac = 1.0f;
+ float fac = 1.0f, total_scale;
float obsize[3];
mat4_to_size(obsize, cob->matrix);
/* calculate normalizing scale factor for non-essential values */
- if (obsize[data->flag] != 0)
- fac = sqrtf(volume / obsize[data->flag]);
+ total_scale = obsize[0] * obsize[1] * obsize[2];
+ if (total_scale != 0)
+ fac = sqrtf(volume / total_scale);
/* apply scaling factor to the channels not being kept */
switch (data->flag) {
diff --git a/source/blender/blenkernel/intern/context.c b/source/blender/blenkernel/intern/context.c
index 09823a8b463..809db09eb86 100644
--- a/source/blender/blenkernel/intern/context.c
+++ b/source/blender/blenkernel/intern/context.c
@@ -997,7 +997,7 @@ SceneCollection *CTX_data_scene_collection(const bContext *C)
return BKE_collection_master(&scene->id);
}
-int CTX_data_mode_enum_ex(const Object *obedit, const Object *ob)
+int CTX_data_mode_enum_ex(const Object *obedit, const Object *ob, const eObjectMode object_mode)
{
// Object *obedit = CTX_data_edit_object(C);
if (obedit) {
@@ -1023,12 +1023,12 @@ int CTX_data_mode_enum_ex(const Object *obedit, const Object *ob)
else {
// Object *ob = CTX_data_active_object(C);
if (ob) {
- if (ob->mode & OB_MODE_POSE) return CTX_MODE_POSE;
- else if (ob->mode & OB_MODE_SCULPT) return CTX_MODE_SCULPT;
- else if (ob->mode & OB_MODE_WEIGHT_PAINT) return CTX_MODE_PAINT_WEIGHT;
- else if (ob->mode & OB_MODE_VERTEX_PAINT) return CTX_MODE_PAINT_VERTEX;
- else if (ob->mode & OB_MODE_TEXTURE_PAINT) return CTX_MODE_PAINT_TEXTURE;
- else if (ob->mode & OB_MODE_PARTICLE_EDIT) return CTX_MODE_PARTICLE;
+ if (object_mode & OB_MODE_POSE) return CTX_MODE_POSE;
+ else if (object_mode & OB_MODE_SCULPT) return CTX_MODE_SCULPT;
+ else if (object_mode & OB_MODE_WEIGHT_PAINT) return CTX_MODE_PAINT_WEIGHT;
+ else if (object_mode & OB_MODE_VERTEX_PAINT) return CTX_MODE_PAINT_VERTEX;
+ else if (object_mode & OB_MODE_TEXTURE_PAINT) return CTX_MODE_PAINT_TEXTURE;
+ else if (object_mode & OB_MODE_PARTICLE_EDIT) return CTX_MODE_PARTICLE;
}
}
@@ -1039,7 +1039,7 @@ 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);
+ return CTX_data_mode_enum_ex(obedit, obact, obact ? obact->mode : OB_MODE_OBJECT);
}
/* would prefer if we can use the enum version below over this one - Campbell */
@@ -1276,8 +1276,8 @@ void CTX_data_eval_ctx(const bContext *C, EvaluationContext *eval_ctx)
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);
+ DEG_evaluation_context_init_from_scene(
+ eval_ctx,
+ scene, view_layer,
+ DAG_EVAL_VIEWPORT);
}
diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c
index 2a27bad0fb5..0c4dbdf7763 100644
--- a/source/blender/blenkernel/intern/curve.c
+++ b/source/blender/blenkernel/intern/curve.c
@@ -5258,9 +5258,7 @@ void BKE_curve_rect_from_textbox(const struct Curve *cu, const struct TextBox *t
void BKE_curve_eval_geometry(const EvaluationContext *UNUSED(eval_ctx),
Curve *curve)
{
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s on %s\n", __func__, curve->id.name);
- }
+ DEG_debug_print_eval(__func__, curve->id.name, curve);
if (curve->bb == NULL || (curve->bb->flag & BOUNDBOX_DIRTY)) {
BKE_curve_texspace_calc(curve);
}
diff --git a/source/blender/blenkernel/intern/curve_decimate.c b/source/blender/blenkernel/intern/curve_decimate.c
index 7983c63c99d..1a6c4714afd 100644
--- a/source/blender/blenkernel/intern/curve_decimate.c
+++ b/source/blender/blenkernel/intern/curve_decimate.c
@@ -159,7 +159,7 @@ static void curve_decimate(
struct Knot *k;
{
- struct Removal *r = BLI_heap_popmin(heap);
+ struct Removal *r = BLI_heap_pop_min(heap);
k = &knots[r->knot_index];
k->heap_node = NULL;
k->prev->handles[1] = r->handles[0];
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 15a520fe8ce..ffa4e652056 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -299,7 +299,10 @@ bool BKE_displist_surfindex_get(DispList *dl, int a, int *b, int *p1, int *p2, i
}
/* ****************** make displists ********************* */
-
+#ifdef __INTEL_COMPILER
+/* ICC with the optimization -02 causes crashes. */
+# pragma intel optimization_level 1
+#endif
static void curve_to_displist(Curve *cu, ListBase *nubase, ListBase *dispbase,
const bool for_render, const bool use_render_resolution)
{
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index 2591c3c3c47..ee678dd4c41 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -54,7 +54,7 @@
#include "BKE_animsys.h"
#include "BKE_armature.h"
-#include "BKE_bvhutils.h" /* bvh tree */
+#include "BKE_bvhutils.h" /* bvh tree */
#include "BKE_colorband.h"
#include "BKE_cdderivedmesh.h"
#include "BKE_constraint.h"
@@ -3348,7 +3348,7 @@ typedef struct BrushMaterials {
/* Initialize materials for brush object:
* Calculates inverse matrices for linked objects, updates
* volume caches etc. */
-static void dynamicPaint_updateBrushMaterials(Object *brushOb, Material *ui_mat, Scene *scene, BrushMaterials *bMats)
+static void dynamicPaint_updateBrushMaterials(const EvaluationContext *eval_ctx, Object *brushOb, Material *ui_mat, Scene *scene, BrushMaterials *bMats)
{
/* Calculate inverse transformation matrix
* for this object */
@@ -3363,13 +3363,13 @@ static void dynamicPaint_updateBrushMaterials(Object *brushOb, Material *ui_mat,
if (tot) {
bMats->ob_mats = MEM_callocN(sizeof(Material *) * (tot), "BrushMaterials");
for (i = 0; i < tot; i++) {
- bMats->ob_mats[i] = RE_sample_material_init(give_current_material(brushOb, (i + 1)), scene);
+ bMats->ob_mats[i] = RE_sample_material_init(eval_ctx, give_current_material(brushOb, (i + 1)), scene);
}
}
bMats->tot = tot;
}
else {
- bMats->mat = RE_sample_material_init(ui_mat, scene);
+ bMats->mat = RE_sample_material_init(eval_ctx, ui_mat, scene);
}
}
@@ -4516,7 +4516,7 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface,
*/
tree = BLI_kdtree_new(psys->totpart);
- /* loop through particles and insert valid ones to the tree */
+ /* loop through particles and insert valid ones to the tree */
p = 0;
for (ParticleData *pa = psys->particles; p < psys->totpart; p++, pa++) {
/* Proceed only if particle is active */
@@ -4555,7 +4555,7 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface,
}
/* begin thread safe malloc */
- BLI_begin_threaded_malloc();
+ BLI_threaded_malloc_begin();
/* only continue if particle bb is close enough to canvas bb */
if (boundsIntersectDist(&grid->grid_bounds, &part_bb, range)) {
@@ -4590,7 +4590,7 @@ static int dynamicPaint_paintParticles(DynamicPaintSurface *surface,
&settings);
}
}
- BLI_end_threaded_malloc();
+ BLI_threaded_malloc_end();
BLI_kdtree_free(tree);
return 1;
@@ -6087,7 +6087,7 @@ static int dynamicPaint_doStep(const struct EvaluationContext *eval_ctx, Scene *
}
/* Prepare materials if required */
if (brush_usesMaterial(brush, scene))
- dynamicPaint_updateBrushMaterials(brushObj, brush->mat, scene, &bMats);
+ dynamicPaint_updateBrushMaterials(eval_ctx, brushObj, brush->mat, scene, &bMats);
/* Apply brush on the surface depending on it's collision type */
if (brush->psys && brush->psys->part &&
diff --git a/source/blender/blenkernel/intern/editderivedmesh.c b/source/blender/blenkernel/intern/editderivedmesh.c
index 0491cbd21f0..2018962eb62 100644
--- a/source/blender/blenkernel/intern/editderivedmesh.c
+++ b/source/blender/blenkernel/intern/editderivedmesh.c
@@ -44,7 +44,7 @@
#include "atomic_ops.h"
#include "BLI_math.h"
-#include "BLI_jitter.h"
+#include "BLI_jitter_2d.h"
#include "BLI_bitmap.h"
#include "BLI_task.h"
diff --git a/source/blender/blenkernel/intern/editlattice.c b/source/blender/blenkernel/intern/editlattice.c
new file mode 100644
index 00000000000..cef3c970c7a
--- /dev/null
+++ b/source/blender/blenkernel/intern/editlattice.c
@@ -0,0 +1,147 @@
+/*
+ * ***** 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/editlattice.c
+ * \ingroup bke
+ */
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_listBase.h"
+#include "DNA_object_types.h"
+#include "DNA_key_types.h"
+#include "DNA_lattice_types.h"
+#include "DNA_meshdata_types.h"
+#include "DNA_curve_types.h"
+
+#include "BLI_math_vector.h"
+#include "BLI_listbase.h"
+
+#include "BKE_deform.h"
+#include "BKE_key.h"
+
+#include "BKE_editlattice.h" /* own include */
+
+void BKE_editlattice_free(Object *ob)
+{
+ Lattice *lt = ob->data;
+
+ if (lt->editlatt) {
+ Lattice *editlt = lt->editlatt->latt;
+
+ if (editlt->def) {
+ MEM_freeN(editlt->def);
+ }
+ if (editlt->dvert) {
+ BKE_defvert_array_free(editlt->dvert, editlt->pntsu * editlt->pntsv * editlt->pntsw);
+ }
+ MEM_freeN(editlt);
+ MEM_freeN(lt->editlatt);
+
+ lt->editlatt = NULL;
+ }
+}
+
+void BKE_editlattice_make(Object *obedit)
+{
+ Lattice *lt = obedit->data;
+ KeyBlock *actkey;
+
+ BKE_editlattice_free(obedit);
+
+ actkey = BKE_keyblock_from_object(obedit);
+ if (actkey) {
+ BKE_keyblock_convert_to_lattice(actkey, lt);
+ }
+ lt->editlatt = MEM_callocN(sizeof(EditLatt), "editlatt");
+ lt->editlatt->latt = MEM_dupallocN(lt);
+ lt->editlatt->latt->def = MEM_dupallocN(lt->def);
+
+ if (lt->dvert) {
+ int tot = lt->pntsu * lt->pntsv * lt->pntsw;
+ lt->editlatt->latt->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
+ BKE_defvert_array_copy(lt->editlatt->latt->dvert, lt->dvert, tot);
+ }
+
+ if (lt->key) {
+ lt->editlatt->shapenr = obedit->shapenr;
+ }
+}
+
+void BKE_editlattice_load(Object *obedit)
+{
+ Lattice *lt, *editlt;
+ KeyBlock *actkey;
+ BPoint *bp;
+ float *fp;
+ int tot;
+
+ lt = obedit->data;
+ editlt = lt->editlatt->latt;
+
+ if (lt->editlatt->shapenr) {
+ actkey = BLI_findlink(&lt->key->block, lt->editlatt->shapenr - 1);
+
+ /* active key: vertices */
+ tot = editlt->pntsu * editlt->pntsv * editlt->pntsw;
+
+ if (actkey->data) {
+ MEM_freeN(actkey->data);
+ }
+
+ fp = actkey->data = MEM_callocN(lt->key->elemsize * tot, "actkey->data");
+ actkey->totelem = tot;
+
+ bp = editlt->def;
+ while (tot--) {
+ copy_v3_v3(fp, bp->vec);
+ fp += 3;
+ bp++;
+ }
+ }
+ else {
+ MEM_freeN(lt->def);
+
+ lt->def = MEM_dupallocN(editlt->def);
+
+ lt->flag = editlt->flag;
+
+ lt->pntsu = editlt->pntsu;
+ lt->pntsv = editlt->pntsv;
+ lt->pntsw = editlt->pntsw;
+
+ lt->typeu = editlt->typeu;
+ lt->typev = editlt->typev;
+ lt->typew = editlt->typew;
+ lt->actbp = editlt->actbp;
+ }
+
+ if (lt->dvert) {
+ BKE_defvert_array_free(lt->dvert, lt->pntsu * lt->pntsv * lt->pntsw);
+ lt->dvert = NULL;
+ }
+
+ if (editlt->dvert) {
+ tot = lt->pntsu * lt->pntsv * lt->pntsw;
+
+ lt->dvert = MEM_mallocN(sizeof(MDeformVert) * tot, "Lattice MDeformVert");
+ BKE_defvert_array_copy(lt->dvert, editlt->dvert, tot);
+ }
+}
diff --git a/source/blender/blenkernel/intern/effect.c b/source/blender/blenkernel/intern/effect.c
index 16124fb4777..b54093555f5 100644
--- a/source/blender/blenkernel/intern/effect.c
+++ b/source/blender/blenkernel/intern/effect.c
@@ -42,7 +42,7 @@
#include "DNA_listBase.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_particle_types.h"
#include "DNA_texture_types.h"
#include "DNA_scene_types.h"
@@ -221,7 +221,8 @@ ListBase *pdInitEffectors(
if (weights->group) {
view_layer = weights->group->view_layer;
}
- else if (eval_ctx) {
+ /* TODO(mai): the check for view_layer shouldnt be needed, remove when render engine api is updated for this */
+ else if (eval_ctx && eval_ctx->view_layer) {
view_layer = eval_ctx->view_layer;
}
else {
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 9c85a26b58a..905f103250a 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -804,7 +804,7 @@ void bezt_add_to_cfra_elem(ListBase *lb, BezTriple *bezt)
for (ce = lb->first; ce; ce = ce->next) {
/* double key? */
- if (ce->cfra == bezt->vec[1][0]) {
+ if (IS_EQT(ce->cfra, bezt->vec[1][0], BEZT_BINARYSEARCH_THRESH)) {
if (bezt->f2 & SELECT) ce->sel = bezt->f2;
return;
}
@@ -1590,11 +1590,9 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
return 0.0f;
}
else if (dtar->transChan >= DTAR_TRANSCHAN_SCALEX) {
- /* extract scale, and choose the right axis */
- float scale[3];
-
- mat4_to_size(scale, mat);
- return scale[dtar->transChan - DTAR_TRANSCHAN_SCALEX];
+ /* Extract scale, and choose the right axis,
+ * inline 'mat4_to_size'. */
+ return len_v3(mat[dtar->transChan - DTAR_TRANSCHAN_SCALEX]);
}
else if (dtar->transChan >= DTAR_TRANSCHAN_ROTX) {
/* extract rotation as eulers (if needed)
diff --git a/source/blender/blenkernel/intern/fluidsim.c b/source/blender/blenkernel/intern/fluidsim.c
index 12b9abc6d03..d0d3317b477 100644
--- a/source/blender/blenkernel/intern/fluidsim.c
+++ b/source/blender/blenkernel/intern/fluidsim.c
@@ -40,8 +40,8 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
-#include "DNA_object_fluidsim.h"
-#include "DNA_object_force.h" // for pointcache
+#include "DNA_object_fluidsim_types.h"
+#include "DNA_object_force_types.h" // for pointcache
#include "DNA_object_types.h"
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
@@ -54,7 +54,6 @@
#include "BKE_customdata.h"
#include "BKE_DerivedMesh.h"
#include "BKE_fluidsim.h"
-#include "BKE_global.h"
#include "BKE_modifier.h"
#include "BKE_mesh.h"
diff --git a/source/blender/blenkernel/intern/font.c b/source/blender/blenkernel/intern/font.c
index a314cc0a131..5545eba8764 100644
--- a/source/blender/blenkernel/intern/font.c
+++ b/source/blender/blenkernel/intern/font.c
@@ -1080,8 +1080,13 @@ makebreak:
float distfac, imat[4][4], imat3[3][3], cmat[3][3];
float minx, maxx, miny, maxy;
float timeofs, sizefac;
-
- invert_m4_m4(imat, ob->obmat);
+
+ if (ob != NULL) {
+ invert_m4_m4(imat, ob->obmat);
+ }
+ else {
+ unit_m4(imat);
+ }
copy_m3_m4(imat3, imat);
copy_m3_m4(cmat, cu->textoncurve->obmat);
diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c
index ca6d92efa80..7566d370c45 100644
--- a/source/blender/blenkernel/intern/group.c
+++ b/source/blender/blenkernel/intern/group.c
@@ -55,7 +55,7 @@
#include "BKE_object.h"
#include "BKE_scene.h"
-#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
+#include "DEG_depsgraph.h"
/** Free (or release) any data used by this group (does not free the group itself). */
void BKE_group_free(Group *group)
@@ -213,13 +213,13 @@ static bool group_object_cyclic_check_internal(Object *object, Group *group)
if (dup_group == group)
return true;
else {
- FOREACH_GROUP_OBJECT(dup_group, group_object)
+ FOREACH_GROUP_OBJECT_BEGIN(dup_group, group_object)
{
if (group_object_cyclic_check_internal(group_object, dup_group)) {
return true;
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
/* un-flag the object, it's allowed to have the same group multiple times in parallel */
@@ -278,13 +278,13 @@ Group *BKE_group_object_find(Group *group, Object *ob)
bool BKE_group_is_animated(Group *group, Object *UNUSED(parent))
{
- FOREACH_GROUP_OBJECT(group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(group, object)
{
if (object->proxy) {
return true;
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
return false;
}
@@ -369,45 +369,21 @@ void BKE_group_handle_recalc_and_update(const struct EvaluationContext *eval_ctx
#endif
{
/* only do existing tags, as set by regular depsgraph */
- FOREACH_GROUP_OBJECT(group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(group, object)
{
if (object->id.recalc & ID_RECALC_ALL) {
BKE_object_handle_update(eval_ctx, scene, object);
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
}
/* ******** Dependency graph evaluation ******** */
-static void group_eval_layer_collections(
- const struct EvaluationContext *eval_ctx,
- Group *group,
- ListBase *layer_collections,
- LayerCollection *parent_layer_collection)
-{
- BLI_LISTBASE_FOREACH (LayerCollection *, layer_collection, layer_collections) {
- /* Evaluate layer collection itself. */
- BKE_layer_eval_layer_collection(eval_ctx,
- layer_collection,
- parent_layer_collection);
- /* Evaluate nested collections. */
- group_eval_layer_collections(eval_ctx,
- group,
- &layer_collection->layer_collections,
- layer_collection);
- }
-}
-
void BKE_group_eval_view_layers(const struct EvaluationContext *eval_ctx,
Group *group)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, group->id.name, group);
- BKE_layer_eval_layer_collection_pre(eval_ctx, &group->id, group->view_layer);
- group_eval_layer_collections(eval_ctx,
- group,
- &group->view_layer->layer_collections,
- NULL);
- BKE_layer_eval_layer_collection_post(eval_ctx, group->view_layer);
+ DEG_debug_print_eval(__func__, group->id.name, group);
+ BKE_layer_eval_view_layer(eval_ctx, &group->id, group->view_layer);
}
diff --git a/source/blender/blenkernel/intern/icons.c b/source/blender/blenkernel/intern/icons.c
index a407fd0bae8..f3ff2c4425a 100644
--- a/source/blender/blenkernel/intern/icons.c
+++ b/source/blender/blenkernel/intern/icons.c
@@ -433,23 +433,28 @@ void BKE_previewimg_ensure(PreviewImage *prv, const int size)
}
}
-void BKE_icon_changed(int id)
+void BKE_icon_changed(const int icon_id)
{
Icon *icon = NULL;
- if (!id || G.background) return;
+ if (!icon_id || G.background) return;
- icon = BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(id));
+ icon = BLI_ghash_lookup(gIcons, SET_INT_IN_POINTER(icon_id));
if (icon) {
- PreviewImage *prv = BKE_previewimg_id_ensure((ID *)icon->obj);
+ /* We *only* expect ID-tied icons here, not non-ID icon/preview! */
+ BLI_assert(icon->type != 0);
+
+ /* Do not enforce creation of previews for valid ID types using BKE_previewimg_id_ensure() here ,
+ * we only want to ensure *existing* preview images are properly tagged as changed/invalid, that's all. */
+ PreviewImage **p_prv = BKE_previewimg_id_get_p((ID *)icon->obj);
- /* all previews changed */
- if (prv) {
+ /* If we have previews, they all are now invalid changed. */
+ if (p_prv && *p_prv) {
int i;
for (i = 0; i < NUM_ICON_SIZES; ++i) {
- prv->flag[i] |= PRV_CHANGED;
- prv->changed_timestamp[i]++;
+ (*p_prv)->flag[i] |= PRV_CHANGED;
+ (*p_prv)->changed_timestamp[i]++;
}
}
}
@@ -549,7 +554,7 @@ int BKE_icon_preview_ensure(ID *id, PreviewImage *preview)
return preview->icon_id;
}
-Icon *BKE_icon_get(int icon_id)
+Icon *BKE_icon_get(const int icon_id)
{
Icon *icon = NULL;
@@ -563,7 +568,7 @@ Icon *BKE_icon_get(int icon_id)
return icon;
}
-void BKE_icon_set(int icon_id, struct Icon *icon)
+void BKE_icon_set(const int icon_id, struct Icon *icon)
{
void **val_p;
@@ -586,7 +591,7 @@ void BKE_icon_id_delete(struct ID *id)
/**
* Remove icon and free data.
*/
-void BKE_icon_delete(int icon_id)
+void BKE_icon_delete(const int icon_id)
{
Icon *icon;
diff --git a/source/blender/blenkernel/intern/idprop.c b/source/blender/blenkernel/intern/idprop.c
index 33a665ba06e..87e5ed8cc1e 100644
--- a/source/blender/blenkernel/intern/idprop.c
+++ b/source/blender/blenkernel/intern/idprop.c
@@ -905,9 +905,10 @@ bool IDP_EqualsProperties_ex(IDProperty *prop1, IDProperty *prop2, const bool is
if (prop1->len != prop2->len)
return false;
- for (i = 0; i < prop1->len; i++)
- if (!IDP_EqualsProperties(&array1[i], &array2[i]))
+ for (i = 0; i < prop1->len; i++) {
+ if (!IDP_EqualsProperties_ex(&array1[i], &array2[i], is_strict))
return false;
+ }
return true;
}
case IDP_ID:
diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c
index d720dc41abf..28245f9a4d8 100644
--- a/source/blender/blenkernel/intern/image.c
+++ b/source/blender/blenkernel/intern/image.c
@@ -46,6 +46,7 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "IMB_moviecache.h"
+#include "IMB_metadata.h"
#ifdef WITH_OPENEXR
# include "intern/openexr/openexr_multi.h"
@@ -152,7 +153,7 @@ static void imagecache_put(Image *image, int index, ImBuf *ibuf)
if (image->cache == NULL) {
// char cache_name[64];
- // BLI_snprintf(cache_name, sizeof(cache_name), "Image Datablock %s", image->id.name);
+ // SNPRINTF(cache_name, "Image Datablock %s", image->id.name);
image->cache = IMB_moviecache_create("Image Datablock Cache", sizeof(ImageCacheKey),
imagecache_hashhash, imagecache_hashcmp);
@@ -437,7 +438,7 @@ static void copy_image_packedfiles(ListBase *lb_dst, const ListBase *lb_src)
BLI_listbase_clear(lb_dst);
for (imapf_src = lb_src->first; imapf_src; imapf_src = imapf_src->next) {
ImagePackedFile *imapf_dst = MEM_mallocN(sizeof(ImagePackedFile), "Image Packed Files (copy)");
- BLI_strncpy(imapf_dst->filepath, imapf_src->filepath, sizeof(imapf_dst->filepath));
+ STRNCPY(imapf_dst->filepath, imapf_src->filepath);
if (imapf_src->packedfile)
imapf_dst->packedfile = dupPackedFile(imapf_src->packedfile);
@@ -593,7 +594,7 @@ Image *BKE_image_load(Main *bmain, const char *filepath)
int file;
char str[FILE_MAX];
- BLI_strncpy(str, filepath, sizeof(str));
+ STRNCPY(str, filepath);
BLI_path_abs(str, bmain->name);
/* exists? */
@@ -603,7 +604,7 @@ Image *BKE_image_load(Main *bmain, const char *filepath)
close(file);
ima = image_alloc(bmain, BLI_path_basename(filepath), IMA_SRC_FILE, IMA_TYPE_IMAGE);
- BLI_strncpy(ima->name, filepath, sizeof(ima->name));
+ STRNCPY(ima->name, filepath);
if (BLI_testextensie_array(filepath, imb_ext_movie))
ima->source = IMA_SRC_MOVIE;
@@ -622,13 +623,13 @@ Image *BKE_image_load_exists_ex(const char *filepath, bool *r_exists)
Image *ima;
char str[FILE_MAX], strtest[FILE_MAX];
- BLI_strncpy(str, filepath, sizeof(str));
+ STRNCPY(str, filepath);
BLI_path_abs(str, G.main->name);
/* first search an identical filepath */
for (ima = G.main->image.first; ima; ima = ima->id.next) {
if (ima->source != IMA_SRC_VIEWER && ima->source != IMA_SRC_GENERATED) {
- BLI_strncpy(strtest, ima->name, sizeof(ima->name));
+ STRNCPY(strtest, ima->name);
BLI_path_abs(strtest, ID_BLEND_PATH(G.main, &ima->id));
if (BLI_path_cmp(strtest, str) == 0) {
@@ -669,7 +670,7 @@ static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char
if (colorspace_settings->name[0] == '\0') {
const char *colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_FLOAT);
- BLI_strncpy(colorspace_settings->name, colorspace, sizeof(colorspace_settings->name));
+ STRNCPY(colorspace_settings->name, colorspace);
}
if (ibuf != NULL) {
@@ -683,7 +684,7 @@ static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char
if (colorspace_settings->name[0] == '\0') {
const char *colorspace = IMB_colormanagement_role_colorspace_name_get(COLOR_ROLE_DEFAULT_BYTE);
- BLI_strncpy(colorspace_settings->name, colorspace, sizeof(colorspace_settings->name));
+ STRNCPY(colorspace_settings->name, colorspace);
}
if (ibuf != NULL) {
@@ -696,7 +697,7 @@ static ImBuf *add_ibuf_size(unsigned int width, unsigned int height, const char
return NULL;
}
- BLI_strncpy(ibuf->name, name, sizeof(ibuf->name));
+ STRNCPY(ibuf->name, name);
ibuf->userflags |= IB_BITMAPDIRTY;
switch (gen_type) {
@@ -726,7 +727,7 @@ Image *BKE_image_add_generated(
int view_id;
const char *names[2] = {STEREO_LEFT_NAME, STEREO_RIGHT_NAME};
- /* BLI_strncpy(ima->name, name, FILE_MAX); */ /* don't do this, this writes in ain invalid filepath! */
+ /* STRNCPY(ima->name, name); */ /* don't do this, this writes in ain invalid filepath! */
ima->gen_x = width;
ima->gen_y = height;
ima->gen_type = gen_type;
@@ -767,7 +768,7 @@ Image *BKE_image_add_from_imbuf(ImBuf *ibuf, const char *name)
ima = image_alloc(G.main, name, IMA_SRC_FILE, IMA_TYPE_IMAGE);
if (ima) {
- BLI_strncpy(ima->name, ibuf->name, FILE_MAX);
+ STRNCPY(ima->name, ibuf->name);
image_assign_ibuf(ima, ibuf, IMA_NO_INDEX, 0);
ima->ok = IMA_OK_LOADED;
}
@@ -813,7 +814,7 @@ static void image_memorypack_multiview(Image *ima)
pf->size = ibuf->encodedsize;
imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image PackedFile");
- BLI_strncpy(imapf->filepath, iv->filepath, sizeof(imapf->filepath));
+ STRNCPY(imapf->filepath, iv->filepath);
imapf->packedfile = pf;
BLI_addtail(&ima->packedfiles, imapf);
@@ -863,7 +864,7 @@ void BKE_image_memorypack(Image *ima)
pf->size = ibuf->encodedsize;
imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image PackedFile");
- BLI_strncpy(imapf->filepath, ima->name, sizeof(imapf->filepath));
+ STRNCPY(imapf->filepath, ima->name);
imapf->packedfile = pf;
BLI_addtail(&ima->packedfiles, imapf);
@@ -889,7 +890,7 @@ void BKE_image_packfiles(ReportList *reports, Image *ima, const char *basepath)
BLI_addtail(&ima->packedfiles, imapf);
imapf->packedfile = newPackedFile(reports, ima->name, basepath);
if (imapf->packedfile) {
- BLI_strncpy(imapf->filepath, ima->name, sizeof(imapf->filepath));
+ STRNCPY(imapf->filepath, ima->name);
}
else {
BLI_freelinkN(&ima->packedfiles, imapf);
@@ -903,7 +904,7 @@ void BKE_image_packfiles(ReportList *reports, Image *ima, const char *basepath)
imapf->packedfile = newPackedFile(reports, iv->filepath, basepath);
if (imapf->packedfile) {
- BLI_strncpy(imapf->filepath, iv->filepath, sizeof(imapf->filepath));
+ STRNCPY(imapf->filepath, iv->filepath);
}
else {
BLI_freelinkN(&ima->packedfiles, imapf);
@@ -923,7 +924,7 @@ void BKE_image_packfiles_from_mem(ReportList *reports, Image *ima, char *data, c
ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), __func__);
BLI_addtail(&ima->packedfiles, imapf);
imapf->packedfile = newPackedFileMemory(data, data_len);
- BLI_strncpy(imapf->filepath, ima->name, sizeof(imapf->filepath));
+ STRNCPY(imapf->filepath, ima->name);
}
}
@@ -1623,6 +1624,7 @@ typedef struct StampData {
char marker[512];
char time[512];
char frame[512];
+ char frame_range[512];
char camera[STAMP_NAME_SIZE];
char cameralens[STAMP_NAME_SIZE];
char scene[STAMP_NAME_SIZE];
@@ -1639,14 +1641,19 @@ typedef struct StampData {
} StampData;
#undef STAMP_NAME_SIZE
-static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int do_prefix)
+/**
+ * \param do_prefix: Include a label like "File ", "Date ", etc. in the stamp data strings.
+ * \param use_dynamic: Also include data that can change on a per-frame basis.
+ */
+static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int do_prefix,
+ bool use_dynamic)
{
char text[256];
struct tm *tl;
time_t t;
if (scene->r.stamp & R_STAMP_FILENAME) {
- BLI_snprintf(stamp_data->file, sizeof(stamp_data->file), do_prefix ? "File %s" : "%s", G.relbase_valid ? G.main->name : "<untitled>");
+ SNPRINTF(stamp_data->file, do_prefix ? "File %s" : "%s", G.relbase_valid ? G.main->name : "<untitled>");
}
else {
stamp_data->file[0] = '\0';
@@ -1654,7 +1661,7 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d
if (scene->r.stamp & R_STAMP_NOTE) {
/* Never do prefix for Note */
- BLI_snprintf(stamp_data->note, sizeof(stamp_data->note), "%s", scene->r.stamp_udata);
+ SNPRINTF(stamp_data->note, "%s", scene->r.stamp_udata);
}
else {
stamp_data->note[0] = '\0';
@@ -1663,83 +1670,93 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d
if (scene->r.stamp & R_STAMP_DATE) {
t = time(NULL);
tl = localtime(&t);
- BLI_snprintf(text, sizeof(text), "%04d/%02d/%02d %02d:%02d:%02d", tl->tm_year + 1900, tl->tm_mon + 1, tl->tm_mday, tl->tm_hour, tl->tm_min, tl->tm_sec);
- BLI_snprintf(stamp_data->date, sizeof(stamp_data->date), do_prefix ? "Date %s" : "%s", text);
+ SNPRINTF(text, "%04d/%02d/%02d %02d:%02d:%02d",
+ tl->tm_year + 1900, tl->tm_mon + 1, tl->tm_mday, tl->tm_hour, tl->tm_min, tl->tm_sec);
+ SNPRINTF(stamp_data->date, do_prefix ? "Date %s" : "%s", text);
}
else {
stamp_data->date[0] = '\0';
}
- if (scene->r.stamp & R_STAMP_MARKER) {
+ if (use_dynamic && scene->r.stamp & R_STAMP_MARKER) {
const char *name = BKE_scene_find_last_marker_name(scene, CFRA);
- if (name) BLI_strncpy(text, name, sizeof(text));
- else BLI_strncpy(text, "<none>", sizeof(text));
+ if (name) STRNCPY(text, name);
+ else STRNCPY(text, "<none>");
- BLI_snprintf(stamp_data->marker, sizeof(stamp_data->marker), do_prefix ? "Marker %s" : "%s", text);
+ SNPRINTF(stamp_data->marker, do_prefix ? "Marker %s" : "%s", text);
}
else {
stamp_data->marker[0] = '\0';
}
- if (scene->r.stamp & R_STAMP_TIME) {
+ if (use_dynamic && scene->r.stamp & R_STAMP_TIME) {
const short timecode_style = USER_TIMECODE_SMPTE_FULL;
BLI_timecode_string_from_time(text, sizeof(text), 0, FRA2TIME(scene->r.cfra), FPS, timecode_style);
- BLI_snprintf(stamp_data->time, sizeof(stamp_data->time), do_prefix ? "Timecode %s" : "%s", text);
+ SNPRINTF(stamp_data->time, do_prefix ? "Timecode %s" : "%s", text);
}
else {
stamp_data->time[0] = '\0';
}
- if (scene->r.stamp & R_STAMP_FRAME) {
+ if (use_dynamic && scene->r.stamp & R_STAMP_FRAME) {
char fmtstr[32];
int digits = 1;
if (scene->r.efra > 9)
digits = integer_digits_i(scene->r.efra);
- BLI_snprintf(fmtstr, sizeof(fmtstr), do_prefix ? "Frame %%0%di" : "%%0%di", digits);
- BLI_snprintf(stamp_data->frame, sizeof(stamp_data->frame), fmtstr, scene->r.cfra);
+ SNPRINTF(fmtstr, do_prefix ? "Frame %%0%di" : "%%0%di", digits);
+ SNPRINTF(stamp_data->frame, fmtstr, scene->r.cfra);
}
else {
stamp_data->frame[0] = '\0';
}
- if (scene->r.stamp & R_STAMP_CAMERA) {
- BLI_snprintf(stamp_data->camera, sizeof(stamp_data->camera), do_prefix ? "Camera %s" : "%s", camera ? camera->id.name + 2 : "<none>");
+ if (scene->r.stamp & R_STAMP_FRAME_RANGE) {
+ SNPRINTF(stamp_data->frame_range,
+ do_prefix ? "Frame Range %d:%d" : "%d:%d",
+ scene->r.sfra, scene->r.efra);
+ }
+ else {
+ stamp_data->frame_range[0] = '\0';
+ }
+
+ if (use_dynamic && scene->r.stamp & R_STAMP_CAMERA) {
+ SNPRINTF(stamp_data->camera, do_prefix ? "Camera %s" : "%s", camera ? camera->id.name + 2 : "<none>");
}
else {
stamp_data->camera[0] = '\0';
}
- if (scene->r.stamp & R_STAMP_CAMERALENS) {
+ if (use_dynamic && scene->r.stamp & R_STAMP_CAMERALENS) {
if (camera && camera->type == OB_CAMERA) {
- BLI_snprintf(text, sizeof(text), "%.2f", ((Camera *)camera->data)->lens);
+ SNPRINTF(text, "%.2f", ((Camera *)camera->data)->lens);
}
else {
- BLI_strncpy(text, "<none>", sizeof(text));
+ STRNCPY(text, "<none>");
}
- BLI_snprintf(stamp_data->cameralens, sizeof(stamp_data->cameralens), do_prefix ? "Lens %s" : "%s", text);
+ SNPRINTF(stamp_data->cameralens, do_prefix ? "Lens %s" : "%s", text);
}
else {
stamp_data->cameralens[0] = '\0';
}
if (scene->r.stamp & R_STAMP_SCENE) {
- BLI_snprintf(stamp_data->scene, sizeof(stamp_data->scene), do_prefix ? "Scene %s" : "%s", scene->id.name + 2);
+ SNPRINTF(stamp_data->scene, do_prefix ? "Scene %s" : "%s", scene->id.name + 2);
}
else {
stamp_data->scene[0] = '\0';
}
- if (scene->r.stamp & R_STAMP_SEQSTRIP) {
+ if (use_dynamic && scene->r.stamp & R_STAMP_SEQSTRIP) {
Sequence *seq = BKE_sequencer_foreground_frame_get(scene, scene->r.cfra);
- if (seq) BLI_strncpy(text, seq->name + 2, sizeof(text));
- else BLI_strncpy(text, "<none>", sizeof(text));
+ if (seq) STRNCPY(text, seq->name + 2);
+ else STRNCPY(text, "<none>");
- BLI_snprintf(stamp_data->strip, sizeof(stamp_data->strip), do_prefix ? "Strip %s" : "%s", text);
+ SNPRINTF(stamp_data->strip, do_prefix ? "Strip %s" : "%s", text);
}
else {
stamp_data->strip[0] = '\0';
@@ -1749,22 +1766,29 @@ static void stampdata(Scene *scene, Object *camera, StampData *stamp_data, int d
Render *re = RE_GetSceneRender(scene);
RenderStats *stats = re ? RE_GetStats(re) : NULL;
- if (stats && (scene->r.stamp & R_STAMP_RENDERTIME)) {
+ if (use_dynamic && stats && (scene->r.stamp & R_STAMP_RENDERTIME)) {
BLI_timecode_string_from_time_simple(text, sizeof(text), stats->lastframetime);
- BLI_snprintf(stamp_data->rendertime, sizeof(stamp_data->rendertime), do_prefix ? "RenderTime %s" : "%s", text);
+ SNPRINTF(stamp_data->rendertime, do_prefix ? "RenderTime %s" : "%s", text);
}
else {
stamp_data->rendertime[0] = '\0';
}
- if (stats && (scene->r.stamp & R_STAMP_MEMORY)) {
- BLI_snprintf(stamp_data->memory, sizeof(stamp_data->memory), do_prefix ? "Peak Memory %.2fM" : "%.2fM", stats->mem_peak);
+ if (use_dynamic && stats && (scene->r.stamp & R_STAMP_MEMORY)) {
+ SNPRINTF(stamp_data->memory, do_prefix ? "Peak Memory %.2fM" : "%.2fM", stats->mem_peak);
}
else {
stamp_data->memory[0] = '\0';
}
}
+ if (scene->r.stamp & R_STAMP_FRAME_RANGE) {
+ SNPRINTF(stamp_data->frame_range,
+ do_prefix ? "Frame Range %d:%d" : "%d:%d", scene->r.sfra, scene->r.efra);
+ }
+ else {
+ stamp_data->frame_range[0] = '\0';
+ }
}
/* Will always add prefix. */
@@ -1773,73 +1797,73 @@ static void stampdata_from_template(StampData *stamp_data,
const StampData *stamp_data_template)
{
if (scene->r.stamp & R_STAMP_FILENAME) {
- BLI_snprintf(stamp_data->file, sizeof(stamp_data->file), "File %s", stamp_data_template->file);
+ SNPRINTF(stamp_data->file, "File %s", stamp_data_template->file);
}
else {
stamp_data->file[0] = '\0';
}
if (scene->r.stamp & R_STAMP_NOTE) {
- BLI_snprintf(stamp_data->note, sizeof(stamp_data->note), "%s", stamp_data_template->note);
+ SNPRINTF(stamp_data->note, "%s", stamp_data_template->note);
}
else {
stamp_data->note[0] = '\0';
}
if (scene->r.stamp & R_STAMP_DATE) {
- BLI_snprintf(stamp_data->date, sizeof(stamp_data->date), "Date %s", stamp_data_template->date);
+ SNPRINTF(stamp_data->date, "Date %s", stamp_data_template->date);
}
else {
stamp_data->date[0] = '\0';
}
if (scene->r.stamp & R_STAMP_MARKER) {
- BLI_snprintf(stamp_data->marker, sizeof(stamp_data->marker), "Marker %s", stamp_data_template->marker);
+ SNPRINTF(stamp_data->marker, "Marker %s", stamp_data_template->marker);
}
else {
stamp_data->marker[0] = '\0';
}
if (scene->r.stamp & R_STAMP_TIME) {
- BLI_snprintf(stamp_data->time, sizeof(stamp_data->time), "Timecode %s", stamp_data_template->time);
+ SNPRINTF(stamp_data->time, "Timecode %s", stamp_data_template->time);
}
else {
stamp_data->time[0] = '\0';
}
if (scene->r.stamp & R_STAMP_FRAME) {
- BLI_snprintf(stamp_data->frame, sizeof(stamp_data->frame), "Frame %s", stamp_data_template->frame);
+ SNPRINTF(stamp_data->frame, "Frame %s", stamp_data_template->frame);
}
else {
stamp_data->frame[0] = '\0';
}
if (scene->r.stamp & R_STAMP_CAMERA) {
- BLI_snprintf(stamp_data->camera, sizeof(stamp_data->camera), "Camera %s", stamp_data_template->camera);
+ SNPRINTF(stamp_data->camera, "Camera %s", stamp_data_template->camera);
}
else {
stamp_data->camera[0] = '\0';
}
if (scene->r.stamp & R_STAMP_CAMERALENS) {
- BLI_snprintf(stamp_data->cameralens, sizeof(stamp_data->cameralens), "Lens %s", stamp_data_template->cameralens);
+ SNPRINTF(stamp_data->cameralens, "Lens %s", stamp_data_template->cameralens);
}
else {
stamp_data->cameralens[0] = '\0';
}
if (scene->r.stamp & R_STAMP_SCENE) {
- BLI_snprintf(stamp_data->scene, sizeof(stamp_data->scene), "Scene %s", stamp_data_template->scene);
+ SNPRINTF(stamp_data->scene, "Scene %s", stamp_data_template->scene);
}
else {
stamp_data->scene[0] = '\0';
}
if (scene->r.stamp & R_STAMP_SEQSTRIP) {
- BLI_snprintf(stamp_data->strip, sizeof(stamp_data->strip), "Strip %s", stamp_data_template->strip);
+ SNPRINTF(stamp_data->strip, "Strip %s", stamp_data_template->strip);
}
else {
stamp_data->strip[0] = '\0';
}
if (scene->r.stamp & R_STAMP_RENDERTIME) {
- BLI_snprintf(stamp_data->rendertime, sizeof(stamp_data->rendertime), "RenderTime %s", stamp_data_template->rendertime);
+ SNPRINTF(stamp_data->rendertime, "RenderTime %s", stamp_data_template->rendertime);
}
else {
stamp_data->rendertime[0] = '\0';
}
if (scene->r.stamp & R_STAMP_MEMORY) {
- BLI_snprintf(stamp_data->memory, sizeof(stamp_data->memory), "Peak Memory %s", stamp_data_template->memory);
+ SNPRINTF(stamp_data->memory, "Peak Memory %s", stamp_data_template->memory);
}
else {
stamp_data->memory[0] = '\0';
@@ -1885,7 +1909,7 @@ void BKE_image_stamp_buf(
display = IMB_colormanagement_display_get_named(display_device);
if (stamp_data_template == NULL) {
- stampdata(scene, camera, &stamp_data, (scene->r.stamp & R_STAMP_HIDE_LABELS) == 0);
+ stampdata(scene, camera, &stamp_data, (scene->r.stamp & R_STAMP_HIDE_LABELS) == 0, true);
}
else {
stampdata_from_template(&stamp_data, scene, stamp_data_template);
@@ -2106,13 +2130,28 @@ void BKE_render_result_stamp_info(Scene *scene, Object *camera, struct RenderRes
}
if (!allocate_only)
- stampdata(scene, camera, stamp_data, 0);
+ stampdata(scene, camera, stamp_data, 0, true);
if (!rr->stamp_data) {
rr->stamp_data = stamp_data;
}
}
+struct StampData *BKE_stamp_info_from_scene_static(Scene *scene)
+{
+ struct StampData *stamp_data;
+
+ if (!(scene && (scene->r.stamp & R_STAMP_ALL)))
+ return NULL;
+
+ /* Memory is allocated here (instead of by the caller) so that the caller
+ * doesn't have to know the size of the StampData struct. */
+ stamp_data = MEM_callocN(sizeof(StampData), __func__);
+ stampdata(scene, NULL, stamp_data, 0, false);
+
+ return stamp_data;
+}
+
void BKE_stamp_info_callback(void *data, struct StampData *stamp_data, StampCallback callback, bool noskip)
{
if ((callback == NULL) || (stamp_data == NULL)) {
@@ -2130,6 +2169,7 @@ void BKE_stamp_info_callback(void *data, struct StampData *stamp_data, StampCall
CALL(marker, "Marker");
CALL(time, "Time");
CALL(frame, "Frame");
+ CALL(frame_range, "FrameRange");
CALL(camera, "Camera");
CALL(cameralens, "Lens");
CALL(scene, "Scene");
@@ -2158,8 +2198,8 @@ void BKE_render_result_stamp_data(RenderResult *rr, const char *key, const char
stamp_data = rr->stamp_data;
StampDataCustomField *field = MEM_mallocN(sizeof(StampDataCustomField),
"StampData Custom Field");
- BLI_strncpy(field->key, key, sizeof(field->key));
- BLI_strncpy(field->value, value, sizeof(field->value));
+ STRNCPY(field->key, key);
+ STRNCPY(field->value, value);
BLI_addtail(&stamp_data->custom_fields, field);
}
@@ -2173,27 +2213,31 @@ void BKE_stamp_data_free(struct StampData *stamp_data)
}
/* wrap for callback only */
-static void metadata_change_field(void *data, const char *propname, char *propvalue, int UNUSED(len))
+static void metadata_set_field(void *data, const char *propname, char *propvalue, int UNUSED(len))
{
- IMB_metadata_change_field(data, propname, propvalue);
+ /* We know it is an ImBuf* because that's what we pass to BKE_stamp_info_callback. */
+ struct ImBuf *imbuf = data;
+ IMB_metadata_set_field(imbuf->metadata, propname, propvalue);
}
static void metadata_get_field(void *data, const char *propname, char *propvalue, int len)
{
- IMB_metadata_get_field(data, propname, propvalue, len);
+ /* We know it is an ImBuf* because that's what we pass to BKE_stamp_info_callback. */
+ struct ImBuf *imbuf = data;
+ IMB_metadata_get_field(imbuf->metadata, propname, propvalue, len);
}
void BKE_imbuf_stamp_info(RenderResult *rr, struct ImBuf *ibuf)
{
struct StampData *stamp_data = rr->stamp_data;
-
- BKE_stamp_info_callback(ibuf, stamp_data, metadata_change_field, false);
+ IMB_metadata_ensure(&ibuf->metadata);
+ BKE_stamp_info_callback(ibuf, stamp_data, metadata_set_field, false);
}
void BKE_stamp_info_from_imbuf(RenderResult *rr, struct ImBuf *ibuf)
{
struct StampData *stamp_data = rr->stamp_data;
-
+ IMB_metadata_ensure(&ibuf->metadata);
BKE_stamp_info_callback(ibuf, stamp_data, metadata_get_field, true);
}
@@ -2548,7 +2592,7 @@ void BKE_image_verify_viewer_views(const RenderData *rd, Image *ima, ImageUser *
bool do_reset;
const bool is_multiview = (rd->scemode & R_MULTIVIEW) != 0;
- BLI_lock_thread(LOCK_DRAW_IMAGE);
+ BLI_thread_lock(LOCK_DRAW_IMAGE);
if (!BKE_scene_multiview_is_stereo3d(rd))
iuser->flag &= ~IMA_SHOW_STEREO;
@@ -2582,7 +2626,7 @@ void BKE_image_verify_viewer_views(const RenderData *rd, Image *ima, ImageUser *
BLI_spin_unlock(&image_spin);
}
- BLI_unlock_thread(LOCK_DRAW_IMAGE);
+ BLI_thread_unlock(LOCK_DRAW_IMAGE);
}
void BKE_image_walk_all_users(const Main *mainp, void *customdata,
@@ -2740,7 +2784,7 @@ void BKE_image_signal(Image *ima, ImageUser *iuser, int signal)
if (BKE_image_has_packedfile(ima)) {
const int totfiles = image_num_files(ima);
- if (totfiles != BLI_listbase_count_ex(&ima->packedfiles, totfiles + 1)) {
+ if (totfiles != BLI_listbase_count_at_most(&ima->packedfiles, totfiles + 1)) {
/* in case there are new available files to be loaded */
image_free_packedfiles(ima);
BKE_image_packfiles(NULL, ima, ID_BLEND_PATH(G.main, &ima->id));
@@ -2895,7 +2939,7 @@ void BKE_image_multiview_index(Image *ima, ImageUser *iuser)
iuser->multi_index = iuser->multiview_eye;
}
else {
- if ((iuser->view < 0) || (iuser->view >= BLI_listbase_count_ex(&ima->views, iuser->view + 1))) {
+ if ((iuser->view < 0) || (iuser->view >= BLI_listbase_count_at_most(&ima->views, iuser->view + 1))) {
iuser->multi_index = iuser->view = 0;
}
else {
@@ -2958,7 +3002,7 @@ static void image_init_multilayer_multiview(Image *ima, RenderResult *rr)
if (rr) {
for (RenderView *rv = rr->views.first; rv; rv = rv->next) {
ImageView *iv = MEM_callocN(sizeof(ImageView), "Viewer Image View");
- BLI_strncpy(iv->name, rv->name, sizeof(iv->name));
+ STRNCPY(iv->name, rv->name);
BLI_addtail(&ima->views, iv);
}
}
@@ -3039,8 +3083,8 @@ static void image_add_view(Image *ima, const char *viewname, const char *filepat
ImageView *iv;
iv = MEM_mallocN(sizeof(ImageView), "Viewer Image View");
- BLI_strncpy(iv->name, viewname, sizeof(iv->name));
- BLI_strncpy(iv->filepath, filepath, sizeof(iv->filepath));
+ STRNCPY(iv->name, viewname);
+ STRNCPY(iv->filepath, filepath);
/* For stereo drawing we need to ensure:
* STEREO_LEFT_NAME == STEREO_LEFT_ID and
@@ -3362,7 +3406,7 @@ static ImBuf *image_load_movie_file(Image *ima, ImageUser *iuser, int frame)
const int totfiles = image_num_files(ima);
int i;
- if (totfiles != BLI_listbase_count_ex(&ima->anims, totfiles + 1)) {
+ if (totfiles != BLI_listbase_count_at_most(&ima->anims, totfiles + 1)) {
image_free_anims(ima);
for (i = 0; i < totfiles; i++) {
@@ -3490,7 +3534,7 @@ static ImBuf *load_image_single(
ImagePackedFile *imapf = MEM_mallocN(sizeof(ImagePackedFile), "Image Packefile");
BLI_addtail(&ima->packedfiles, imapf);
- BLI_strncpy(imapf->filepath, filepath, sizeof(imapf->filepath));
+ STRNCPY(imapf->filepath, filepath);
imapf->packedfile = newPackedFile(NULL, filepath, ID_BLEND_PATH(G.main, &ima->id));
}
}
@@ -3518,7 +3562,7 @@ static ImBuf *image_load_image_file(Image *ima, ImageUser *iuser, int cfra)
/* this should never happen, but just playing safe */
if (has_packed) {
- if (totfiles != BLI_listbase_count_ex(&ima->packedfiles, totfiles + 1)) {
+ if (totfiles != BLI_listbase_count_at_most(&ima->packedfiles, totfiles + 1)) {
image_free_packedfiles(ima);
has_packed = false;
}
@@ -3663,7 +3707,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
/* release is done in BKE_image_release_ibuf using r_lock */
if (from_render) {
- BLI_lock_thread(LOCK_VIEWER);
+ BLI_thread_lock(LOCK_VIEWER);
*r_lock = re;
rv = NULL;
}
@@ -3756,7 +3800,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
}
/* invalidate color managed buffers if render result changed */
- BLI_lock_thread(LOCK_COLORMANAGE);
+ BLI_thread_lock(LOCK_COLORMANAGE);
if (ibuf->x != rres.rectx || ibuf->y != rres.recty || ibuf->rect_float != rectf) {
ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;
}
@@ -3797,7 +3841,7 @@ static ImBuf *image_get_render_result(Image *ima, ImageUser *iuser, void **r_loc
ibuf->flags &= ~IB_zbuffloat;
}
- BLI_unlock_thread(LOCK_COLORMANAGE);
+ BLI_thread_unlock(LOCK_COLORMANAGE);
ibuf->dither = dither;
@@ -3999,7 +4043,7 @@ static ImBuf *image_acquire_ibuf(Image *ima, ImageUser *iuser, void **r_lock)
/* requires lock/unlock, otherwise don't return image */
if (r_lock) {
/* unlock in BKE_image_release_ibuf */
- BLI_lock_thread(LOCK_VIEWER);
+ BLI_thread_lock(LOCK_VIEWER);
*r_lock = ima;
/* XXX anim play for viewer nodes not yet supported */
@@ -4052,11 +4096,11 @@ void BKE_image_release_ibuf(Image *ima, ImBuf *ibuf, void *lock)
if (lock) {
/* for getting image during threaded render / compositing, need to release */
if (lock == ima) {
- BLI_unlock_thread(LOCK_VIEWER); /* viewer image */
+ BLI_thread_unlock(LOCK_VIEWER); /* viewer image */
}
else if (lock) {
RE_ReleaseResultImage(lock); /* render result */
- BLI_unlock_thread(LOCK_VIEWER); /* view image imbuf */
+ BLI_thread_unlock(LOCK_VIEWER); /* view image imbuf */
}
}
@@ -4645,7 +4689,7 @@ static void image_update_views_format(Image *ima, ImageUser *iuser)
for (srv = scene->r.views.first; srv; srv = srv->next) {
if (BKE_scene_multiview_is_render_view_active(&scene->r, srv)) {
char filepath[FILE_MAX];
- BLI_snprintf(filepath, sizeof(filepath), "%s%s%s", prefix, srv->suffix, ext);
+ SNPRINTF(filepath, "%s%s%s", prefix, srv->suffix, ext);
image_add_view(ima, srv->name, filepath);
}
}
@@ -4656,7 +4700,7 @@ static void image_update_views_format(Image *ima, ImageUser *iuser)
int file;
char str[FILE_MAX];
- BLI_strncpy(str, iv->filepath, sizeof(str));
+ STRNCPY(str, iv->filepath);
BLI_path_abs(str, G.main->name);
/* exists? */
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index 00cf40f06cd..fcbc25ebad5 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -1663,7 +1663,7 @@ static void nlastrips_to_animdata(ID *id, ListBase *strips)
/* trying to add to the current failed (no space),
* so add a new track to the stack, and add to that...
*/
- nlt = add_nlatrack(adt, NULL);
+ nlt = BKE_nlatrack_add(adt, NULL);
BKE_nlatrack_add_strip(nlt, strip);
}
diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c
index 931fc09d235..bf36c437d60 100644
--- a/source/blender/blenkernel/intern/lamp.c
+++ b/source/blender/blenkernel/intern/lamp.c
@@ -47,7 +47,6 @@
#include "BKE_animsys.h"
#include "BKE_colortools.h"
#include "BKE_icons.h"
-#include "BKE_global.h"
#include "BKE_lamp.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
diff --git a/source/blender/blenkernel/intern/lattice.c b/source/blender/blenkernel/intern/lattice.c
index d92d0d9edbf..c41ad78977e 100644
--- a/source/blender/blenkernel/intern/lattice.c
+++ b/source/blender/blenkernel/intern/lattice.c
@@ -54,7 +54,6 @@
#include "BKE_cdderivedmesh.h"
#include "BKE_curve.h"
#include "BKE_displist.h"
-#include "BKE_global.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
#include "BKE_library.h"
diff --git a/source/blender/blenkernel/intern/layer.c b/source/blender/blenkernel/intern/layer.c
index c6515d0c47a..50c7dc0c02f 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -57,10 +57,9 @@
#include "MEM_guardedalloc.h"
-#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
-
/* prototype */
struct EngineSettingsCB_Type;
+static void layer_collections_sync_flags(ListBase *layer_collections_dst, const ListBase *layer_collections_src);
static void layer_collection_free(ViewLayer *view_layer, LayerCollection *lc);
static void layer_collection_objects_populate(ViewLayer *view_layer, LayerCollection *lc, ListBase *objects);
static LayerCollection *layer_collection_add(ViewLayer *view_layer, LayerCollection *parent, SceneCollection *sc);
@@ -217,6 +216,8 @@ void BKE_view_layer_free_ex(ViewLayer *view_layer, const bool do_id_user)
MEM_freeN(view_layer->id_properties);
}
+ MEM_SAFE_FREE(view_layer->object_bases_array);
+
MEM_freeN(view_layer);
}
@@ -353,27 +354,95 @@ static SceneCollection *scene_collection_from_new_tree(
return NULL;
}
+static void layer_collection_sync_flags(
+ LayerCollection *layer_collection_dst,
+ const LayerCollection *layer_collection_src)
+{
+ layer_collection_dst->flag = layer_collection_src->flag;
+
+ if (layer_collection_dst->properties != NULL) {
+ IDP_FreeProperty(layer_collection_dst->properties);
+ MEM_SAFE_FREE(layer_collection_dst->properties);
+ }
+
+ if (layer_collection_src->properties != NULL) {
+ layer_collection_dst->properties = IDP_CopyProperty(layer_collection_src->properties);
+ }
+
+ layer_collections_sync_flags(&layer_collection_dst->layer_collections,
+ &layer_collection_src->layer_collections);
+}
+
static void layer_collections_sync_flags(ListBase *layer_collections_dst, const ListBase *layer_collections_src)
{
+ BLI_assert(BLI_listbase_count(layer_collections_dst) == BLI_listbase_count(layer_collections_src));
LayerCollection *layer_collection_dst = (LayerCollection *)layer_collections_dst->first;
const LayerCollection *layer_collection_src = (const LayerCollection *)layer_collections_src->first;
while (layer_collection_dst != NULL) {
- layer_collection_dst->flag = layer_collection_src->flag;
+ layer_collection_sync_flags(layer_collection_dst, layer_collection_src);
+ layer_collection_dst = layer_collection_dst->next;
+ layer_collection_src = layer_collection_src->next;
+ }
+}
- if (layer_collection_dst->properties != NULL) {
- IDP_FreeProperty(layer_collection_dst->properties);
- MEM_SAFE_FREE(layer_collection_dst->properties);
+static bool layer_collection_sync_if_match(
+ ListBase *lb,
+ const SceneCollection *scene_collection_dst,
+ const SceneCollection *scene_collection_src)
+{
+ for (LayerCollection *layer_collection = lb->first;
+ layer_collection;
+ layer_collection = layer_collection->next)
+ {
+ if (layer_collection->scene_collection == scene_collection_src) {
+ LayerCollection *layer_collection_dst =
+ BLI_findptr(
+ lb,
+ scene_collection_dst,
+ offsetof(LayerCollection, scene_collection));
+
+ if (layer_collection_dst != NULL) {
+ layer_collection_sync_flags(layer_collection_dst, layer_collection);
+ }
+ return true;
}
-
- if (layer_collection_src->properties != NULL) {
- layer_collection_dst->properties = IDP_CopyProperty(layer_collection_src->properties);
+ else {
+ if (layer_collection_sync_if_match(
+ &layer_collection->layer_collections,
+ scene_collection_dst,
+ scene_collection_src))
+ {
+ return true;
+ }
}
+ }
+ return false;
+}
- 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;
+/**
+ * Sync sibling collections across all view layers
+ *
+ * Make sure every linked instance of \a scene_collection_dst has the same values
+ * (flags, overrides, ...) as the corresponding scene_collection_src.
+ *
+ * \note expect scene_collection_dst to be scene_collection_src->next, and it also
+ * expects both collections to have the same ammount of sub-collections.
+ */
+void BKE_layer_collection_sync_flags(
+ ID *owner_id,
+ SceneCollection *scene_collection_dst,
+ SceneCollection *scene_collection_src)
+{
+ for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
+ for (LayerCollection *layer_collection = view_layer->layer_collections.first;
+ layer_collection;
+ layer_collection = layer_collection->next)
+ {
+ layer_collection_sync_if_match(
+ &layer_collection->layer_collections,
+ scene_collection_dst,
+ scene_collection_src);
+ }
}
}
@@ -436,6 +505,80 @@ void BKE_view_layer_copy_data(
view_layer_dst->basact = base_dst;
}
}
+
+ view_layer_dst->object_bases_array = NULL;
+}
+
+/**
+ * Find and return the ListBase of LayerCollection that has \a lc_child as one of its directly
+ * nested LayerCollection.
+ *
+ * \param lb_parent Initial ListBase of LayerCollection to look into recursively
+ * usually the view layer's collection list
+ */
+static ListBase *find_layer_collection_parent_list_base(ListBase *lb_parent, const LayerCollection *lc_child)
+{
+ for (LayerCollection *lc_nested = lb_parent->first; lc_nested; lc_nested = lc_nested->next) {
+ if (lc_nested == lc_child) {
+ return lb_parent;
+ }
+
+ ListBase *found = find_layer_collection_parent_list_base(&lc_nested->layer_collections, lc_child);
+ if (found != NULL) {
+ return found;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Makes a shallow copy of a LayerCollection
+ *
+ * Add a new collection in the same level as the old one (linking if necessary),
+ * and copy all the collection data across them.
+ */
+struct LayerCollection *BKE_layer_collection_duplicate(struct ID *owner_id, struct LayerCollection *layer_collection)
+{
+ SceneCollection *scene_collection, *scene_collection_new;
+
+ scene_collection = layer_collection->scene_collection;
+ scene_collection_new = BKE_collection_duplicate(owner_id, scene_collection);
+
+ LayerCollection *layer_collection_new = NULL;
+
+ /* If the original layer_collection was directly linked to the view layer
+ we need to link the new scene collection here as well. */
+ for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
+ if (BLI_findindex(&view_layer->layer_collections, layer_collection) != -1) {
+ layer_collection_new = BKE_collection_link(view_layer, scene_collection_new);
+ layer_collection_sync_flags(layer_collection_new, layer_collection);
+
+ if (layer_collection_new != layer_collection->next) {
+ BLI_remlink(&view_layer->layer_collections, layer_collection_new);
+ BLI_insertlinkafter(&view_layer->layer_collections, layer_collection, layer_collection_new);
+ }
+ break;
+ }
+ }
+
+ /* Otherwise just try to find the corresponding layer collection to return it back. */
+ if (layer_collection_new == NULL) {
+ for (ViewLayer *view_layer = BKE_view_layer_first_from_id(owner_id); view_layer; view_layer = view_layer->next) {
+ ListBase *layer_collections_parent;
+ layer_collections_parent = find_layer_collection_parent_list_base(
+ &view_layer->layer_collections,
+ layer_collection);
+ if (layer_collections_parent != NULL) {
+ layer_collection_new = BLI_findptr(
+ layer_collections_parent,
+ scene_collection_new,
+ offsetof(LayerCollection, scene_collection));
+ break;
+ }
+ }
+ }
+ return layer_collection_new;
}
static void view_layer_object_base_unref(ViewLayer *view_layer, Base *base)
@@ -988,6 +1131,34 @@ void BKE_layer_collection_resync(const ID *owner_id, const SceneCollection *sc)
/* ---------------------------------------------------------------------- */
/**
+ * Select all the objects of this layer collection
+ *
+ * It also select the objects that are in nested collections.
+ * \note Recursive
+ */
+void BKE_layer_collection_objects_select(struct LayerCollection *layer_collection)
+{
+ if ((layer_collection->flag & COLLECTION_DISABLED) ||
+ ((layer_collection->flag & COLLECTION_SELECTABLE) == 0))
+ {
+ return;
+ }
+
+ for (LinkData *link = layer_collection->object_bases.first; link; link = link->next) {
+ Base *base = link->data;
+ if (base->flag & BASE_SELECTABLED) {
+ base->flag |= BASE_SELECTED;
+ }
+ }
+
+ for (LayerCollection *iter = layer_collection->layer_collections.first; iter; iter = iter->next) {
+ BKE_layer_collection_objects_select(iter);
+ }
+}
+
+/* ---------------------------------------------------------------------- */
+
+/**
* Link a collection to a renderlayer
* The collection needs to be created separately
*/
@@ -1115,16 +1286,29 @@ static LayerCollection *layer_collection_add(ViewLayer *view_layer, LayerCollect
/* ---------------------------------------------------------------------- */
/**
- * See if render layer has the scene collection linked directly, or indirectly (nested)
+ * Return the first matching LayerCollection in the ViewLayer for the SceneCollection.
*/
-bool BKE_view_layer_has_collection(ViewLayer *view_layer, const SceneCollection *sc)
+LayerCollection *BKE_layer_collection_first_from_scene_collection(ViewLayer *view_layer, const SceneCollection *scene_collection)
{
- for (LayerCollection *lc = view_layer->layer_collections.first; lc; lc = lc->next) {
- if (find_layer_collection_by_scene_collection(lc, sc) != NULL) {
- return true;
+ for (LayerCollection *layer_collection = view_layer->layer_collections.first;
+ layer_collection != NULL;
+ layer_collection = layer_collection->next)
+ {
+ LayerCollection *found = find_layer_collection_by_scene_collection(layer_collection, scene_collection);
+
+ if (found != NULL) {
+ return found;
}
}
- return false;
+ return NULL;
+}
+
+/**
+ * See if view layer has the scene collection linked directly, or indirectly (nested)
+ */
+bool BKE_view_layer_has_collection(ViewLayer *view_layer, const SceneCollection *scene_collection)
+{
+ return BKE_layer_collection_first_from_scene_collection(view_layer, scene_collection) != NULL;
}
/**
@@ -1968,12 +2152,13 @@ void BKE_visible_bases_iterator_end(BLI_Iterator *UNUSED(iter))
void BKE_renderable_objects_iterator_begin(BLI_Iterator *iter, void *data_in)
{
- ObjectsRenderableIteratorData *data = data_in;
+ struct ObjectsRenderableIteratorData *data = data_in;
+ /* Tag objects to prevent going over the same object twice. */
for (Scene *scene = data->scene; scene; scene = scene->set) {
for (ViewLayer *view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
- base->object->id.flag |= LIB_TAG_DOIT;
+ base->object->id.flag |= LIB_TAG_DOIT;
}
}
}
@@ -1981,8 +2166,8 @@ void BKE_renderable_objects_iterator_begin(BLI_Iterator *iter, void *data_in)
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->base_temp.next = view_layer->object_bases.first;
+ data->iter.base = &data->base_temp;
data->iter.set = NULL;
@@ -1992,18 +2177,27 @@ void BKE_renderable_objects_iterator_begin(BLI_Iterator *iter, void *data_in)
void BKE_renderable_objects_iterator_next(BLI_Iterator *iter)
{
- ObjectsRenderableIteratorData *data = iter->data;
+ /* Set it early in case we need to exit and we are running from within a loop. */
+ iter->skip = true;
+
+ struct ObjectsRenderableIteratorData *data = iter->data;
Base *base = data->iter.base->next;
/* There is still a base in the current scene layer. */
if (base != NULL) {
Object *ob = base->object;
- iter->current = ob;
+ /* We need to set the iter.base even if the rest fail otherwise
+ * we keep checking the exactly same base over and over again. */
data->iter.base = base;
- if ((base->flag & BASE_VISIBLED) == 0) {
- BKE_renderable_objects_iterator_next(iter);
+ if (ob->id.flag & LIB_TAG_DOIT) {
+ ob->id.flag &= ~LIB_TAG_DOIT;
+
+ if ((base->flag & BASE_VISIBLED) != 0) {
+ iter->skip = false;
+ iter->current = ob;
+ }
}
return;
}
@@ -2013,30 +2207,23 @@ void BKE_renderable_objects_iterator_next(BLI_Iterator *iter)
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);
+ data->base_temp.next = view_layer->object_bases.first;
+ data->iter.base = &data->base_temp;
return;
}
}
/* Setup the "set" for the next iteration. */
- Scene scene = {.set = data->scene};
- data->iter.set = &scene;
- BKE_renderable_objects_iterator_next(iter);
+ data->scene_temp.set = data->scene;
+ data->iter.set = &data->scene_temp;
return;
}
/* Look for an object in the next set. */
while ((data->iter.set = data->iter.set->set)) {
ViewLayer *view_layer = BKE_view_layer_from_scene_get(data->iter.set);
-
- Base base_iter = {(Base *)view_layer->object_bases.first, NULL};
- data->iter.base = &base_iter;
-
- BKE_renderable_objects_iterator_next(iter);
+ data->base_temp.next = view_layer->object_bases.first;
+ data->iter.base = &data->base_temp;
return;
}
@@ -2070,10 +2257,9 @@ static void idproperty_reset(IDProperty **props, IDProperty *props_ref)
}
}
-void BKE_layer_eval_layer_collection_pre(const struct EvaluationContext *UNUSED(eval_ctx),
- ID *owner_id, ViewLayer *view_layer)
+static void layer_eval_layer_collection_pre(ID *owner_id, ViewLayer *view_layer)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, view_layer->name, view_layer);
+ DEG_debug_print_eval(__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) {
@@ -2113,18 +2299,21 @@ static bool layer_collection_visible_get(const EvaluationContext *eval_ctx, Laye
}
}
-void BKE_layer_eval_layer_collection(const EvaluationContext *eval_ctx,
- LayerCollection *layer_collection,
- LayerCollection *parent_layer_collection)
+static void 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] : "");
+ if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) {
+ /* TODO)sergey): Try to make it more generic and handled by depsgraph messaging. */
+ printf("%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 */
@@ -2170,18 +2359,65 @@ void BKE_layer_eval_layer_collection(const EvaluationContext *eval_ctx,
}
}
-void BKE_layer_eval_layer_collection_post(const struct EvaluationContext *UNUSED(eval_ctx),
- ViewLayer *view_layer)
+static void layer_eval_layer_collection_post(ViewLayer *view_layer)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, view_layer->name, view_layer);
- /* if base is not selectabled, clear select */
+ DEG_debug_print_eval(__func__, view_layer->name, view_layer);
+ /* Create array of bases, for fast index-based lookup. */
+ const int num_object_bases = BLI_listbase_count(&view_layer->object_bases);
+ MEM_SAFE_FREE(view_layer->object_bases_array);
+ view_layer->object_bases_array = MEM_malloc_arrayN(
+ num_object_bases, sizeof(Base *), "view_layer->object_bases_array");
+ int base_index = 0;
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
+ /* if base is not selectabled, clear select. */
if ((base->flag & BASE_SELECTABLED) == 0) {
base->flag &= ~BASE_SELECTED;
}
+ /* Store base in the array. */
+ view_layer->object_bases_array[base_index++] = base;
+ }
+}
+
+static void layer_eval_collections_recurse(const EvaluationContext *eval_ctx,
+ ListBase *layer_collections,
+ LayerCollection *parent_layer_collection)
+{
+ for (LayerCollection *layer_collection = layer_collections->first;
+ layer_collection != NULL;
+ layer_collection = layer_collection->next)
+ {
+ layer_eval_layer_collection(eval_ctx,
+ layer_collection,
+ parent_layer_collection);
+ layer_eval_collections_recurse(eval_ctx,
+ &layer_collection->layer_collections,
+ layer_collection);
}
}
+void BKE_layer_eval_view_layer(const struct EvaluationContext *eval_ctx,
+ struct ID *owner_id,
+ ViewLayer *view_layer)
+{
+ layer_eval_layer_collection_pre(owner_id, view_layer);
+ layer_eval_collections_recurse(eval_ctx,
+ &view_layer->layer_collections,
+ NULL);
+ layer_eval_layer_collection_post(view_layer);
+}
+
+void BKE_layer_eval_view_layer_indexed(const struct EvaluationContext *eval_ctx,
+ struct ID *owner_id,
+ int view_layer_index)
+{
+ BLI_assert(GS(owner_id->name) == ID_SCE);
+ BLI_assert(view_layer_index >= 0);
+ Scene *scene = (Scene *)owner_id;
+ ViewLayer *view_layer = BLI_findlink(&scene->view_layers, view_layer_index);
+ BLI_assert(view_layer != NULL);
+ BKE_layer_eval_view_layer(eval_ctx, owner_id, view_layer);
+}
+
/**
* Free any static allocated memory.
*/
diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c
index 75a288092d8..f7f0991238f 100644
--- a/source/blender/blenkernel/intern/library.c
+++ b/source/blender/blenkernel/intern/library.c
@@ -849,6 +849,7 @@ void BKE_libblock_management_main_add(Main *bmain, void *idv)
new_id(lb, id, NULL);
/* alphabetic insertion: is in new_id */
id->tag &= ~(LIB_TAG_NO_MAIN | LIB_TAG_NO_USER_REFCOUNT);
+ bmain->is_memfile_undo_written = false;
BKE_main_unlock(bmain);
}
@@ -868,6 +869,7 @@ void BKE_libblock_management_main_remove(Main *bmain, void *idv)
BKE_main_lock(bmain);
BLI_remlink(lb, id);
id->tag |= LIB_TAG_NO_MAIN;
+ bmain->is_memfile_undo_written = false;
BKE_main_unlock(bmain);
}
@@ -1244,6 +1246,7 @@ void *BKE_libblock_alloc(Main *bmain, short type, const char *name, const int fl
BKE_main_lock(bmain);
BLI_addtail(lb, id);
new_id(lb, id, name);
+ bmain->is_memfile_undo_written = false;
/* alphabetic insertion: is in new_id */
BKE_main_unlock(bmain);
@@ -2144,7 +2147,7 @@ void BKE_library_make_local(
GSet *loop_tags = BLI_gset_ptr_new(__func__);
for (LinkNode *it = todo_ids; it; it = it->next) {
library_make_local_copying_check(it->link, loop_tags, bmain->relations, done_ids);
- BLI_assert(BLI_gset_size(loop_tags) == 0);
+ BLI_assert(BLI_gset_len(loop_tags) == 0);
}
BLI_gset_free(loop_tags, NULL);
BLI_gset_free(done_ids, NULL);
diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c
index da765ca45af..953db6f3cb0 100644
--- a/source/blender/blenkernel/intern/library_query.c
+++ b/source/blender/blenkernel/intern/library_query.c
@@ -52,7 +52,7 @@
#include "DNA_movieclip_types.h"
#include "DNA_mask_types.h"
#include "DNA_node_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_lightprobe_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
@@ -422,10 +422,6 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
/* nodetree **are owned by IDs**, treat them as mere sub-data and not real ID! */
library_foreach_ID_as_subdata_link((ID **)&scene->nodetree, callback, user_data, flag, &data);
}
- /* DO NOT handle scene->basact here, it's doubling with the loop over whole scene->base later,
- * since basact is just a pointer to one of those items. */
- CALLBACK_INVOKE(scene->obedit, IDWALK_CB_NOP);
-
if (scene->ed) {
Sequence *seq;
SEQP_BEGIN(scene->ed, seq)
@@ -445,13 +441,13 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
CALLBACK_INVOKE(scene->gpd, IDWALK_CB_USER);
- FOREACH_SCENE_COLLECTION(scene, sc)
+ FOREACH_SCENE_COLLECTION_BEGIN(scene, sc)
{
for (LinkData *link = sc->objects.first; link; link = link->next) {
CALLBACK_INVOKE_ID(link->data, IDWALK_CB_USER);
}
}
- FOREACH_SCENE_COLLECTION_END
+ FOREACH_SCENE_COLLECTION_END;
ViewLayer *view_layer;
for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) {
@@ -685,6 +681,9 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
}
CALLBACK_INVOKE(material->group, IDWALK_CB_USER);
CALLBACK_INVOKE(material->edit_image, IDWALK_CB_USER);
+ if (material->texpaintslot != NULL) {
+ CALLBACK_INVOKE(material->texpaintslot->ima, IDWALK_CB_NOP);
+ }
break;
}
@@ -777,7 +776,7 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call
case ID_GR:
{
Group *group = (Group *) id;
- FOREACH_GROUP_BASE(group, base)
+ FOREACH_GROUP_BASE_BEGIN(group, base)
{
CALLBACK_INVOKE(base->object, IDWALK_CB_USER_ONE);
}
diff --git a/source/blender/blenkernel/intern/library_remap.c b/source/blender/blenkernel/intern/library_remap.c
index 87e45990a6c..2c6df24f762 100644
--- a/source/blender/blenkernel/intern/library_remap.c
+++ b/source/blender/blenkernel/intern/library_remap.c
@@ -281,6 +281,26 @@ static void libblock_remap_data_preprocess_scene_object_unlink(
}
}
+static void libblock_remap_data_preprocess_group_unlink(
+ IDRemap *r_id_remap_data, Object *ob, const bool skip_indirect, const bool is_indirect)
+{
+ Main *bmain = r_id_remap_data->bmain;
+ for (Group *group = bmain->group.first; group; group = group->id.next) {
+ if (BKE_group_object_exists(group, ob)) {
+ if (skip_indirect && is_indirect) {
+ r_id_remap_data->skipped_indirect++;
+ r_id_remap_data->skipped_refcounted++;
+ }
+ else {
+ BKE_collections_object_remove(bmain, &group->id, ob, false);
+ if (!is_indirect) {
+ r_id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT;
+ }
+ }
+ }
+ }
+}
+
static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
{
switch (GS(r_id_remap_data->id->name)) {
@@ -295,19 +315,24 @@ static void libblock_remap_data_preprocess(IDRemap *r_id_remap_data)
/* In case we are unlinking... */
if (!r_id_remap_data->old_id) {
/* ... everything from scene. */
- FOREACH_SCENE_OBJECT(sce, ob_iter)
+ FOREACH_SCENE_OBJECT_BEGIN(sce, ob_iter)
{
libblock_remap_data_preprocess_scene_object_unlink(
r_id_remap_data, sce, ob_iter, skip_indirect, is_indirect);
+ libblock_remap_data_preprocess_group_unlink(
+ r_id_remap_data, ob_iter, skip_indirect, is_indirect);
}
- FOREACH_SCENE_OBJECT_END
+ 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;
libblock_remap_data_preprocess_scene_object_unlink(
r_id_remap_data, sce, old_ob, skip_indirect, is_indirect);
+ libblock_remap_data_preprocess_group_unlink(
+ r_id_remap_data, old_ob, skip_indirect, is_indirect);
}
+
}
break;
}
@@ -368,7 +393,7 @@ 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...). */
- FOREACH_SCENE_OBJECT(sce, ob)
+ FOREACH_SCENE_OBJECT_BEGIN(sce, ob)
{
if (ob->flag & OB_FROMGROUP) {
Group *grp = BKE_group_object_find(NULL, ob);
@@ -382,7 +407,7 @@ static void libblock_remap_data_postprocess_group_scene_unlink(Main *UNUSED(bmai
}
}
}
- FOREACH_SCENE_OBJECT_END
+ FOREACH_SCENE_OBJECT_END;
}
static void libblock_remap_data_postprocess_obdata_relink(Main *UNUSED(bmain), Object *ob, ID *new_id)
diff --git a/source/blender/blenkernel/intern/linestyle.c b/source/blender/blenkernel/intern/linestyle.c
index 2fc4c81cb0b..dd1315fe3fa 100644
--- a/source/blender/blenkernel/intern/linestyle.c
+++ b/source/blender/blenkernel/intern/linestyle.c
@@ -47,7 +47,6 @@
#include "BKE_colorband.h"
#include "BKE_context.h"
#include "BKE_freestyle.h"
-#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_linestyle.h"
#include "BKE_node.h"
diff --git a/source/blender/blenkernel/intern/mask.c b/source/blender/blenkernel/intern/mask.c
index 3256c16e2f6..ba5a6a25048 100644
--- a/source/blender/blenkernel/intern/mask.c
+++ b/source/blender/blenkernel/intern/mask.c
@@ -51,7 +51,7 @@
#include "BKE_animsys.h"
#include "BKE_curve.h"
-#include "BKE_global.h"
+
#include "BKE_library.h"
#include "BKE_main.h"
#include "BKE_mask.h"
diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c
index f60d87f2464..61c136d2c4f 100644
--- a/source/blender/blenkernel/intern/mask_evaluate.c
+++ b/source/blender/blenkernel/intern/mask_evaluate.c
@@ -42,12 +42,10 @@
#include "DNA_mask_types.h"
#include "BKE_curve.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)
{
float max_segment = 0.01f;
@@ -898,11 +896,9 @@ void BKE_mask_layer_evaluate_deform(MaskLayer *masklay, const float ctime)
}
}
-#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
-
void BKE_mask_eval_animation(struct EvaluationContext *eval_ctx, Mask *mask)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, mask->id.name, mask);
+ DEG_debug_print_eval(__func__, mask->id.name, mask);
for (MaskLayer *mask_layer = mask->masklayers.first;
mask_layer != NULL;
mask_layer = mask_layer->next)
@@ -913,7 +909,7 @@ void BKE_mask_eval_animation(struct EvaluationContext *eval_ctx, Mask *mask)
void BKE_mask_eval_update(struct EvaluationContext *eval_ctx, Mask *mask)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, mask->id.name, mask);
+ DEG_debug_print_eval(__func__, mask->id.name, mask);
for (MaskLayer *mask_layer = mask->masklayers.first;
mask_layer != NULL;
mask_layer = mask_layer->next)
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 7235aa0aaf6..2971f56c775 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -72,6 +72,7 @@
#include "BKE_editmesh.h"
#include "BKE_font.h"
+#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
#include "GPU_material.h"
@@ -98,6 +99,9 @@ void BKE_material_free(Material *ma)
MEM_SAFE_FREE(ma->ramp_col);
MEM_SAFE_FREE(ma->ramp_spec);
+
+ /* Free gpu material before the ntree */
+ GPU_material_free(&ma->gpumaterial);
/* is no lib link block, but material extension */
if (ma->nodetree) {
@@ -108,8 +112,6 @@ void BKE_material_free(Material *ma)
MEM_SAFE_FREE(ma->texpaintslot);
- GPU_material_free(&ma->gpumaterial);
-
BKE_icon_id_delete((ID *)ma);
BKE_previewimg_free(&ma->preview);
}
@@ -259,6 +261,10 @@ void BKE_material_copy_data(Main *bmain, Material *ma_dst, const Material *ma_sr
ma_dst->preview = NULL;
}
+ if (ma_src->texpaintslot != NULL) {
+ ma_dst->texpaintslot = MEM_dupallocN(ma_src->texpaintslot);
+ }
+
BLI_listbase_clear(&ma_dst->gpumaterial);
/* TODO Duplicate Engine Settings and set runtime to NULL */
@@ -1709,13 +1715,14 @@ void paste_matcopybuf(Material *ma)
MEM_freeN(mtex);
}
+ /* Free gpu material before the ntree */
+ GPU_material_free(&ma->gpumaterial);
+
if (ma->nodetree) {
ntreeFreeTree(ma->nodetree);
MEM_freeN(ma->nodetree);
}
- GPU_material_free(&ma->gpumaterial);
-
id = (ma->id);
memcpy(ma, &matcopybuf, sizeof(Material));
(ma->id) = id;
@@ -1772,9 +1779,7 @@ bool BKE_object_material_edit_image_set(Object *ob, short mat_nr, Image *image)
void BKE_material_eval(const struct EvaluationContext *UNUSED(eval_ctx), Material *material)
{
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s on %s (%p)\n", __func__, material->id.name, material);
- }
+ DEG_debug_print_eval(__func__, material->id.name, material);
if ((BLI_listbase_is_empty(&material->gpumaterial) == false)) {
GPU_material_uniform_buffer_tag_dirty(&material->gpumaterial);
}
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index 5a0ac86823f..cc801b2d8c3 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -549,9 +549,9 @@ void BKE_mball_eval_geometry(const struct EvaluationContext *UNUSED(eval_ctx),
/* 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])
+void BKE_mball_element_calc_scale_xform(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);
diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c
index 3217c234718..af92422f4c3 100644
--- a/source/blender/blenkernel/intern/mesh.c
+++ b/source/blender/blenkernel/intern/mesh.c
@@ -66,6 +66,7 @@
#include "BKE_editmesh.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
/* Define for cases when you want extra validation of mesh
* after certain modifications.
@@ -1044,7 +1045,7 @@ static void make_edges_mdata_extend(MEdge **r_alledge, int *r_totedge,
BKE_mesh_poly_edgehash_insert(eh, mp, mloop + mp->loopstart);
}
- totedge_new = BLI_edgehash_size(eh);
+ totedge_new = BLI_edgehash_len(eh);
#ifdef DEBUG
/* ensure that theres no overlap! */
@@ -2205,6 +2206,8 @@ static int split_faces_prepare_new_verts(
MLoop *ml = mloop;
MLoopNorSpace **lnor_space = lnors_spacearr->lspacearr;
+ BLI_assert(lnors_spacearr->data_type == MLNOR_SPACEARR_LOOP_INDEX);
+
for (int loop_idx = 0; loop_idx < num_loops; loop_idx++, ml++, lnor_space++) {
if (!BLI_BITMAP_TEST(done_loops, loop_idx)) {
const int vert_idx = ml->v;
@@ -2214,7 +2217,15 @@ static int split_faces_prepare_new_verts(
BLI_assert(*lnor_space);
- if ((*lnor_space)->loops) {
+ if ((*lnor_space)->flags & MLNOR_SPACE_IS_SINGLE) {
+ /* Single loop in this fan... */
+ BLI_assert(GET_INT_FROM_POINTER((*lnor_space)->loops) == loop_idx);
+ BLI_BITMAP_ENABLE(done_loops, loop_idx);
+ if (vert_used) {
+ ml->v = new_vert_idx;
+ }
+ }
+ else {
for (LinkNode *lnode = (*lnor_space)->loops; lnode; lnode = lnode->next) {
const int ml_fan_idx = GET_INT_FROM_POINTER(lnode->link);
BLI_BITMAP_ENABLE(done_loops, ml_fan_idx);
@@ -2223,13 +2234,6 @@ static int split_faces_prepare_new_verts(
}
}
}
- else {
- /* Single loop in this fan... */
- BLI_BITMAP_ENABLE(done_loops, loop_idx);
- if (vert_used) {
- ml->v = new_vert_idx;
- }
- }
if (!vert_used) {
BLI_BITMAP_ENABLE(verts_used, vert_idx);
@@ -2425,12 +2429,12 @@ void BKE_mesh_split_faces(Mesh *mesh, bool free_loop_normals)
/* settings: 1 - preview, 2 - render */
Mesh *BKE_mesh_new_from_object(
const EvaluationContext *eval_ctx, Main *bmain, Scene *sce, Object *ob,
- int apply_modifiers, int settings, int calc_tessface, int calc_undeformed)
+ int apply_modifiers, int calc_tessface, int calc_undeformed)
{
Mesh *tmpmesh;
Curve *tmpcu = NULL, *copycu;
int i;
- const bool render = (settings == eModifierMode_Render);
+ const bool render = (DEG_get_mode(eval_ctx->depsgraph) == DAG_EVAL_RENDER);
const bool cage = !apply_modifiers;
bool do_mat_id_data_us = true;
@@ -2466,7 +2470,7 @@ Mesh *BKE_mesh_new_from_object(
/* if getting the original caged mesh, delete object modifiers */
if (cage)
- BKE_object_free_modifiers(tmpobj);
+ BKE_object_free_modifiers(tmpobj, 0);
/* copies the data */
copycu = tmpobj->data = BKE_curve_copy(bmain, (Curve *) ob->data);
@@ -2667,9 +2671,7 @@ Mesh *BKE_mesh_new_from_object(
void BKE_mesh_eval_geometry(const EvaluationContext *UNUSED(eval_ctx),
Mesh *mesh)
{
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s on %s\n", __func__, mesh->id.name);
- }
+ DEG_debug_print_eval(__func__, mesh->id.name, mesh);
if (mesh->bb == NULL || (mesh->bb->flag & BOUNDBOX_DIRTY)) {
BKE_mesh_texspace_calc(mesh);
}
diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c
index 00d1b29caf8..01cee2a19ff 100644
--- a/source/blender/blenkernel/intern/mesh_evaluate.c
+++ b/source/blender/blenkernel/intern/mesh_evaluate.c
@@ -43,7 +43,7 @@
#include "BLI_math.h"
#include "BLI_edgehash.h"
#include "BLI_bitmap.h"
-#include "BLI_polyfill2d.h"
+#include "BLI_polyfill_2d.h"
#include "BLI_linklist.h"
#include "BLI_linklist_stack.h"
#include "BLI_alloca.h"
@@ -253,16 +253,6 @@ static void mesh_calc_normals_poly_prepare_cb(
}
}
-static void mesh_calc_normals_poly_accum_cb(
- void *__restrict userdata,
- const int lidx,
- const ParallelRangeTLS *__restrict UNUSED(tls))
-{
- MeshCalcNormalsData *data = userdata;
-
- add_v3_v3(data->vnors[data->mloop[lidx].v], data->lnors_weighted[lidx]);
-}
-
static void mesh_calc_normals_poly_finalize_cb(
void *__restrict userdata,
const int vidx,
@@ -327,7 +317,11 @@ void BKE_mesh_calc_normals_poly(
BLI_task_parallel_range(0, numPolys, &data, mesh_calc_normals_poly_prepare_cb, &settings);
/* Actually accumulate weighted loop normals into vertex ones. */
- BLI_task_parallel_range(0, numLoops, &data, mesh_calc_normals_poly_accum_cb, &settings);
+ /* Unfortunately, not possible to thread that (not in a reasonable, totally lock- and barrier-free fashion),
+ * since several loops will point to the same vertex... */
+ for (int lidx = 0; lidx < numLoops; lidx++) {
+ add_v3_v3(vnors[mloop[lidx].v], data.lnors_weighted[lidx]);
+ }
/* Normalize and validate computed vertex normals. */
BLI_task_parallel_range(0, numVerts, &data, mesh_calc_normals_poly_finalize_cb, &settings);
@@ -450,7 +444,7 @@ cleanup:
MEM_freeN(fnors);
}
-void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, const int numLoops)
+void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, const int numLoops, const char data_type)
{
if (!(lnors_spacearr->lspacearr && lnors_spacearr->loops_pool)) {
MemArena *mem;
@@ -462,6 +456,8 @@ void BKE_lnor_spacearr_init(MLoopNorSpaceArray *lnors_spacearr, const int numLoo
lnors_spacearr->lspacearr = BLI_memarena_calloc(mem, sizeof(MLoopNorSpace *) * (size_t)numLoops);
lnors_spacearr->loops_pool = BLI_memarena_alloc(mem, sizeof(LinkNode) * (size_t)numLoops);
}
+ BLI_assert(ELEM(data_type, MLNOR_SPACEARR_BMLOOP_PTR, MLNOR_SPACEARR_LOOP_INDEX));
+ lnors_spacearr->data_type = data_type;
}
void BKE_lnor_spacearr_clear(MLoopNorSpaceArray *lnors_spacearr)
@@ -555,12 +551,32 @@ void BKE_lnor_space_define(MLoopNorSpace *lnor_space, const float lnor[3],
}
}
-void BKE_lnor_space_add_loop(MLoopNorSpaceArray *lnors_spacearr, MLoopNorSpace *lnor_space, const int ml_index,
- const bool do_add_loop)
+/**
+ * Add a new given loop to given lnor_space.
+ * Depending on \a lnor_space->data_type, we expect \a bm_loop to be a pointer to BMLoop struct (in case of BMLOOP_PTR),
+ * or NULL (in case of LOOP_INDEX), loop index is then stored in pointer.
+ * If \a is_single is set, the BMLoop or loop index is directly stored in \a lnor_space->loops pointer (since there
+ * is only one loop in this fan), else it is added to the linked list of loops in the fan.
+ */
+void BKE_lnor_space_add_loop(
+ MLoopNorSpaceArray *lnors_spacearr, MLoopNorSpace *lnor_space,
+ const int ml_index, void *bm_loop, const bool is_single)
{
+ BLI_assert((lnors_spacearr->data_type == MLNOR_SPACEARR_LOOP_INDEX && bm_loop == NULL) ||
+ (lnors_spacearr->data_type == MLNOR_SPACEARR_BMLOOP_PTR && bm_loop != NULL));
+
lnors_spacearr->lspacearr[ml_index] = lnor_space;
- if (do_add_loop) {
- BLI_linklist_prepend_nlink(&lnor_space->loops, SET_INT_IN_POINTER(ml_index), &lnors_spacearr->loops_pool[ml_index]);
+ if (bm_loop == NULL) {
+ bm_loop = SET_INT_IN_POINTER(ml_index);
+ }
+ if (is_single) {
+ BLI_assert(lnor_space->loops == NULL);
+ lnor_space->flags |= MLNOR_SPACE_IS_SINGLE;
+ lnor_space->loops = bm_loop;
+ }
+ else {
+ BLI_assert((lnor_space->flags & MLNOR_SPACE_IS_SINGLE) == 0);
+ BLI_linklist_prepend_nlink(&lnor_space->loops, bm_loop, &lnors_spacearr->loops_pool[ml_index]);
}
}
@@ -686,10 +702,11 @@ typedef struct LoopSplitTaskDataCommon {
const MEdge *medges;
const MLoop *mloops;
const MPoly *mpolys;
- const int (*edge_to_loops)[2];
- const int *loop_to_poly;
+ int (*edge_to_loops)[2];
+ int *loop_to_poly;
const float (*polynors)[3];
+ int numEdges;
int numLoops;
int numPolys;
} LoopSplitTaskDataCommon;
@@ -699,7 +716,154 @@ typedef struct LoopSplitTaskDataCommon {
/* See comment about edge_to_loops below. */
#define IS_EDGE_SHARP(_e2l) (ELEM((_e2l)[1], INDEX_UNSET, INDEX_INVALID))
-static void loop_manifold_fan_around_vert_next(
+static void mesh_edges_sharp_tag(
+ LoopSplitTaskDataCommon *data,
+ const bool check_angle, const float split_angle, const bool do_sharp_edges_tag)
+{
+ const MVert *mverts = data->mverts;
+ const MEdge *medges = data->medges;
+ const MLoop *mloops = data->mloops;
+
+ const MPoly *mpolys = data->mpolys;
+
+ const int numEdges = data->numEdges;
+ const int numPolys = data->numPolys;
+
+ float (*loopnors)[3] = data->loopnors; /* Note: loopnors may be NULL here. */
+ const float (*polynors)[3] = data->polynors;
+
+ int (*edge_to_loops)[2] = data->edge_to_loops;
+ int *loop_to_poly = data->loop_to_poly;
+
+ BLI_bitmap *sharp_edges = do_sharp_edges_tag ? BLI_BITMAP_NEW(numEdges, __func__) : NULL;
+
+ const MPoly *mp;
+ int mp_index;
+
+ const float split_angle_cos = check_angle ? cosf(split_angle) : -1.0f;
+
+ for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) {
+ const MLoop *ml_curr;
+ int *e2l;
+ int ml_curr_index = mp->loopstart;
+ const int ml_last_index = (ml_curr_index + mp->totloop) - 1;
+
+ ml_curr = &mloops[ml_curr_index];
+
+ for (; ml_curr_index <= ml_last_index; ml_curr++, ml_curr_index++) {
+ e2l = edge_to_loops[ml_curr->e];
+
+ loop_to_poly[ml_curr_index] = mp_index;
+
+ /* Pre-populate all loop normals as if their verts were all-smooth, this way we don't have to compute
+ * those later!
+ */
+ if (loopnors) {
+ normal_short_to_float_v3(loopnors[ml_curr_index], mverts[ml_curr->v].no);
+ }
+
+ /* Check whether current edge might be smooth or sharp */
+ if ((e2l[0] | e2l[1]) == 0) {
+ /* 'Empty' edge until now, set e2l[0] (and e2l[1] to INDEX_UNSET to tag it as unset). */
+ e2l[0] = ml_curr_index;
+ /* We have to check this here too, else we might miss some flat faces!!! */
+ e2l[1] = (mp->flag & ME_SMOOTH) ? INDEX_UNSET : INDEX_INVALID;
+ }
+ else if (e2l[1] == INDEX_UNSET) {
+ const bool is_angle_sharp = (check_angle &&
+ dot_v3v3(polynors[loop_to_poly[e2l[0]]], polynors[mp_index]) < split_angle_cos);
+
+ /* Second loop using this edge, time to test its sharpness.
+ * An edge is sharp if it is tagged as such, or its face is not smooth,
+ * or both poly have opposed (flipped) normals, i.e. both loops on the same edge share the same vertex,
+ * or angle between both its polys' normals is above split_angle value.
+ */
+ if (!(mp->flag & ME_SMOOTH) || (medges[ml_curr->e].flag & ME_SHARP) ||
+ ml_curr->v == mloops[e2l[0]].v ||
+ is_angle_sharp)
+ {
+ /* Note: we are sure that loop != 0 here ;) */
+ e2l[1] = INDEX_INVALID;
+
+ /* We want to avoid tagging edges as sharp when it is already defined as such by
+ * other causes than angle threshold... */
+ if (do_sharp_edges_tag && is_angle_sharp) {
+ BLI_BITMAP_SET(sharp_edges, ml_curr->e, true);
+ }
+ }
+ else {
+ e2l[1] = ml_curr_index;
+ }
+ }
+ else if (!IS_EDGE_SHARP(e2l)) {
+ /* More than two loops using this edge, tag as sharp if not yet done. */
+ e2l[1] = INDEX_INVALID;
+
+ /* We want to avoid tagging edges as sharp when it is already defined as such by
+ * other causes than angle threshold... */
+ if (do_sharp_edges_tag) {
+ BLI_BITMAP_SET(sharp_edges, ml_curr->e, false);
+ }
+ }
+ /* Else, edge is already 'disqualified' (i.e. sharp)! */
+ }
+ }
+
+ /* If requested, do actual tagging of edges as sharp in another loop. */
+ if (do_sharp_edges_tag) {
+ MEdge *me;
+ int me_index;
+ for (me = (MEdge *)medges, me_index = 0; me_index < numEdges; me++, me_index++) {
+ if (BLI_BITMAP_TEST(sharp_edges, me_index)) {
+ me->flag |= ME_SHARP;
+ }
+ }
+
+ MEM_freeN(sharp_edges);
+ }
+}
+
+/** Define sharp edges as needed to mimic 'autosmooth' from angle threshold.
+ *
+ * Used when defining an empty custom loop normals data layer, to keep same shading as with autosmooth!
+ */
+void BKE_edges_sharp_from_angle_set(
+ const struct MVert *mverts, const int UNUSED(numVerts),
+ struct MEdge *medges, const int numEdges,
+ struct MLoop *mloops, const int numLoops,
+ struct MPoly *mpolys, const float (*polynors)[3], const int numPolys,
+ const float split_angle)
+{
+ if (split_angle >= (float)M_PI) {
+ /* Nothing to do! */
+ return;
+ }
+
+ /* Mapping edge -> loops. See BKE_mesh_normals_loop_split() for details. */
+ int (*edge_to_loops)[2] = MEM_calloc_arrayN((size_t)numEdges, sizeof(*edge_to_loops), __func__);
+
+ /* Simple mapping from a loop to its polygon index. */
+ int *loop_to_poly = MEM_malloc_arrayN((size_t)numLoops, sizeof(*loop_to_poly), __func__);
+
+ LoopSplitTaskDataCommon common_data = {
+ .mverts = mverts,
+ .medges = medges,
+ .mloops = mloops,
+ .mpolys = mpolys,
+ .edge_to_loops = edge_to_loops,
+ .loop_to_poly = loop_to_poly,
+ .polynors = polynors,
+ .numEdges = numEdges,
+ .numPolys = numPolys,
+ };
+
+ mesh_edges_sharp_tag(&common_data, true, split_angle, true);
+
+ MEM_freeN(edge_to_loops);
+ MEM_freeN(loop_to_poly);
+}
+
+void BKE_mesh_loop_manifold_fan_around_vert_next(
const MLoop *mloops, const MPoly *mpolys,
const int *loop_to_poly, const int *e2lfan_curr, const uint mv_pivot_index,
const MLoop **r_mlfan_curr, int *r_mlfan_curr_index, int *r_mlfan_vert_index, int *r_mpfan_curr_index)
@@ -788,7 +952,7 @@ static void split_loop_nor_single_do(LoopSplitTaskDataCommon *common_data, LoopS
BKE_lnor_space_define(lnor_space, *lnor, vec_curr, vec_prev, NULL);
/* We know there is only one loop in this space, no need to create a linklist in this case... */
- BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, ml_curr_index, false);
+ BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, ml_curr_index, NULL, true);
if (clnors_data) {
BKE_lnor_space_custom_data_to_normal(lnor_space, clnors_data[ml_curr_index], *lnor);
@@ -921,7 +1085,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
if (lnors_spacearr) {
/* Assign current lnor space to current 'vertex' loop. */
- BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, mlfan_vert_index, true);
+ BKE_lnor_space_add_loop(lnors_spacearr, lnor_space, mlfan_vert_index, NULL, false);
if (me_curr != me_org) {
/* We store here all edges-normalized vectors processed. */
BLI_stack_push(edge_vectors, vec_curr);
@@ -939,7 +1103,7 @@ static void split_loop_nor_fan_do(LoopSplitTaskDataCommon *common_data, LoopSpli
copy_v3_v3(vec_prev, vec_curr);
/* Find next loop of the smooth fan. */
- loop_manifold_fan_around_vert_next(
+ BKE_mesh_loop_manifold_fan_around_vert_next(
mloops, mpolys, loop_to_poly, e2lfan_curr, mv_pivot_index,
&mlfan_curr, &mlfan_curr_index, &mlfan_vert_index, &mpfan_curr_index);
@@ -1076,7 +1240,7 @@ static bool loop_split_generator_check_cyclic_smooth_fan(
while (true) {
/* Find next loop of the smooth fan. */
- loop_manifold_fan_around_vert_next(
+ BKE_mesh_loop_manifold_fan_around_vert_next(
mloops, mpolys, loop_to_poly, e2lfan_curr, mv_pivot_index,
&mlfan_curr, &mlfan_curr_index, &mlfan_vert_index, &mpfan_curr_index);
@@ -1270,7 +1434,7 @@ void BKE_mesh_normals_loop_split(
const MVert *mverts, const int UNUSED(numVerts), MEdge *medges, const int numEdges,
MLoop *mloops, float (*r_loopnors)[3], const int numLoops,
MPoly *mpolys, const float (*polynors)[3], const int numPolys,
- const bool use_split_normals, float split_angle,
+ const bool use_split_normals, const float split_angle,
MLoopNorSpaceArray *r_lnors_spacearr, short (*clnors_data)[2], int *r_loop_to_poly)
{
/* For now this is not supported. If we do not use split normals, we do not generate anything fancy! */
@@ -1319,9 +1483,6 @@ void BKE_mesh_normals_loop_split(
/* Simple mapping from a loop to its polygon index. */
int *loop_to_poly = r_loop_to_poly ? r_loop_to_poly : MEM_malloc_arrayN((size_t)numLoops, sizeof(*loop_to_poly), __func__);
- MPoly *mp;
- int mp_index;
-
/* When using custom loop normals, disable the angle feature! */
const bool check_angle = (split_angle < (float)M_PI) && (clnors_data == NULL);
@@ -1331,67 +1492,12 @@ void BKE_mesh_normals_loop_split(
TIMEIT_START_AVERAGED(BKE_mesh_normals_loop_split);
#endif
- if (check_angle) {
- split_angle = cosf(split_angle);
- }
-
if (!r_lnors_spacearr && clnors_data) {
/* We need to compute lnor spacearr if some custom lnor data are given to us! */
r_lnors_spacearr = &_lnors_spacearr;
}
if (r_lnors_spacearr) {
- BKE_lnor_spacearr_init(r_lnors_spacearr, numLoops);
- }
-
- /* This first loop check which edges are actually smooth, and compute edge vectors. */
- for (mp = mpolys, mp_index = 0; mp_index < numPolys; mp++, mp_index++) {
- MLoop *ml_curr;
- int *e2l;
- int ml_curr_index = mp->loopstart;
- const int ml_last_index = (ml_curr_index + mp->totloop) - 1;
-
- ml_curr = &mloops[ml_curr_index];
-
- for (; ml_curr_index <= ml_last_index; ml_curr++, ml_curr_index++) {
- e2l = edge_to_loops[ml_curr->e];
-
- loop_to_poly[ml_curr_index] = mp_index;
-
- /* Pre-populate all loop normals as if their verts were all-smooth, this way we don't have to compute
- * those later!
- */
- normal_short_to_float_v3(r_loopnors[ml_curr_index], mverts[ml_curr->v].no);
-
- /* Check whether current edge might be smooth or sharp */
- if ((e2l[0] | e2l[1]) == 0) {
- /* 'Empty' edge until now, set e2l[0] (and e2l[1] to INDEX_UNSET to tag it as unset). */
- e2l[0] = ml_curr_index;
- /* We have to check this here too, else we might miss some flat faces!!! */
- e2l[1] = (mp->flag & ME_SMOOTH) ? INDEX_UNSET : INDEX_INVALID;
- }
- else if (e2l[1] == INDEX_UNSET) {
- /* Second loop using this edge, time to test its sharpness.
- * An edge is sharp if it is tagged as such, or its face is not smooth,
- * or both poly have opposed (flipped) normals, i.e. both loops on the same edge share the same vertex,
- * or angle between both its polys' normals is above split_angle value.
- */
- if (!(mp->flag & ME_SMOOTH) || (medges[ml_curr->e].flag & ME_SHARP) ||
- ml_curr->v == mloops[e2l[0]].v ||
- (check_angle && dot_v3v3(polynors[loop_to_poly[e2l[0]]], polynors[mp_index]) < split_angle))
- {
- /* Note: we are sure that loop != 0 here ;) */
- e2l[1] = INDEX_INVALID;
- }
- else {
- e2l[1] = ml_curr_index;
- }
- }
- else if (!IS_EDGE_SHARP(e2l)) {
- /* More than two loops using this edge, tag as sharp if not yet done. */
- e2l[1] = INDEX_INVALID;
- }
- /* Else, edge is already 'disqualified' (i.e. sharp)! */
- }
+ BKE_lnor_spacearr_init(r_lnors_spacearr, numLoops, MLNOR_SPACEARR_LOOP_INDEX);
}
/* Init data common to all tasks. */
@@ -1403,13 +1509,17 @@ void BKE_mesh_normals_loop_split(
.medges = medges,
.mloops = mloops,
.mpolys = mpolys,
- .edge_to_loops = (const int(*)[2])edge_to_loops,
+ .edge_to_loops = edge_to_loops,
.loop_to_poly = loop_to_poly,
.polynors = polynors,
+ .numEdges = numEdges,
.numLoops = numLoops,
.numPolys = numPolys,
};
+ /* This first loop check which edges are actually smooth, and compute edge vectors. */
+ mesh_edges_sharp_tag(&common_data, check_angle, split_angle, false);
+
if (numLoops < LOOP_SPLIT_TASK_BLOCK_SIZE * 8) {
/* Not enough loops to be worth the whole threading overhead... */
loop_split_generator(NULL, &common_data);
@@ -1501,6 +1611,8 @@ static void mesh_normals_loop_custom_set(
}
}
+ BLI_assert(lnors_spacearr.data_type == MLNOR_SPACEARR_LOOP_INDEX);
+
/* Now, check each current smooth fan (one lnor space per smooth fan!), and if all its matching custom lnors
* are not (enough) equal, add sharp edges as needed.
* This way, next time we run BKE_mesh_normals_loop_split(), we'll get lnor spacearr/smooth fans matching
@@ -1524,7 +1636,7 @@ static void mesh_normals_loop_custom_set(
if (!BLI_BITMAP_TEST(done_loops, i)) {
/* Notes:
- * * In case of mono-loop smooth fan, loops is NULL, so everything is fine (we have nothing to do).
+ * * In case of mono-loop smooth fan, we have nothing to do.
* * Loops in this linklist are ordered (in reversed order compared to how they were discovered by
* BKE_mesh_normals_loop_split(), but this is not a problem). Which means if we find a
* mismatching clnor, we know all remaining loops will have to be in a new, different smooth fan/
@@ -1532,6 +1644,11 @@ static void mesh_normals_loop_custom_set(
* * In smooth fan case, we compare each clnor against a ref one, to avoid small differences adding
* up into a real big one in the end!
*/
+ if (lnors_spacearr.lspacearr[i]->flags & MLNOR_SPACE_IS_SINGLE) {
+ BLI_BITMAP_ENABLE(done_loops, i);
+ continue;
+ }
+
LinkNode *loops = lnors_spacearr.lspacearr[i]->loops;
MLoop *prev_ml = NULL;
const float *org_nor = NULL;
@@ -1579,9 +1696,6 @@ static void mesh_normals_loop_custom_set(
medges[(prev_ml->e == mlp->e) ? prev_ml->e : ml->e].flag |= ME_SHARP;
}
}
-
- /* For single loops, where lnors_spacearr.lspacearr[i]->loops is NULL. */
- BLI_BITMAP_ENABLE(done_loops, i);
}
}
@@ -1611,7 +1725,15 @@ static void mesh_normals_loop_custom_set(
* computed 2D factors).
*/
LinkNode *loops = lnors_spacearr.lspacearr[i]->loops;
- if (loops) {
+ if (lnors_spacearr.lspacearr[i]->flags & MLNOR_SPACE_IS_SINGLE) {
+ BLI_assert(GET_INT_FROM_POINTER(loops) == i);
+ const int nidx = use_vertices ? (int)mloops[i].v : i;
+ float *nor = r_custom_loopnors[nidx];
+
+ BKE_lnor_space_custom_normal_to_data(lnors_spacearr.lspacearr[i], nor, r_clnors_data[i]);
+ BLI_BITMAP_DISABLE(done_loops, i);
+ }
+ else {
int nbr_nors = 0;
float avg_nor[3];
short clnor_data_tmp[2], *clnor_data;
@@ -1638,13 +1760,6 @@ static void mesh_normals_loop_custom_set(
clnor_data[1] = clnor_data_tmp[1];
}
}
- else {
- const int nidx = use_vertices ? (int)mloops[i].v : i;
- float *nor = r_custom_loopnors[nidx];
-
- BKE_lnor_space_custom_normal_to_data(lnors_spacearr.lspacearr[i], nor, r_clnors_data[i]);
- BLI_BITMAP_DISABLE(done_loops, i);
- }
}
}
@@ -2272,6 +2387,7 @@ void BKE_mesh_calc_volume(
}
}
+/** \} */
/* -------------------------------------------------------------------- */
@@ -2798,9 +2914,22 @@ void BKE_mesh_recalc_looptri(
}
else if (mp_totloop == 4) {
ML_TO_MLT(0, 1, 2);
+ MLoopTri *mlt_a = mlt;
mlooptri_index++;
ML_TO_MLT(0, 2, 3);
+ MLoopTri *mlt_b = mlt;
mlooptri_index++;
+
+ if (UNLIKELY(is_quad_flip_v3_first_third_fast(
+ mvert[mloop[mlt_a->tri[0]].v].co,
+ mvert[mloop[mlt_a->tri[1]].v].co,
+ mvert[mloop[mlt_a->tri[2]].v].co,
+ mvert[mloop[mlt_b->tri[2]].v].co)))
+ {
+ /* flip out of degenerate 0-2 state. */
+ mlt_a->tri[2] = mlt_b->tri[2];
+ mlt_b->tri[0] = mlt_a->tri[1];
+ }
}
#endif /* USE_TESSFACE_SPEEDUP */
else {
diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c
index f321c94bf00..0af4dae4506 100644
--- a/source/blender/blenkernel/intern/mesh_remap.c
+++ b/source/blender/blenkernel/intern/mesh_remap.c
@@ -36,7 +36,7 @@
#include "BLI_bitmap.h"
#include "BLI_math.h"
#include "BLI_memarena.h"
-#include "BLI_polyfill2d.h"
+#include "BLI_polyfill_2d.h"
#include "BLI_rand.h"
#include "BKE_bvhutils.h"
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
index 54de843bc64..8301b6a42b1 100644
--- a/source/blender/blenkernel/intern/mesh_validate.c
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -63,8 +63,8 @@ typedef union {
} EdgeUUID;
typedef struct SortFace {
- EdgeUUID es[4];
- unsigned int index;
+ EdgeUUID es[4];
+ unsigned int index;
} SortFace;
/* Used to detect polys (faces) using exactly the same vertices. */
@@ -127,28 +127,28 @@ static int search_face_cmp(const void *v1, const void *v2)
if (sfa->es[0].edval > sfb->es[0].edval) {
return 1;
}
- else if (sfa->es[0].edval < sfb->es[0].edval) {
+ else if (sfa->es[0].edval < sfb->es[0].edval) {
return -1;
}
- else if (sfa->es[1].edval > sfb->es[1].edval) {
+ else if (sfa->es[1].edval > sfb->es[1].edval) {
return 1;
}
- else if (sfa->es[1].edval < sfb->es[1].edval) {
+ else if (sfa->es[1].edval < sfb->es[1].edval) {
return -1;
}
- else if (sfa->es[2].edval > sfb->es[2].edval) {
+ else if (sfa->es[2].edval > sfb->es[2].edval) {
return 1;
}
- else if (sfa->es[2].edval < sfb->es[2].edval) {
+ else if (sfa->es[2].edval < sfb->es[2].edval) {
return -1;
}
- else if (sfa->es[3].edval > sfb->es[3].edval) {
+ else if (sfa->es[3].edval > sfb->es[3].edval) {
return 1;
}
- else if (sfa->es[3].edval < sfb->es[3].edval) {
+ else if (sfa->es[3].edval < sfb->es[3].edval) {
return -1;
}
@@ -1412,7 +1412,7 @@ void BKE_mesh_calc_edges(Mesh *mesh, bool update, const bool select)
}
}
- totedge = BLI_edgehash_size(eh);
+ totedge = BLI_edgehash_len(eh);
/* write new edges into a temporary CustomData */
CustomData_reset(&edata);
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 8bfeacd256c..5eb5272f3e5 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -69,6 +69,8 @@
#include "BKE_main.h"
/* end */
+#include "DEG_depsgraph.h"
+
#include "MOD_modifiertypes.h"
static ModifierTypeInfo *modifier_types[NUM_MODIFIER_TYPES] = {NULL};
@@ -136,16 +138,38 @@ ModifierData *modifier_new(int type)
return md;
}
-void modifier_free(ModifierData *md)
+static void modifier_free_data_id_us_cb(void *UNUSED(userData), Object *UNUSED(ob), ID **idpoin, int cb_flag)
+{
+ ID *id = *idpoin;
+ if (id != NULL && (cb_flag & IDWALK_CB_USER) != 0) {
+ id_us_min(id);
+ }
+}
+
+void modifier_free_ex(ModifierData *md, const int flag)
{
const ModifierTypeInfo *mti = modifierType_getInfo(md->type);
+ if ((flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
+ if (mti->foreachIDLink) {
+ mti->foreachIDLink(md, NULL, modifier_free_data_id_us_cb, NULL);
+ }
+ else if (mti->foreachObjectLink) {
+ mti->foreachObjectLink(md, NULL, (ObjectWalkFunc)modifier_free_data_id_us_cb, NULL);
+ }
+ }
+
if (mti->freeData) mti->freeData(md);
if (md->error) MEM_freeN(md->error);
MEM_freeN(md);
}
+void modifier_free(ModifierData *md)
+{
+ modifier_free_ex(md, 0);
+}
+
bool modifier_unique_name(ListBase *modifiers, ModifierData *md)
{
if (modifiers && md) {
@@ -666,9 +690,9 @@ bool modifiers_isCorrectableDeformed(struct Scene *scene, Object *ob)
ModifierData *md = modifiers_getVirtualModifierList(ob, &virtualModifierData);
int required_mode = eModifierMode_Realtime;
- if (ob->mode == OB_MODE_EDIT)
+ if (ob->mode == OB_MODE_EDIT) {
required_mode |= eModifierMode_Editmode;
-
+ }
for (; md; md = md->next) {
if (!modifier_isEnabled(scene, md, required_mode)) {
/* pass */
diff --git a/source/blender/blenkernel/intern/modifiers_bmesh.c b/source/blender/blenkernel/intern/modifiers_bmesh.c
index 0838630a6cb..a1172d3f110 100644
--- a/source/blender/blenkernel/intern/modifiers_bmesh.c
+++ b/source/blender/blenkernel/intern/modifiers_bmesh.c
@@ -62,7 +62,7 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm, const bool calc_face_normal)
{
MVert *mv, *mvert;
MEdge *me, *medge;
- MPoly /* *mpoly, */ /* UNUSED */ *mp;
+ MPoly *mpoly, *mp;
MLoop *mloop;
BMVert *v, **vtable;
BMEdge *e, **etable;
@@ -70,7 +70,6 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm, const bool calc_face_normal)
BMFace *f;
int i, j, totvert, totedge /* , totface */ /* UNUSED */ ;
bool is_init = (bm->totvert == 0) && (bm->totedge == 0) && (bm->totface == 0);
- bool is_cddm = (dm->type == DM_TYPE_CDDM); /* duplicate the arrays for non cddm */
char has_orig_htype = 0;
int cd_vert_bweight_offset;
@@ -106,7 +105,8 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm, const bool calc_face_normal)
etable = MEM_mallocN(sizeof(*etable) * totedge, __func__);
/*do verts*/
- mv = mvert = is_cddm ? dm->getVertArray(dm) : dm->dupVertArray(dm);
+ bool vert_allocated;
+ mv = mvert = DM_get_vert_array(dm, &vert_allocated);;
for (i = 0; i < totvert; i++, mv++) {
v = BM_vert_create(bm, mv->co, NULL, BM_CREATE_SKIP_CD);
normal_short_to_float_v3(v->no, mv->no);
@@ -124,11 +124,12 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm, const bool calc_face_normal)
*orig_index = ORIGINDEX_NONE;
}
}
- if (!is_cddm) MEM_freeN(mvert);
+ if (vert_allocated) MEM_freeN(mvert);
if (is_init) bm->elem_index_dirty &= ~BM_VERT;
/*do edges*/
- me = medge = is_cddm ? dm->getEdgeArray(dm) : dm->dupEdgeArray(dm);
+ bool edge_allocated;
+ me = medge = DM_get_edge_array(dm, &edge_allocated);
for (i = 0; i < totedge; i++, me++) {
//BLI_assert(BM_edge_exists(vtable[me->v1], vtable[me->v2]) == NULL);
e = BM_edge_create(bm, vtable[me->v1], vtable[me->v2], NULL, BM_CREATE_SKIP_CD);
@@ -147,13 +148,14 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm, const bool calc_face_normal)
*orig_index = ORIGINDEX_NONE;
}
}
- if (!is_cddm) MEM_freeN(medge);
+ if (edge_allocated) MEM_freeN(medge);
if (is_init) bm->elem_index_dirty &= ~BM_EDGE;
/* do faces */
/* note: i_alt is aligned with bmesh faces which may not always align with mpolys */
- mp = dm->getPolyArray(dm);
- mloop = dm->getLoopArray(dm);
+ bool poly_allocated, loop_allocated;
+ mpoly = mp = DM_get_poly_array(dm, &poly_allocated);
+ mloop = DM_get_loop_array(dm, &loop_allocated);
face_normals = (dm->dirty & DM_DIRTY_NORMALS) ? NULL : CustomData_get_layer(&dm->polyData, CD_NORMAL);
for (i = 0; i < dm->numPolyData; i++, mp++) {
BMLoop *l_iter;
@@ -194,6 +196,8 @@ void DM_to_bmesh_ex(DerivedMesh *dm, BMesh *bm, const bool calc_face_normal)
*orig_index = ORIGINDEX_NONE;
}
}
+ if (poly_allocated) MEM_freeN(mpoly);
+ if (loop_allocated) MEM_freeN(mloop);
if (is_init) bm->elem_index_dirty &= ~(BM_FACE | BM_LOOP);
MEM_freeN(vtable);
diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c
index 08df976941b..9ed715d7591 100644
--- a/source/blender/blenkernel/intern/movieclip.c
+++ b/source/blender/blenkernel/intern/movieclip.c
@@ -73,12 +73,12 @@
#include "IMB_imbuf.h"
#include "IMB_moviecache.h"
+#include "DEG_depsgraph.h"
+
#ifdef WITH_OPENEXR
# include "intern/openexr/openexr_multi.h"
#endif
-#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
-
/*********************** movieclip buffer loaders *************************/
static int sequence_guess_offset(const char *full_name, int head_len, unsigned short numlen)
@@ -926,7 +926,7 @@ static ImBuf *movieclip_get_postprocessed_ibuf(MovieClip *clip,
/* cache isn't threadsafe itself and also loading of movies
* can't happen from concurrent threads that's why we use lock here */
- BLI_lock_thread(LOCK_MOVIECLIP);
+ BLI_thread_lock(LOCK_MOVIECLIP);
/* try to obtain cached postprocessed frame first */
if (need_postprocessed_frame(user, postprocess_flag)) {
@@ -976,7 +976,7 @@ static ImBuf *movieclip_get_postprocessed_ibuf(MovieClip *clip,
}
}
- BLI_unlock_thread(LOCK_MOVIECLIP);
+ BLI_thread_unlock(LOCK_MOVIECLIP);
return ibuf;
}
@@ -1202,6 +1202,23 @@ int BKE_movieclip_get_duration(MovieClip *clip)
return clip->len;
}
+float BKE_movieclip_get_fps(MovieClip *clip)
+{
+ if (clip->source != MCLIP_SRC_MOVIE) {
+ return 0.0f;
+ }
+ movieclip_open_anim_file(clip);
+ if (clip->anim == NULL) {
+ return 0.0f;
+ }
+ short frs_sec;
+ float frs_sec_base;
+ if (IMB_anim_get_fps(clip->anim, &frs_sec, &frs_sec_base, true)) {
+ return (float)frs_sec / frs_sec_base;
+ }
+ return 0.0f;
+}
+
void BKE_movieclip_get_aspect(MovieClip *clip, float *aspx, float *aspy)
{
*aspx = 1.0;
@@ -1410,13 +1427,13 @@ static void movieclip_build_proxy_ibuf(MovieClip *clip, ImBuf *ibuf, int cfra, i
* could be solved in a way that thread only prepares memory
* buffer and write to disk happens separately
*/
- BLI_lock_thread(LOCK_MOVIECLIP);
+ BLI_thread_lock(LOCK_MOVIECLIP);
BLI_make_existing_file(name);
if (IMB_saveiff(scaleibuf, name, IB_rect) == 0)
perror(name);
- BLI_unlock_thread(LOCK_MOVIECLIP);
+ BLI_thread_unlock(LOCK_MOVIECLIP);
IMB_freeImBuf(scaleibuf);
}
@@ -1560,9 +1577,9 @@ ImBuf *BKE_movieclip_anim_ibuf_for_frame(MovieClip *clip, MovieClipUser *user)
ImBuf *ibuf = NULL;
if (clip->source == MCLIP_SRC_MOVIE) {
- BLI_lock_thread(LOCK_MOVIECLIP);
+ BLI_thread_lock(LOCK_MOVIECLIP);
ibuf = movieclip_load_movie_file(clip, user, user->framenr, clip->flag);
- BLI_unlock_thread(LOCK_MOVIECLIP);
+ BLI_thread_unlock(LOCK_MOVIECLIP);
}
return ibuf;
@@ -1572,9 +1589,9 @@ bool BKE_movieclip_has_cached_frame(MovieClip *clip, MovieClipUser *user)
{
bool has_frame = false;
- BLI_lock_thread(LOCK_MOVIECLIP);
+ BLI_thread_lock(LOCK_MOVIECLIP);
has_frame = has_imbuf_cache(clip, user, clip->flag);
- BLI_unlock_thread(LOCK_MOVIECLIP);
+ BLI_thread_unlock(LOCK_MOVIECLIP);
return has_frame;
}
@@ -1585,15 +1602,15 @@ bool BKE_movieclip_put_frame_if_possible(MovieClip *clip,
{
bool result;
- BLI_lock_thread(LOCK_MOVIECLIP);
+ BLI_thread_lock(LOCK_MOVIECLIP);
result = put_imbuf_cache(clip, user, ibuf, clip->flag, false);
- BLI_unlock_thread(LOCK_MOVIECLIP);
+ BLI_thread_unlock(LOCK_MOVIECLIP);
return result;
}
void BKE_movieclip_eval_update(struct EvaluationContext *UNUSED(eval_ctx), MovieClip *clip)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, clip->id.name, clip);
+ DEG_debug_print_eval(__func__, clip->id.name, clip);
BKE_tracking_dopesheet_tag_update(&clip->tracking);
}
diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c
index cbb7a766dfe..777c2a580fd 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -75,7 +75,7 @@
/* Remove the given NLA strip from the NLA track it occupies, free the strip's data,
* and the strip itself.
*/
-void free_nlastrip(ListBase *strips, NlaStrip *strip)
+void BKE_nlastrip_free(ListBase *strips, NlaStrip *strip)
{
NlaStrip *cs, *csn;
@@ -86,7 +86,7 @@ void free_nlastrip(ListBase *strips, NlaStrip *strip)
/* free child-strips */
for (cs = strip->strips.first; cs; cs = csn) {
csn = cs->next;
- free_nlastrip(&strip->strips, cs);
+ BKE_nlastrip_free(&strip->strips, cs);
}
/* remove reference to action */
@@ -113,7 +113,7 @@ void free_nlastrip(ListBase *strips, NlaStrip *strip)
/* Remove the given NLA track from the set of NLA tracks, free the track's data,
* and the track itself.
*/
-void free_nlatrack(ListBase *tracks, NlaTrack *nlt)
+void BKE_nlatrack_free(ListBase *tracks, NlaTrack *nlt)
{
NlaStrip *strip, *stripn;
@@ -124,7 +124,7 @@ void free_nlatrack(ListBase *tracks, NlaTrack *nlt)
/* free strips */
for (strip = nlt->strips.first; strip; strip = stripn) {
stripn = strip->next;
- free_nlastrip(&nlt->strips, strip);
+ BKE_nlastrip_free(&nlt->strips, strip);
}
/* free NLA track itself now */
@@ -137,7 +137,7 @@ void free_nlatrack(ListBase *tracks, NlaTrack *nlt)
/* Free the elements of type NLA Tracks provided in the given list, but do not free
* the list itself since that is not free-standing
*/
-void free_nladata(ListBase *tracks)
+void BKE_nla_tracks_free(ListBase *tracks)
{
NlaTrack *nlt, *nltn;
@@ -148,7 +148,7 @@ void free_nladata(ListBase *tracks)
/* free tracks one by one */
for (nlt = tracks->first; nlt; nlt = nltn) {
nltn = nlt->next;
- free_nlatrack(tracks, nlt);
+ BKE_nlatrack_free(tracks, nlt);
}
/* clear the list's pointers to be safe */
@@ -162,7 +162,7 @@ void free_nladata(ListBase *tracks)
*
* \param use_same_action When true, the existing action is used (instead of being duplicated)
*/
-NlaStrip *copy_nlastrip(NlaStrip *strip, const bool use_same_action)
+NlaStrip *BKE_nlastrip_copy(NlaStrip *strip, const bool use_same_action)
{
NlaStrip *strip_d;
NlaStrip *cs, *cs_d;
@@ -195,7 +195,7 @@ NlaStrip *copy_nlastrip(NlaStrip *strip, const bool use_same_action)
BLI_listbase_clear(&strip_d->strips);
for (cs = strip->strips.first; cs; cs = cs->next) {
- cs_d = copy_nlastrip(cs, use_same_action);
+ cs_d = BKE_nlastrip_copy(cs, use_same_action);
BLI_addtail(&strip_d->strips, cs_d);
}
@@ -204,7 +204,7 @@ NlaStrip *copy_nlastrip(NlaStrip *strip, const bool use_same_action)
}
/* Copy NLA Track */
-NlaTrack *copy_nlatrack(NlaTrack *nlt, const bool use_same_actions)
+NlaTrack *BKE_nlatrack_copy(NlaTrack *nlt, const bool use_same_actions)
{
NlaStrip *strip, *strip_d;
NlaTrack *nlt_d;
@@ -221,7 +221,7 @@ NlaTrack *copy_nlatrack(NlaTrack *nlt, const bool use_same_actions)
BLI_listbase_clear(&nlt_d->strips);
for (strip = nlt->strips.first; strip; strip = strip->next) {
- strip_d = copy_nlastrip(strip, use_same_actions);
+ strip_d = BKE_nlastrip_copy(strip, use_same_actions);
BLI_addtail(&nlt_d->strips, strip_d);
}
@@ -230,7 +230,7 @@ NlaTrack *copy_nlatrack(NlaTrack *nlt, const bool use_same_actions)
}
/* Copy all NLA data */
-void copy_nladata(ListBase *dst, ListBase *src)
+void BKE_nla_tracks_copy(ListBase *dst, ListBase *src)
{
NlaTrack *nlt, *nlt_d;
@@ -245,7 +245,7 @@ void copy_nladata(ListBase *dst, ListBase *src)
for (nlt = src->first; nlt; nlt = nlt->next) {
/* make a copy, and add the copy to the destination list */
// XXX: we need to fix this sometime
- nlt_d = copy_nlatrack(nlt, true);
+ nlt_d = BKE_nlatrack_copy(nlt, true);
BLI_addtail(dst, nlt_d);
}
}
@@ -255,7 +255,7 @@ void copy_nladata(ListBase *dst, ListBase *src)
/* Add a NLA Track to the given AnimData
* - prev: NLA-Track to add the new one after
*/
-NlaTrack *add_nlatrack(AnimData *adt, NlaTrack *prev)
+NlaTrack *BKE_nlatrack_add(AnimData *adt, NlaTrack *prev)
{
NlaTrack *nlt;
@@ -285,8 +285,8 @@ NlaTrack *add_nlatrack(AnimData *adt, NlaTrack *prev)
return nlt;
}
-/* Add a NLA Strip referencing the given Action */
-NlaStrip *add_nlastrip(bAction *act)
+/* Create a NLA Strip referencing the given Action */
+NlaStrip *BKE_nlastrip_new(bAction *act)
{
NlaStrip *strip;
@@ -327,7 +327,7 @@ NlaStrip *add_nlastrip(bAction *act)
}
/* Add new NLA-strip to the top of the NLA stack - i.e. into the last track if space, or a new one otherwise */
-NlaStrip *add_nlastrip_to_stack(AnimData *adt, bAction *act)
+NlaStrip *BKE_nlastack_add_strip(AnimData *adt, bAction *act)
{
NlaStrip *strip;
NlaTrack *nlt;
@@ -337,7 +337,7 @@ NlaStrip *add_nlastrip_to_stack(AnimData *adt, bAction *act)
return NULL;
/* create a new NLA strip */
- strip = add_nlastrip(act);
+ strip = BKE_nlastrip_new(act);
if (strip == NULL)
return NULL;
@@ -346,7 +346,7 @@ NlaStrip *add_nlastrip_to_stack(AnimData *adt, bAction *act)
/* trying to add to the last track failed (no track or no space),
* so add a new track to the stack, and add to that...
*/
- nlt = add_nlatrack(adt, NULL);
+ nlt = BKE_nlatrack_add(adt, NULL);
BKE_nlatrack_add_strip(nlt, strip);
}
@@ -358,7 +358,7 @@ NlaStrip *add_nlastrip_to_stack(AnimData *adt, bAction *act)
}
/* Add a NLA Strip referencing the given speaker's sound */
-NlaStrip *add_nla_soundstrip(Scene *scene, Speaker *speaker)
+NlaStrip *BKE_nla_add_soundstrip(Scene *scene, Speaker *speaker)
{
NlaStrip *strip = MEM_callocN(sizeof(NlaStrip), "NlaSoundStrip");
@@ -751,7 +751,7 @@ void BKE_nlastrips_clear_metastrip(ListBase *strips, NlaStrip *strip)
}
/* free the meta-strip now */
- free_nlastrip(strips, strip);
+ BKE_nlastrip_free(strips, strip);
}
/* Remove meta-strips (i.e. flatten the list of strips) from the top-level of the list of strips
@@ -1392,7 +1392,12 @@ void BKE_nlastrip_validate_fcurves(NlaStrip *strip)
/* store path - make copy, and store that */
fcu->rna_path = BLI_strdupn("influence", 9);
- /* TODO: insert a few keyframes to ensure default behavior? */
+ /* insert keyframe to ensure current value stays on first refresh */
+ fcu->bezt = MEM_callocN(sizeof(BezTriple), "nlastrip influence bezt");
+ fcu->totvert = 1;
+
+ fcu->bezt->vec[1][0] = strip->start;
+ fcu->bezt->vec[1][1] = strip->influence;
}
}
@@ -1709,7 +1714,7 @@ bool BKE_nla_action_stash(AnimData *adt)
}
}
- nlt = add_nlatrack(adt, prev_track);
+ nlt = BKE_nlatrack_add(adt, prev_track);
BLI_assert(nlt != NULL);
/* we need to ensure that if there wasn't any previous instance, it must go to tbe bottom of the stack */
@@ -1724,7 +1729,7 @@ bool BKE_nla_action_stash(AnimData *adt)
/* add the action as a strip in this new track
* NOTE: a new user is created here
*/
- strip = add_nlastrip(adt->action);
+ strip = BKE_nlastrip_new(adt->action);
BLI_assert(strip != NULL);
BKE_nlatrack_add_strip(nlt, strip);
@@ -1760,7 +1765,8 @@ bool BKE_nla_action_stash(AnimData *adt)
void BKE_nla_action_pushdown(AnimData *adt)
{
NlaStrip *strip;
-
+ const bool is_first = (adt) && (adt->nla_tracks.first == NULL);
+
/* sanity checks */
/* TODO: need to report the error for this */
if (ELEM(NULL, adt, adt->action))
@@ -1776,7 +1782,7 @@ void BKE_nla_action_pushdown(AnimData *adt)
}
/* add a new NLA strip to the track, which references the active action */
- strip = add_nlastrip_to_stack(adt, adt->action);
+ strip = BKE_nlastack_add_strip(adt, adt->action);
/* do other necessary work on strip */
if (strip) {
@@ -1784,6 +1790,32 @@ void BKE_nla_action_pushdown(AnimData *adt)
id_us_min(&adt->action->id);
adt->action = NULL;
+ /* copy current "action blending" settings from adt to the strip,
+ * as it was keyframed with these settings, so omitting them will
+ * change the effect [T54233]
+ *
+ * NOTE: We only do this when there are no tracks
+ */
+ if (is_first == false) {
+ strip->blendmode = adt->act_blendmode;
+ strip->influence = adt->act_influence;
+ strip->extendmode = adt->act_extendmode;
+
+ if (adt->act_influence < 1.0f) {
+ /* enable "user-controlled" influence (which will insert a default keyframe)
+ * so that the influence doesn't get lost on the new update
+ *
+ * NOTE: An alternative way would have been to instead hack the influence
+ * to not get always get reset to full strength if NLASTRIP_FLAG_USR_INFLUENCE
+ * is disabled but auto-blending isn't being used. However, that approach
+ * is a bit hacky/hard to discover, and may cause backwards compatability issues,
+ * so it's better to just do it this way.
+ */
+ strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE;
+ BKE_nlastrip_validate_fcurves(strip);
+ }
+ }
+
/* if the strip is the first one in the track it lives in, check if there
* are strips in any other tracks that may be before this, and set the extend
* mode accordingly
@@ -1793,7 +1825,8 @@ void BKE_nla_action_pushdown(AnimData *adt)
* so that it doesn't override strips in previous tracks
*/
/* FIXME: this needs to be more automated, since user can rearrange strips */
- strip->extendmode = NLASTRIP_EXTEND_HOLD_FORWARD;
+ if (strip->extendmode == NLASTRIP_EXTEND_HOLD)
+ strip->extendmode = NLASTRIP_EXTEND_HOLD_FORWARD;
}
/* make strip the active one... */
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index cac2aab26dd..41b7cd1f48e 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -75,6 +75,8 @@
#include "NOD_shader.h"
#include "NOD_texture.h"
+#include "DEG_depsgraph.h"
+
#define NODE_DEFAULT_MAX_WIDTH 700
/* Fallback types for undefined tree, nodes, sockets */
@@ -2787,7 +2789,7 @@ int BKE_node_instance_hash_haskey(bNodeInstanceHash *hash, bNodeInstanceKey key)
int BKE_node_instance_hash_size(bNodeInstanceHash *hash)
{
- return BLI_ghash_size(hash->ghash);
+ return BLI_ghash_len(hash->ghash);
}
void BKE_node_instance_hash_clear_tags(bNodeInstanceHash *hash)
@@ -3590,6 +3592,7 @@ static void registerShaderNodes(void)
register_node_type_sh_attribute();
register_node_type_sh_bevel();
register_node_type_sh_displacement();
+ register_node_type_sh_vector_displacement();
register_node_type_sh_geometry();
register_node_type_sh_light_path();
register_node_type_sh_light_falloff();
@@ -3615,6 +3618,7 @@ static void registerShaderNodes(void)
register_node_type_sh_holdout();
register_node_type_sh_volume_absorption();
register_node_type_sh_volume_scatter();
+ register_node_type_sh_volume_principled();
register_node_type_sh_subsurface_scattering();
register_node_type_sh_mix_shader();
register_node_type_sh_add_shader();
@@ -3819,6 +3823,7 @@ bool BKE_node_tree_iter_step(struct NodeTreeIterStore *ntreeiter,
void BKE_nodetree_remove_layer_n(bNodeTree *ntree, Scene *scene, const int layer_index)
{
+ BLI_assert(layer_index != -1);
for (bNode *node = ntree->nodes.first; node; node = node->next) {
if (node->type == CMP_NODE_R_LAYERS && (Scene *)node->id == scene) {
if (node->custom1 == layer_index) {
@@ -3868,8 +3873,6 @@ void BKE_nodetree_shading_params_eval(const struct EvaluationContext *UNUSED(eva
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);
- }
+ DEG_debug_print_eval(__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 2a4914da101..2cb4356a52a 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -200,12 +200,12 @@ void BKE_object_free_curve_cache(Object *ob)
}
}
-void BKE_object_free_modifiers(Object *ob)
+void BKE_object_free_modifiers(Object *ob, const int flag)
{
ModifierData *md;
while ((md = BLI_pophead(&ob->modifiers))) {
- modifier_free(md);
+ modifier_free_ex(md, flag);
}
/* particle modifiers were freed, so free the particlesystems as well */
@@ -240,7 +240,7 @@ void BKE_object_modifier_hook_reset(Object *ob, HookModifierData *hmd)
}
}
-bool BKE_object_support_modifier_type_check(Object *ob, int modifier_type)
+bool BKE_object_support_modifier_type_check(const Object *ob, int modifier_type)
{
const ModifierTypeInfo *mti;
@@ -267,7 +267,7 @@ bool BKE_object_support_modifier_type_check(Object *ob, int modifier_type)
void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_src)
{
ModifierData *md;
- BKE_object_free_modifiers(ob_dst);
+ BKE_object_free_modifiers(ob_dst, 0);
if (!ELEM(ob_dst->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
/* only objects listed above can have modifiers and linking them to objects
@@ -427,7 +427,8 @@ void BKE_object_free(Object *ob)
{
BKE_animdata_free((ID *)ob, false);
- BKE_object_free_modifiers(ob);
+ /* BKE_<id>_free shall never touch to ID->us. Never ever. */
+ BKE_object_free_modifiers(ob, LIB_ID_CREATE_NO_USER_REFCOUNT);
MEM_SAFE_FREE(ob->mat);
MEM_SAFE_FREE(ob->matbits);
@@ -467,11 +468,8 @@ 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);
+ if (oed->free != NULL) {
+ oed->free(oed);
}
}
BLI_freelistN(&ob->drawdata);
@@ -498,7 +496,7 @@ void BKE_object_free(Object *ob)
}
/* actual check for internal data, not context or flags */
-bool BKE_object_is_in_editmode(Object *ob)
+bool BKE_object_is_in_editmode(const Object *ob)
{
if (ob->data == NULL)
return false;
@@ -546,13 +544,13 @@ bool BKE_object_is_in_editmode(Object *ob)
return false;
}
-bool BKE_object_is_in_editmode_vgroup(Object *ob)
+bool BKE_object_is_in_editmode_vgroup(const Object *ob)
{
return (OB_TYPE_SUPPORT_VGROUP(ob->type) &&
BKE_object_is_in_editmode(ob));
}
-bool BKE_object_is_in_wpaint_select_vert(Object *ob)
+bool BKE_object_is_in_wpaint_select_vert(const Object *ob)
{
if (ob->type == OB_MESH) {
Mesh *me = ob->data;
@@ -594,7 +592,7 @@ bool BKE_object_is_visible(Object *ob, const eObjectVisibilityCheck mode)
}
}
-bool BKE_object_exists_check(Object *obtest)
+bool BKE_object_exists_check(const Object *obtest)
{
Object *ob;
@@ -1056,7 +1054,6 @@ ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys, const int f
BLI_listbase_clear(&psysn->pathcachebufs);
BLI_listbase_clear(&psysn->childcachebufs);
- psysn->renderdata = NULL;
/* XXX Never copy caches here? */
psysn->pointcache = BKE_ptcache_copy_list(&psysn->ptcaches, &psys->ptcaches, flag & ~LIB_ID_COPY_CACHES);
@@ -1169,7 +1166,7 @@ static void copy_object_lod(Object *obn, const Object *ob, const int UNUSED(flag
obn->currentlod = (LodLevel *)obn->lodlevels.first;
}
-bool BKE_object_pose_context_check(Object *ob)
+bool BKE_object_pose_context_check(const Object *ob)
{
if ((ob) &&
(ob->type == OB_ARMATURE) &&
@@ -1193,12 +1190,26 @@ Object *BKE_object_pose_armature_get(Object *ob)
ob = modifiers_isDeformedByArmature(ob);
+ /* Only use selected check when non-active. */
if (BKE_object_pose_context_check(ob))
return ob;
return NULL;
}
+Object *BKE_object_pose_armature_get_visible(Object *ob, ViewLayer *view_layer)
+{
+ Object *ob_armature = BKE_object_pose_armature_get(ob);
+ if (ob_armature) {
+ Base *base = BKE_view_layer_base_find(view_layer, ob_armature);
+ if (base) {
+ if (BASE_VISIBLE(base)) {
+ return ob_armature;
+ }
+ }
+ }
+ return NULL;
+}
void BKE_object_transform_copy(Object *ob_tar, const Object *ob_src)
{
copy_v3_v3(ob_tar->loc, ob_src->loc);
@@ -1357,13 +1368,13 @@ void BKE_object_make_local(Main *bmain, Object *ob, const bool lib_local)
}
/* Returns true if the Object is from an external blend file (libdata) */
-bool BKE_object_is_libdata(Object *ob)
+bool BKE_object_is_libdata(const Object *ob)
{
return (ob && ID_IS_LINKED(ob));
}
/* Returns true if the Object data is from an external blend file (libdata) */
-bool BKE_object_obdata_is_libdata(Object *ob)
+bool BKE_object_obdata_is_libdata(const Object *ob)
{
/* Linked objects with local obdata are forbidden! */
BLI_assert(!ob || !ob->data || (ID_IS_LINKED(ob) ? ID_IS_LINKED(ob->data) : true));
@@ -2318,7 +2329,7 @@ void BKE_object_apply_mat4(Object *ob, float mat[4][4], const bool use_compat, c
BoundBox *BKE_boundbox_alloc_unit(void)
{
BoundBox *bb;
- const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {-1.0f, -1.0f, -1.0f};
+ const float min[3] = {-1.0f, -1.0f, -1.0f}, max[3] = {1.0f, 1.0f, 1.0f};
bb = MEM_callocN(sizeof(BoundBox), "OB-BoundBox");
BKE_boundbox_init_from_minmax(bb, min, max);
@@ -2767,7 +2778,7 @@ void BKE_object_handle_update_ex(const EvaluationContext *eval_ctx,
* which is only in BKE_object_where_is_calc now */
/* XXX: should this case be OB_RECALC_OB instead? */
if (recalc_object || recalc_data) {
- if (G.debug & G_DEBUG_DEPSGRAPH) {
+ if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) {
printf("recalcob %s\n", ob->id.name + 2);
}
/* Handle proxy copy for target. */
@@ -3143,7 +3154,7 @@ bool BKE_object_flag_test_recursive(const Object *ob, short flag)
}
}
-bool BKE_object_is_child_recursive(Object *ob_parent, Object *ob_child)
+bool BKE_object_is_child_recursive(const Object *ob_parent, const Object *ob_child)
{
for (ob_child = ob_child->parent; ob_child; ob_child = ob_child->parent) {
if (ob_child == ob_parent) {
diff --git a/source/blender/blenkernel/intern/object_deform.c b/source/blender/blenkernel/intern/object_deform.c
index 754434eaef6..fb2e824b299 100644
--- a/source/blender/blenkernel/intern/object_deform.c
+++ b/source/blender/blenkernel/intern/object_deform.c
@@ -42,7 +42,7 @@
#include "DNA_mesh_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_particle_types.h"
#include "DNA_scene_types.h"
@@ -460,6 +460,70 @@ void BKE_object_defgroup_remove_all(struct Object *ob)
BKE_object_defgroup_remove_all_ex(ob, false);
}
+/**
+ * Compute mapping for vertex groups with matching name, -1 is used for no remapping.
+ * Returns null if no remapping is required.
+ * The returned array has to be freed.
+ */
+int *BKE_object_defgroup_index_map_create(Object *ob_src, Object *ob_dst, int *r_map_len)
+{
+ /* Build src to merged mapping of vgroup indices. */
+ if (BLI_listbase_is_empty(&ob_src->defbase) || BLI_listbase_is_empty(&ob_dst->defbase)) {
+ *r_map_len = 0;
+ return NULL;
+ }
+
+ bDeformGroup *dg_src;
+ *r_map_len = BLI_listbase_count(&ob_src->defbase);
+ int *vgroup_index_map = MEM_malloc_arrayN(*r_map_len, sizeof(*vgroup_index_map), "defgroup index map create");
+ bool is_vgroup_remap_needed = false;
+ int i;
+
+ for (dg_src = ob_src->defbase.first, i = 0; dg_src; dg_src = dg_src->next, i++) {
+ vgroup_index_map[i] = defgroup_name_index(ob_dst, dg_src->name);
+ is_vgroup_remap_needed = is_vgroup_remap_needed || (vgroup_index_map[i] != i);
+ }
+
+ if (!is_vgroup_remap_needed) {
+ MEM_freeN(vgroup_index_map);
+ vgroup_index_map = NULL;
+ *r_map_len = 0;
+ }
+
+ return vgroup_index_map;
+}
+
+void BKE_object_defgroup_index_map_apply(MDeformVert *dvert, int dvert_len, const int *map, int map_len)
+{
+ if (map == NULL || map_len == 0) {
+ return;
+ }
+
+ MDeformVert *dv = dvert;
+ for (int i = 0; i < dvert_len; i++, dv++) {
+ int totweight = dv->totweight;
+ for (int j = 0; j < totweight; j++) {
+ int def_nr = dv->dw[j].def_nr;
+ if ((uint)def_nr < (uint)map_len && map[def_nr] != -1) {
+ dv->dw[j].def_nr = map[def_nr];
+ }
+ else {
+ totweight--;
+ dv->dw[j] = dv->dw[totweight];
+ j--;
+ }
+ }
+ if (totweight != dv->totweight) {
+ if (totweight) {
+ dv->dw = MEM_reallocN(dv->dw, sizeof(*dv->dw) * totweight);
+ }
+ else {
+ MEM_SAFE_FREE(dv->dw);
+ }
+ dv->totweight = totweight;
+ }
+ }
+}
/**
* Get MDeformVert vgroup data from given object. Should only be used in Object mode.
@@ -542,7 +606,7 @@ bool *BKE_object_defgroup_validmap_get(Object *ob, const int defbase_tot)
BLI_ghash_insert(gh, dg->name, NULL);
}
- BLI_assert(BLI_ghash_size(gh) == defbase_tot);
+ BLI_assert(BLI_ghash_len(gh) == defbase_tot);
/* now loop through the armature modifiers and identify deform bones */
for (md = ob->modifiers.first; md; md = !md->next && step1 ? (step1 = 0), modifiers_getVirtualModifierList(ob, &virtualModifierData) : md->next) {
@@ -577,7 +641,7 @@ bool *BKE_object_defgroup_validmap_get(Object *ob, const int defbase_tot)
defgroup_validmap[i] = (BLI_ghash_lookup(gh, dg->name) != NULL);
}
- BLI_assert(i == BLI_ghash_size(gh));
+ BLI_assert(i == BLI_ghash_len(gh));
BLI_ghash_free(gh, NULL, NULL);
diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c
index 13589866e48..1b976fef166 100644
--- a/source/blender/blenkernel/intern/object_dupli.c
+++ b/source/blender/blenkernel/intern/object_dupli.c
@@ -74,6 +74,7 @@ typedef struct DupliContext {
bool do_update;
bool animated;
Group *group; /* XXX child objects are selected from this group if set, could be nicer */
+ Object *obedit; /* Only to check if the object is in edit-mode. */
Scene *scene;
ViewLayer *view_layer;
@@ -108,6 +109,7 @@ static void init_context(DupliContext *r_ctx, const EvaluationContext *eval_ctx,
r_ctx->group = NULL;
r_ctx->object = ob;
+ r_ctx->obedit = OBEDIT_FROM_OBACT(ob);
if (space_mat)
copy_m4_m4(r_ctx->space_mat, space_mat);
else
@@ -241,14 +243,13 @@ static bool is_child(const Object *ob, const Object *parent)
static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChildDuplisFunc make_child_duplis_cb)
{
Object *parent = ctx->object;
- Object *obedit = ctx->scene->obedit;
if (ctx->group) {
int groupid = 0;
- FOREACH_GROUP_BASE(ctx->group, base)
+ FOREACH_GROUP_BASE_BEGIN(ctx->group, base)
{
Object *ob = base->object;
- if ((base->flag & BASE_VISIBLED) && ob != obedit && is_child(ob, parent)) {
+ if ((base->flag & BASE_VISIBLED) && ob != ctx->obedit && is_child(ob, parent)) {
DupliContext pctx;
copy_dupli_context(&pctx, ctx, ctx->object, NULL, groupid, false);
@@ -267,7 +268,7 @@ static void make_child_duplis(const DupliContext *ctx, void *userdata, MakeChild
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->flag & BASE_VISIBLED) && ob != obedit && is_child(ob, parent)) {
+ if ((ob != ctx->obedit) && is_child(ob, parent)) {
DupliContext pctx;
copy_dupli_context(&pctx, ctx, ctx->object, NULL, baseid, false);
@@ -880,7 +881,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
BLI_srandom((unsigned int)(31415926 + psys->seed));
- if ((psys->renderdata || part->draw_as == PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
+ if ((for_render || part->draw_as == PART_DRAW_REND) && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)) {
ParticleSimulationData sim = {NULL};
sim.eval_ctx = ctx->eval_ctx;
sim.scene = scene;
@@ -931,12 +932,12 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
totgroup += dw->count;
}
else {
- FOREACH_GROUP_OBJECT(part->dup_group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(part->dup_group, object)
{
(void) object;
totgroup++;
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
/* we also copy the actual objects to restore afterwards, since
@@ -956,7 +957,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
}
else {
a = 0;
- FOREACH_GROUP_OBJECT(part->dup_group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(part->dup_group, object)
{
oblist[a] = object;
obcopylist[a] = *object;
@@ -966,7 +967,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
continue;
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
}
else {
@@ -1056,7 +1057,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
if (part->ren_as == PART_DRAW_GR && psys->part->draw & PART_DRAW_WHOLE_GR) {
b = 0;
- FOREACH_GROUP_OBJECT(part->dup_group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(part->dup_group, object)
{
copy_m4_m4(tmat, oblist[b]->obmat);
@@ -1081,7 +1082,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem
b++;
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
else {
/* to give ipos in object correct offset */
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 99291b14b88..10ccc9fb672 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -66,12 +66,11 @@
#include "MEM_guardedalloc.h"
#include "DEG_depsgraph.h"
-#define DEBUG_PRINT if (G.debug & G_DEBUG_DEPSGRAPH) printf
void BKE_object_eval_local_transform(const EvaluationContext *UNUSED(eval_ctx),
Object *ob)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob);
+ DEG_debug_print_eval(__func__, ob->id.name, ob);
/* calculate local matrix */
BKE_object_to_mat4(ob, ob->obmat);
@@ -89,7 +88,7 @@ void BKE_object_eval_parent(const EvaluationContext *UNUSED(eval_ctx),
float tmat[4][4];
float locmat[4][4];
- DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob);
+ DEG_debug_print_eval(__func__, ob->id.name, ob);
/* get local matrix (but don't calculate it, as that was done already!) */
// XXX: redundant?
@@ -118,7 +117,7 @@ void BKE_object_eval_constraints(const EvaluationContext *eval_ctx,
bConstraintOb *cob;
float ctime = BKE_scene_frame_get(scene);
- DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob);
+ DEG_debug_print_eval(__func__, ob->id.name, ob);
/* evaluate constraints stack */
/* TODO: split this into:
@@ -136,7 +135,7 @@ void BKE_object_eval_constraints(const EvaluationContext *eval_ctx,
void BKE_object_eval_done(const EvaluationContext *UNUSED(eval_ctx), Object *ob)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob);
+ DEG_debug_print_eval(__func__, ob->id.name, ob);
/* Set negative scale flag in object. */
if (is_negative_m4(ob->obmat)) ob->transflag |= OB_NEG_SCALE;
@@ -153,7 +152,7 @@ void BKE_object_handle_data_update(
Key *key;
float ctime = BKE_scene_frame_get(scene);
- if (G.debug & G_DEBUG_DEPSGRAPH)
+ if (G.debug & G_DEBUG_DEPSGRAPH_EVAL)
printf("recalcdata %s\n", ob->id.name + 2);
/* TODO(sergey): Only used by legacy depsgraph. */
@@ -174,7 +173,7 @@ void BKE_object_handle_data_update(
switch (ob->type) {
case OB_MESH:
{
- BMEditMesh *em = (ob == scene->obedit) ? BKE_editmesh_from_object(ob) : NULL;
+ BMEditMesh *em = (ob->mode & OB_MODE_EDIT) ? BKE_editmesh_from_object(ob) : NULL;
uint64_t data_mask = scene->customdata_mask | CD_MASK_BAREMESH;
#ifdef WITH_FREESTYLE
/* make sure Freestyle edge/face marks appear in DM for render (see T40315) */
@@ -224,7 +223,7 @@ void BKE_object_handle_data_update(
}
/* particles */
- if (ob != scene->obedit && ob->particlesystem.first) {
+ if (!(ob->mode & OB_MODE_EDIT) && ob->particlesystem.first) {
ParticleSystem *tpsys, *psys;
DerivedMesh *dm;
ob->transflag &= ~OB_DUPLIPARTS;
@@ -306,7 +305,7 @@ void BKE_object_eval_uber_data(const EvaluationContext *eval_ctx,
Scene *scene,
Object *ob)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, ob->id.name, ob);
+ DEG_debug_print_eval(__func__, ob->id.name, ob);
BLI_assert(ob->type != OB_ARMATURE);
BKE_object_handle_data_update(eval_ctx, scene, ob);
@@ -387,7 +386,7 @@ void BKE_object_eval_cloth(const EvaluationContext *UNUSED(eval_ctx),
Scene *scene,
Object *object)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, object->id.name, object);
+ DEG_debug_print_eval(__func__, object->id.name, object);
BKE_ptcache_object_reset(scene, object, PTCACHE_RESET_DEPSGRAPH);
}
@@ -410,7 +409,7 @@ void BKE_object_eval_transform_all(const EvaluationContext *eval_ctx,
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);
+ DEG_debug_print_eval(__func__, object->id.name, object);
if (object->type == OB_MESH) {
BKE_mesh_batch_cache_dirty(object->data, BKE_MESH_BATCH_DIRTY_SHADING);
}
@@ -419,7 +418,7 @@ void BKE_object_eval_update_shading(const EvaluationContext *UNUSED(eval_ctx),
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);
+ DEG_debug_print_eval(__func__, object_data->name, object_data);
switch (GS(object_data->name)) {
case ID_ME:
BKE_mesh_batch_cache_dirty((Mesh *)object_data,
@@ -442,10 +441,17 @@ void BKE_object_data_select_update(const EvaluationContext *UNUSED(eval_ctx),
}
}
-void BKE_object_eval_flush_base_flags(const EvaluationContext *UNUSED(eval_ctx),
- Object *object, Base *base, bool is_from_set)
+void BKE_object_eval_flush_base_flags(const EvaluationContext *eval_ctx,
+ Object *object, int base_index, bool is_from_set)
{
- DEBUG_PRINT("%s on %s (%p)\n", __func__, object->id.name, object);
+ ViewLayer *view_layer = eval_ctx->view_layer;
+ BLI_assert(view_layer->object_bases_array != NULL);
+ BLI_assert(base_index >= 0);
+ BLI_assert(base_index < MEM_allocN_len(view_layer->object_bases_array) / sizeof(Base *));
+ Base *base = view_layer->object_bases_array[base_index];
+ BLI_assert(base->object == object);
+
+ DEG_debug_print_eval(__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.
diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c
index 0b4bc39627e..2d8527f23d6 100644
--- a/source/blender/blenkernel/intern/ocean.c
+++ b/source/blender/blenkernel/intern/ocean.c
@@ -917,7 +917,7 @@ void BKE_ocean_init(struct Ocean *o, int M, int N, float Lx, float Lz, float V,
o->_fft_in = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_fft_in");
o->_htilda = (fftw_complex *)MEM_mallocN(o->_M * (1 + o->_N / 2) * sizeof(fftw_complex), "ocean_htilda");
- BLI_lock_thread(LOCK_FFTW);
+ BLI_thread_lock(LOCK_FFTW);
if (o->_do_disp_y) {
o->_disp_y = (double *)MEM_mallocN(o->_M * o->_N * sizeof(double), "ocean_disp_y");
@@ -963,7 +963,7 @@ void BKE_ocean_init(struct Ocean *o, int M, int N, float Lx, float Lz, float V,
o->_Jxz_plan = fftw_plan_dft_c2r_2d(o->_M, o->_N, o->_fft_in_jxz, o->_Jxz, FFTW_ESTIMATE);
}
- BLI_unlock_thread(LOCK_FFTW);
+ BLI_thread_unlock(LOCK_FFTW);
BLI_rw_mutex_unlock(&o->oceanmutex);
@@ -978,7 +978,7 @@ void BKE_ocean_free_data(struct Ocean *oc)
BLI_rw_mutex_lock(&oc->oceanmutex, THREAD_LOCK_WRITE);
- BLI_lock_thread(LOCK_FFTW);
+ BLI_thread_lock(LOCK_FFTW);
if (oc->_do_disp_y) {
fftw_destroy_plan(oc->_disp_y_plan);
@@ -1016,7 +1016,7 @@ void BKE_ocean_free_data(struct Ocean *oc)
MEM_freeN(oc->_Jxz);
}
- BLI_unlock_thread(LOCK_FFTW);
+ BLI_thread_unlock(LOCK_FFTW);
if (oc->_fft_in)
MEM_freeN(oc->_fft_in);
diff --git a/source/blender/blenkernel/intern/outliner_treehash.c b/source/blender/blenkernel/intern/outliner_treehash.c
index d9a602aa41e..9bbde607b80 100644
--- a/source/blender/blenkernel/intern/outliner_treehash.c
+++ b/source/blender/blenkernel/intern/outliner_treehash.c
@@ -133,7 +133,7 @@ static void fill_treehash(void *treehash, BLI_mempool *treestore)
void *BKE_outliner_treehash_create_from_treestore(BLI_mempool *treestore)
{
- GHash *treehash = BLI_ghash_new_ex(tse_hash, tse_cmp, "treehash", BLI_mempool_count(treestore));
+ GHash *treehash = BLI_ghash_new_ex(tse_hash, tse_cmp, "treehash", BLI_mempool_len(treestore));
fill_treehash(treehash, treestore);
return treehash;
}
@@ -147,7 +147,7 @@ void *BKE_outliner_treehash_rebuild_from_treestore(void *treehash, BLI_mempool *
{
BLI_assert(treehash);
- BLI_ghash_clear_ex(treehash, NULL, free_treehash_group, BLI_mempool_count(treestore));
+ BLI_ghash_clear_ex(treehash, NULL, free_treehash_group, BLI_mempool_len(treestore));
fill_treehash(treehash, treestore);
return treehash;
}
diff --git a/source/blender/blenkernel/intern/packedFile.c b/source/blender/blenkernel/intern/packedFile.c
index 35e2531675d..f17c10765b8 100644
--- a/source/blender/blenkernel/intern/packedFile.c
+++ b/source/blender/blenkernel/intern/packedFile.c
@@ -354,16 +354,15 @@ int writePackedFile(ReportList *reports, const char *filename, PackedFile *pf, i
return (ret_value);
}
-
-/*
+
+/**
* This function compares a packed file to a 'real' file.
* It returns an integer indicating if:
*
- * PF_EQUAL - the packed file and original file are identical
- * PF_DIFFERENT - the packed file and original file differ
- * PF_NOFILE - the original file doens't exist
+ * - PF_EQUAL: the packed file and original file are identical
+ * - PF_DIFFERENT: the packed file and original file differ
+ * - PF_NOFILE: the original file doens't exist
*/
-
int checkPackedFile(const char *filename, PackedFile *pf)
{
BLI_stat_t st;
diff --git a/source/blender/blenkernel/intern/paint.c b/source/blender/blenkernel/intern/paint.c
index 152a882de97..20375fe6953 100644
--- a/source/blender/blenkernel/intern/paint.c
+++ b/source/blender/blenkernel/intern/paint.c
@@ -41,6 +41,7 @@
#include "DNA_scene_types.h"
#include "DNA_brush_types.h"
#include "DNA_space_types.h"
+#include "DNA_workspace_types.h"
#include "BLI_bitmap.h"
#include "BLI_utildefines.h"
@@ -176,6 +177,8 @@ Paint *BKE_paint_get_active(Scene *sce, ViewLayer *view_layer)
if (ts->use_uv_sculpt)
return &ts->uvsculpt->paint;
return &ts->imapaint.paint;
+ default:
+ break;
}
}
@@ -376,7 +379,7 @@ void BKE_paint_curve_clamp_endpoint_add_index(PaintCurve *pc, const int add_inde
/* remove colour from palette. Must be certain color is inside the palette! */
void BKE_palette_color_remove(Palette *palette, PaletteColor *color)
{
- if (BLI_listbase_count_ex(&palette->colors, palette->active_color) == palette->active_color) {
+ if (BLI_listbase_count_at_most(&palette->colors, palette->active_color) == palette->active_color) {
palette->active_color--;
}
@@ -499,7 +502,7 @@ void BKE_paint_cavity_curve_preset(Paint *p, int preset)
curvemapping_changed(p->cavity_curve, false);
}
-short BKE_paint_object_mode_from_paint_mode(ePaintMode mode)
+eObjectMode BKE_paint_object_mode_from_paint_mode(ePaintMode mode)
{
switch (mode) {
case ePaintSculpt:
@@ -529,7 +532,7 @@ void BKE_paint_init(Scene *sce, ePaintMode mode, const char col[3])
/* If there's no brush, create one */
brush = BKE_paint_brush(paint);
if (brush == NULL) {
- short ob_mode = BKE_paint_object_mode_from_paint_mode(mode);
+ eObjectMode ob_mode = BKE_paint_object_mode_from_paint_mode(mode);
brush = BKE_brush_first_search(G.main, ob_mode);
if (!brush) {
@@ -902,7 +905,7 @@ void BKE_sculpt_update_mesh_elements(
if (!CustomData_has_layer(&me->ldata, CD_GRID_PAINT_MASK)) {
#if 1
BKE_sculpt_mask_layers_ensure(ob, mmd);
-#else /* if we wanted to support adding mask data while multi-res painting, we would need to do this */
+#else /* if we wanted to support adding mask data while multi-res painting, we would need to do this */
if ((ED_sculpt_mask_layers_ensure(ob, mmd) & ED_SCULPT_MASK_LAYER_CALC_LOOP)) {
/* remake the derived mesh */
ob->recalc |= OB_RECALC_DATA;
@@ -1064,3 +1067,39 @@ int BKE_sculpt_mask_layers_ensure(Object *ob, MultiresModifierData *mmd)
return ret;
}
+
+void BKE_sculpt_toolsettings_data_ensure(struct Scene *scene)
+{
+ Sculpt *sd = scene->toolsettings->sculpt;
+ if (sd == NULL) {
+ sd = scene->toolsettings->sculpt = MEM_callocN(sizeof(Sculpt), __func__);
+
+ /* Turn on X plane mirror symmetry by default */
+ sd->paint.symmetry_flags |= PAINT_SYMM_X;
+ sd->paint.flags |= PAINT_SHOW_BRUSH;
+
+ /* Make sure at least dyntopo subdivision is enabled */
+ sd->flags |= SCULPT_DYNTOPO_SUBDIVIDE | SCULPT_DYNTOPO_COLLAPSE;
+ }
+
+ if (!sd->detail_size) {
+ sd->detail_size = 12;
+ }
+ if (!sd->detail_percent) {
+ sd->detail_percent = 25;
+ }
+ if (sd->constant_detail == 0.0f) {
+ sd->constant_detail = 3.0f;
+ }
+
+ /* Set sane default tiling offsets */
+ if (!sd->paint.tile_offset[0]) {
+ sd->paint.tile_offset[0] = 1.0f;
+ }
+ if (!sd->paint.tile_offset[1]) {
+ sd->paint.tile_offset[1] = 1.0f;
+ }
+ if (!sd->paint.tile_offset[2]) {
+ sd->paint.tile_offset[2] = 1.0f;
+ }
+}
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index e23ca3eaa09..713d523cb1e 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -87,9 +87,12 @@
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_query.h"
#include "RE_render_ext.h"
+#include "particle_private.h"
+
unsigned int PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT];
unsigned int PSYS_FRAND_SEED_MULTIPLIER[PSYS_FRAND_COUNT];
float PSYS_FRAND_BASE[PSYS_FRAND_COUNT];
@@ -109,9 +112,6 @@ static void get_child_modifier_parameters(ParticleSettings *part, ParticleThread
ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex);
static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSettings *part, ParticleData *par,
int child_index, int face_index, const float fw[4], float *orco, ParticleTexture *ptex, int event, float cfra);
-extern void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim,
- ParticleTexture *ptex, const float par_co[3], const float par_vel[3], const float par_rot[4], const float par_orco[3],
- ChildParticle *cpa, const float orco[3], float mat[4][4], ParticleKey *state, float t);
/* few helpers for countall etc. */
int count_particles(ParticleSystem *psys)
@@ -252,7 +252,7 @@ struct LatticeDeformData *psys_create_lattice_deform_data(ParticleSimulationData
{
struct LatticeDeformData *lattice_deform_data = NULL;
- if (psys_in_edit_mode(sim->eval_ctx->view_layer, sim->psys) == 0) {
+ if (psys_in_edit_mode(sim->eval_ctx->depsgraph, sim->psys) == 0) {
Object *lattice = NULL;
ModifierData *md = (ModifierData *)psys_get_modifier(sim->ob, sim->psys);
int mode = G.is_rendering ? eModifierMode_Render : eModifierMode_Realtime;
@@ -289,13 +289,16 @@ void psys_enable_all(Object *ob)
psys->flag &= ~PSYS_DISABLED;
}
-bool psys_in_edit_mode(ViewLayer *view_layer, ParticleSystem *psys)
+bool psys_in_edit_mode(Depsgraph *depsgraph, ParticleSystem *psys)
{
+ ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
+ const bool use_render_params = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
+
return (view_layer->basact &&
(view_layer->basact->object->mode & OB_MODE_PARTICLE_EDIT) &&
psys == psys_get_current((view_layer->basact)->object) &&
(psys->edit || psys->pointcache->edit) &&
- !psys->renderdata);
+ !use_render_params);
}
bool psys_check_enabled(Object *ob, ParticleSystem *psys, const bool use_render_params)
@@ -306,7 +309,7 @@ bool psys_check_enabled(Object *ob, ParticleSystem *psys, const bool use_render_
return 0;
psmd = psys_get_modifier(ob, psys);
- if (psys->renderdata || use_render_params) {
+ if (use_render_params) {
if (!(psmd->modifier.mode & eModifierMode_Render))
return 0;
}
@@ -351,7 +354,7 @@ void psys_check_group_weights(ParticleSettings *part)
}
/* then add objects in the group to new list */
- FOREACH_GROUP_OBJECT(part->dup_group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(part->dup_group, object)
{
dw = part->dupliweights.first;
while (dw && dw->ob != object) {
@@ -365,7 +368,7 @@ void psys_check_group_weights(ParticleSettings *part)
BLI_addtail(&part->dupliweights, dw);
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
dw = part->dupliweights.first;
for (; dw; dw = dw->next) {
@@ -413,6 +416,8 @@ void BKE_particlesettings_free(ParticleSettings *part)
curvemapping_free(part->clumpcurve);
if (part->roughcurve)
curvemapping_free(part->roughcurve);
+ if (part->twistcurve)
+ curvemapping_free(part->twistcurve);
free_partdeflect(part->pd);
free_partdeflect(part->pd2);
@@ -621,204 +626,6 @@ void psys_free(Object *ob, ParticleSystem *psys)
}
/************************************************/
-/* Rendering */
-/************************************************/
-/* these functions move away particle data and bring it back after
- * rendering, to make different render settings possible without
- * removing the previous data. this should be solved properly once */
-
-void psys_render_set(Object *ob, ParticleSystem *psys, float viewmat[4][4], float winmat[4][4], int winx, int winy, int timeoffset)
-{
- ParticleRenderData *data;
- ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
-
- if (psys->renderdata)
- return;
-
- data = MEM_callocN(sizeof(ParticleRenderData), "ParticleRenderData");
-
- data->child = psys->child;
- data->totchild = psys->totchild;
- data->pathcache = psys->pathcache;
- data->pathcachebufs.first = psys->pathcachebufs.first;
- data->pathcachebufs.last = psys->pathcachebufs.last;
- data->totcached = psys->totcached;
- data->childcache = psys->childcache;
- data->childcachebufs.first = psys->childcachebufs.first;
- data->childcachebufs.last = psys->childcachebufs.last;
- data->totchildcache = psys->totchildcache;
-
- if (psmd->dm_final) {
- data->dm = CDDM_copy_with_tessface(psmd->dm_final);
- }
- data->totdmvert = psmd->totdmvert;
- data->totdmedge = psmd->totdmedge;
- data->totdmface = psmd->totdmface;
-
- psys->child = NULL;
- psys->pathcache = NULL;
- psys->childcache = NULL;
- psys->totchild = psys->totcached = psys->totchildcache = 0;
- BLI_listbase_clear(&psys->pathcachebufs);
- BLI_listbase_clear(&psys->childcachebufs);
-
- copy_m4_m4(data->winmat, winmat);
- mul_m4_m4m4(data->viewmat, viewmat, ob->obmat);
- mul_m4_m4m4(data->mat, winmat, data->viewmat);
- data->winx = winx;
- data->winy = winy;
-
- data->timeoffset = timeoffset;
-
- psys->renderdata = data;
-
- /* Hair can and has to be recalculated if everything isn't displayed. */
- if (psys->part->disp != 100 && ELEM(psys->part->type, PART_HAIR, PART_FLUID)) {
- psys->recalc |= PSYS_RECALC_RESET;
- }
-}
-
-void psys_render_restore(Object *ob, ParticleSystem *psys)
-{
- ParticleRenderData *data;
- ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
- float render_disp = psys_get_current_display_percentage(psys);
- float disp;
-
- data = psys->renderdata;
- if (!data)
- return;
-
- if (data->elems)
- MEM_freeN(data->elems);
-
- if (psmd->dm_final) {
- psmd->dm_final->needsFree = 1;
- psmd->dm_final->release(psmd->dm_final);
- }
- if (psmd->dm_deformed) {
- psmd->dm_deformed->needsFree = 1;
- psmd->dm_deformed->release(psmd->dm_deformed);
- psmd->dm_deformed = NULL;
- }
-
- psys_free_path_cache(psys, NULL);
-
- if (psys->child) {
- MEM_freeN(psys->child);
- psys->child = 0;
- psys->totchild = 0;
- }
-
- psys->child = data->child;
- psys->totchild = data->totchild;
- psys->pathcache = data->pathcache;
- psys->pathcachebufs.first = data->pathcachebufs.first;
- psys->pathcachebufs.last = data->pathcachebufs.last;
- psys->totcached = data->totcached;
- psys->childcache = data->childcache;
- psys->childcachebufs.first = data->childcachebufs.first;
- psys->childcachebufs.last = data->childcachebufs.last;
- psys->totchildcache = data->totchildcache;
-
- psmd->dm_final = data->dm;
- psmd->totdmvert = data->totdmvert;
- psmd->totdmedge = data->totdmedge;
- psmd->totdmface = data->totdmface;
- psmd->flag &= ~eParticleSystemFlag_psys_updated;
-
- if (psmd->dm_final) {
- if (!psmd->dm_final->deformedOnly) {
- if (ob->derivedDeform) {
- psmd->dm_deformed = CDDM_copy(ob->derivedDeform);
- }
- else {
- psmd->dm_deformed = CDDM_from_mesh((Mesh *)ob->data);
- }
- DM_ensure_tessface(psmd->dm_deformed);
- }
- psys_calc_dmcache(ob, psmd->dm_final, psmd->dm_deformed, psys);
- }
-
- MEM_freeN(data);
- psys->renderdata = NULL;
-
- /* restore particle display percentage */
- disp = psys_get_current_display_percentage(psys);
-
- if (disp != render_disp) {
- /* Hair can and has to be recalculated if everything isn't displayed. */
- if (ELEM(psys->part->type, PART_HAIR, PART_FLUID)) {
- psys->recalc |= PSYS_RECALC_RESET;
- }
- else {
- PARTICLE_P;
-
- LOOP_PARTICLES {
- if (psys_frand(psys, p) > disp)
- pa->flag |= PARS_NO_DISP;
- else
- pa->flag &= ~PARS_NO_DISP;
- }
- }
- }
-}
-
-bool psys_render_simplify_params(ParticleSystem *psys, ChildParticle *cpa, float *params)
-{
- ParticleRenderData *data;
- ParticleRenderElem *elem;
- float x, w, scale, alpha, lambda, t, scalemin, scalemax;
- int b;
-
- if (!(psys->renderdata && (psys->part->simplify_flag & PART_SIMPLIFY_ENABLE)))
- return false;
-
- data = psys->renderdata;
- if (!data->do_simplify)
- return false;
- b = (data->index_mf_to_mpoly) ? DM_origindex_mface_mpoly(data->index_mf_to_mpoly, data->index_mp_to_orig, cpa->num) : cpa->num;
- if (b == ORIGINDEX_NONE) {
- return false;
- }
-
- elem = &data->elems[b];
-
- lambda = elem->lambda;
- t = elem->t;
- scalemin = elem->scalemin;
- scalemax = elem->scalemax;
-
- if (!elem->reduce) {
- scale = scalemin;
- alpha = 1.0f;
- }
- else {
- x = (elem->curchild + 0.5f) / elem->totchild;
- if (x < lambda - t) {
- scale = scalemax;
- alpha = 1.0f;
- }
- else if (x >= lambda + t) {
- scale = scalemin;
- alpha = 0.0f;
- }
- else {
- w = (lambda + t - x) / (2.0f * t);
- scale = scalemin + (scalemax - scalemin) * w;
- alpha = w;
- }
- }
-
- params[0] = scale;
- params[1] = alpha;
-
- elem->curchild++;
-
- return 1;
-}
-
-/************************************************/
/* Interpolation */
/************************************************/
static float interpolate_particle_value(float v1, float v2, float v3, float v4, const float w[4], int four)
@@ -1811,11 +1618,6 @@ void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int in
/* Path Cache */
/************************************************/
-extern void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3], const float par_rot[4], float time, float freq, float shape, float amplitude, float flat,
- short type, short axis, float obmat[4][4], int smooth_start);
-extern float do_clump(ParticleKey *state, const float par_co[3], float time, const float orco_offset[3], float clumpfac, float clumppow, float pa_clump,
- bool use_clump_noise, float clump_noise_size, CurveMapping *clumpcurve);
-
void precalc_guides(ParticleSimulationData *sim, ListBase *effectors)
{
EffectedPoint point;
@@ -2059,7 +1861,7 @@ void psys_find_parents(ParticleSimulationData *sim, const bool use_render_params
int from = PART_FROM_FACE;
totparent = (int)(totchild * part->parents * 0.3f);
- if ((sim->psys->renderdata || use_render_params) && part->child_nbr && part->ren_child_nbr)
+ if (use_render_params && part->child_nbr && part->ren_child_nbr)
totparent *= (float)part->child_nbr / (float)part->ren_child_nbr;
/* hard limit, workaround for it being ignored above */
@@ -2103,10 +1905,10 @@ static bool psys_thread_context_init_path(
psys_thread_context_init(ctx, sim);
/*---start figuring out what is actually wanted---*/
- if (psys_in_edit_mode(sim->eval_ctx->view_layer, psys)) {
+ if (psys_in_edit_mode(sim->eval_ctx->depsgraph, psys)) {
ParticleEditSettings *pset = &scene->toolsettings->particle;
- if ((psys->renderdata == 0 && use_render_params == 0) && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0)
+ if ((use_render_params == 0) && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0)
totchild = 0;
segments = 1 << pset->draw_step;
@@ -2115,14 +1917,14 @@ static bool psys_thread_context_init_path(
if (totchild && part->childtype == PART_CHILD_FACES) {
totparent = (int)(totchild * part->parents * 0.3f);
- if ((psys->renderdata || use_render_params) && part->child_nbr && part->ren_child_nbr)
+ if (use_render_params && part->child_nbr && part->ren_child_nbr)
totparent *= (float)part->child_nbr / (float)part->ren_child_nbr;
/* part->parents could still be 0 so we can't test with totparent */
between = 1;
}
- if (psys->renderdata || use_render_params)
+ if (use_render_params)
segments = 1 << part->ren_step;
else {
totchild = (int)((float)totchild * (float)part->disp / 100.0f);
@@ -2154,6 +1956,7 @@ static bool psys_thread_context_init_path(
ctx->vg_rough1 = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_ROUGH1);
ctx->vg_rough2 = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_ROUGH2);
ctx->vg_roughe = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_ROUGHE);
+ ctx->vg_twist = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_TWIST);
if (psys->part->flag & PART_CHILD_EFFECT)
ctx->vg_effector = psys_cache_vgroup(ctx->dm, psys, PSYS_VG_EFFECTOR);
@@ -2172,6 +1975,13 @@ static bool psys_thread_context_init_path(
else {
ctx->roughcurve = NULL;
}
+ if ((part->child_flag & PART_CHILD_USE_TWIST_CURVE) && part->twistcurve) {
+ ctx->twistcurve = curvemapping_copy(part->twistcurve);
+ curvemapping_changed_all(ctx->twistcurve);
+ }
+ else {
+ ctx->twistcurve = NULL;
+ }
return true;
}
@@ -2192,7 +2002,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.eval_ctx->view_layer, psys) && psys->edit ? psys->edit->pathcache : psys->pathcache;
+ ParticleCacheKey **pcache = psys_in_edit_mode(ctx->sim.eval_ctx->depsgraph, psys) && psys->edit ? psys->edit->pathcache : psys->pathcache;
ParticleCacheKey *child, *key[4];
ParticleTexture ptex;
float *cpa_fuv = 0, *par_rot = 0, rot[4];
@@ -2316,7 +2126,19 @@ static void psys_thread_create_path(ParticleTask *task, struct ChildParticle *cp
/* get the original coordinates (orco) for texture usage */
cpa_from = part->from;
- cpa_num = pa->num;
+
+ /*
+ * NOTE: Should in theory be the same as:
+ cpa_num = psys_particle_dm_face_lookup(
+ ctx->sim.psmd->dm_final,
+ ctx->sim.psmd->dm_deformed,
+ pa->num, pa->fuv,
+ NULL);
+ */
+ cpa_num = (ELEM(pa->num_dmcache, DMCACHE_ISCHILD, DMCACHE_NOTFOUND))
+ ? pa->num
+ : pa->num_dmcache;
+
/* XXX hack to avoid messed up particle num and subsequent crash (#40733) */
if (cpa_num > ctx->sim.psmd->dm_final->getNumTessFaces(ctx->sim.psmd->dm_final))
cpa_num = 0;
@@ -2569,7 +2391,9 @@ static void cache_key_incremental_rotation(ParticleCacheKey *key0, ParticleCache
void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_render_params)
{
PARTICLE_PSMD;
+#if 0
ParticleEditSettings *pset = &sim->scene->toolsettings->particle;
+#endif
ParticleSystem *psys = sim->psys;
ParticleSettings *part = psys->part;
ParticleCacheKey *ca, **cache;
@@ -2590,7 +2414,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re
float prev_tangent[3] = {0.0f, 0.0f, 0.0f}, hairmat[4][4];
float rotmat[3][3];
int k;
- int segments = (int)pow(2.0, (double)((psys->renderdata || use_render_params) ? part->ren_step : part->draw_step));
+ int segments = (int)pow(2.0, (double)((use_render_params) ? part->ren_step : part->draw_step));
int totpart = psys->totpart;
float length, vec[3];
float *vg_effector = NULL;
@@ -2601,9 +2425,11 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re
if ((psys->flag & PSYS_HAIR_DONE || psys->flag & PSYS_KEYED || psys->pointcache) == 0)
return;
- if (psys_in_edit_mode(sim->eval_ctx->view_layer, psys))
- if (psys->renderdata == 0 && (psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0)
+#if 0 /* TODO(mai): something is very wrong with these conditionals, they dont make sense and the cache isnt updating */
+ if (psys_in_edit_mode(sim->eval_ctx->depsgraph, psys))
+ if ((psys->edit == NULL || pset->flag & PE_DRAW_PART) == 0)
return;
+#endif
keyed = psys->flag & PSYS_KEYED;
baked = psys->pointcache->mem_cache.first && psys->part->type != PART_HAIR;
@@ -3164,7 +2990,7 @@ ModifierData *object_add_particle_system(Scene *scene, Object *ob, const char *n
psys->part = BKE_particlesettings_add(NULL, DATA_("ParticleSettings"));
- if (BLI_listbase_count_ex(&ob->particlesystem, 2) > 1)
+ if (BLI_listbase_count_at_most(&ob->particlesystem, 2) > 1)
BLI_snprintf(psys->name, sizeof(psys->name), DATA_("ParticleSystem %i"), BLI_listbase_count(&ob->particlesystem));
else
BLI_strncpy(psys->name, DATA_("ParticleSystem"), sizeof(psys->name));
@@ -3307,11 +3133,6 @@ static void default_particle_settings(ParticleSettings *part)
part->color_vec_max = 1.f;
part->draw_col = PART_DRAW_COL_MAT;
- part->simplify_refsize = 1920;
- part->simplify_rate = 1.0f;
- part->simplify_transition = 0.1f;
- part->simplify_viewport = 0.8;
-
if (!part->effector_weights)
part->effector_weights = BKE_add_effector_weights(NULL);
@@ -3359,6 +3180,18 @@ void BKE_particlesettings_rough_curve_init(ParticleSettings *part)
part->roughcurve = cumap;
}
+void BKE_particlesettings_twist_curve_init(ParticleSettings *part)
+{
+ CurveMapping *cumap = curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+
+ cumap->cm[0].curve[0].x = 0.0f;
+ cumap->cm[0].curve[0].y = 1.0f;
+ cumap->cm[0].curve[1].x = 1.0f;
+ cumap->cm[0].curve[1].y = 1.0f;
+
+ part->twistcurve = cumap;
+}
+
/**
* Only copy internal data of ParticleSettings 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.
@@ -3381,6 +3214,9 @@ void BKE_particlesettings_copy_data(
if (part_src->roughcurve) {
part_dst->roughcurve = curvemapping_copy(part_src->roughcurve);
}
+ if (part_src->twistcurve) {
+ part_dst->twistcurve = curvemapping_copy(part_src->twistcurve);
+ }
part_dst->boids = boid_copy_settings(part_src->boids);
@@ -3500,6 +3336,7 @@ static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSetti
ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp =
ptex->gravity = ptex->field = ptex->time = ptex->clump = ptex->kink_freq = ptex->kink_amp =
ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.0f;
+ ptex->twist = 1.0f;
ptex->length = 1.0f - part->randlength * psys_frand(psys, child_index + 26);
ptex->length *= part->clength_thres < psys_frand(psys, child_index + 27) ? part->clength : 1.0f;
@@ -3552,6 +3389,7 @@ static void get_cpa_texture(DerivedMesh *dm, ParticleSystem *psys, ParticleSetti
SET_PARTICLE_TEXTURE(PAMAP_KINK_AMP, ptex->kink_amp, mtex->kinkampfac);
SET_PARTICLE_TEXTURE(PAMAP_KINK_FREQ, ptex->kink_freq, mtex->kinkfac);
SET_PARTICLE_TEXTURE(PAMAP_DENS, ptex->exist, mtex->padensfac);
+ SET_PARTICLE_TEXTURE(PAMAP_TWIST, ptex->twist, mtex->twistfac);
}
}
@@ -3577,6 +3415,7 @@ void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTex
ptex->ivel = ptex->life = ptex->exist = ptex->size = ptex->damp =
ptex->gravity = ptex->field = ptex->length = ptex->clump = ptex->kink_freq = ptex->kink_amp =
ptex->effector = ptex->rough1 = ptex->rough2 = ptex->roughe = 1.0f;
+ ptex->twist = 1.0f;
ptex->time = (float)(pa - sim->psys->particles) / (float)sim->psys->totpart;
@@ -3651,6 +3490,7 @@ void psys_get_texture(ParticleSimulationData *sim, ParticleData *pa, ParticleTex
SET_PARTICLE_TEXTURE(PAMAP_GRAVITY, ptex->gravity, mtex->gravityfac);
SET_PARTICLE_TEXTURE(PAMAP_DAMP, ptex->damp, mtex->dampfac);
SET_PARTICLE_TEXTURE(PAMAP_LENGTH, ptex->length, mtex->lengthfac);
+ SET_PARTICLE_TEXTURE(PAMAP_TWIST, ptex->twist, mtex->twistfac);
}
}
@@ -3742,6 +3582,8 @@ static void get_child_modifier_parameters(ParticleSettings *part, ParticleThread
ptex->roughe *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_roughe);
if (ctx->vg_effector)
ptex->effector *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_effector);
+ if (ctx->vg_twist)
+ ptex->twist *= psys_interpolate_value_from_verts(ctx->dm, cpa_from, cpa_num, cpa_fuv, ctx->vg_twist);
}
/* get's hair (or keyed) particles state at the "path time" specified in state->time */
void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *state, const bool vel)
@@ -3794,7 +3636,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->eval_ctx->view_layer, psys) ? NULL : psys->hair_out_dm;
+ pind.dm = psys_in_edit_mode(sim->eval_ctx->depsgraph, psys) ? NULL : psys->hair_out_dm;
init_particle_interpolation(sim->ob, psys, pa, &pind);
do_particle_interpolation(psys, p, pa, t, &pind, state);
@@ -3947,7 +3789,18 @@ void psys_get_particle_on_path(ParticleSimulationData *sim, int p, ParticleKey *
copy_particle_key(&tstate, state, 1);
/* apply different deformations to the child path */
- do_child_modifiers(NULL, sim, &ptex, par->co, par->vel, par->rot, par_orco, cpa, orco, hairmat, state, t);
+ ParticleChildModifierContext modifier_ctx = {NULL};
+ modifier_ctx.thread_ctx = NULL;
+ modifier_ctx.sim = sim;
+ modifier_ctx.ptex = &ptex;
+ modifier_ctx.cpa = cpa;
+ modifier_ctx.orco = orco;
+ modifier_ctx.par_co = par->co;
+ modifier_ctx.par_vel = par->vel;
+ modifier_ctx.par_rot = par->rot;
+ modifier_ctx.par_orco = par_orco;
+ modifier_ctx.parent_keys = psys->childcache ? psys->childcache[p - totpart] : NULL;
+ do_child_modifiers(&modifier_ctx, hairmat, state, t);
/* try to estimate correct velocity */
if (vel) {
@@ -4050,7 +3903,19 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta
CLAMP(t, 0.0f, 1.0f);
unit_m4(mat);
- do_child_modifiers(NULL, sim, NULL, key1->co, key1->vel, key1->rot, par_orco, cpa, cpa->fuv, mat, state, t);
+ ParticleChildModifierContext modifier_ctx = {NULL};
+ modifier_ctx.thread_ctx = NULL;
+ modifier_ctx.sim = sim;
+ modifier_ctx.ptex = NULL;
+ modifier_ctx.cpa = cpa;
+ modifier_ctx.orco = cpa->fuv;
+ modifier_ctx.par_co = key1->co;
+ modifier_ctx.par_vel = key1->vel;
+ modifier_ctx.par_rot = key1->rot;
+ modifier_ctx.par_orco = par_orco;
+ modifier_ctx.parent_keys = psys->childcache ? psys->childcache[p - totpart] : NULL;
+
+ do_child_modifiers(&modifier_ctx, mat, state, t);
if (psys->lattice_deform_data)
calc_latt_deform(psys->lattice_deform_data, state->co, psys->lattice_strength);
diff --git a/source/blender/blenkernel/intern/particle_child.c b/source/blender/blenkernel/intern/particle_child.c
index d2ad05c20b7..c2640e9b9e2 100644
--- a/source/blender/blenkernel/intern/particle_child.c
+++ b/source/blender/blenkernel/intern/particle_child.c
@@ -37,15 +37,9 @@
#include "BKE_colortools.h"
#include "BKE_particle.h"
-struct Material;
+#include "particle_private.h"
-void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3], const float par_rot[4], float time, float freq, float shape, float amplitude, float flat,
- short type, short axis, float obmat[4][4], int smooth_start);
-float do_clump(ParticleKey *state, const float par_co[3], float time, const float orco_offset[3], float clumpfac, float clumppow, float pa_clump,
- bool use_clump_noise, float clump_noise_size, CurveMapping *clumpcurve);
-void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim,
- ParticleTexture *ptex, const float par_co[3], const float par_vel[3], const float par_rot[4], const float par_orco[3],
- ChildParticle *cpa, const float orco[3], float mat[4][4], ParticleKey *state, float t);
+struct Material;
static void get_strand_normal(Material *ma, const float surfnor[3], float surfdist, float nor[3])
{
@@ -67,7 +61,7 @@ static void get_strand_normal(Material *ma, const float surfnor[3], float surfdi
else {
copy_v3_v3(vnor, nor);
}
-
+
if (ma->strand_surfnor > 0.0f) {
if (ma->strand_surfnor > surfdist) {
blend = (ma->strand_surfnor - surfdist) / ma->strand_surfnor;
@@ -85,7 +79,7 @@ typedef struct ParticlePathIterator {
ParticleCacheKey *key;
int index;
float time;
-
+
ParticleCacheKey *parent_key;
float parent_rotation[4];
} ParticlePathIterator;
@@ -94,11 +88,11 @@ static void psys_path_iter_get(ParticlePathIterator *iter, ParticleCacheKey *key
ParticleCacheKey *parent, int index)
{
BLI_assert(index >= 0 && index < totkeys);
-
+
iter->key = keys + index;
iter->index = index;
iter->time = (float)index / (float)(totkeys - 1);
-
+
if (parent) {
iter->parent_key = parent + index;
if (index > 0)
@@ -114,7 +108,7 @@ static void psys_path_iter_get(ParticlePathIterator *iter, ParticleCacheKey *key
typedef struct ParticlePathModifier {
struct ParticlePathModifier *next, *prev;
-
+
void (*apply)(ParticleCacheKey *keys, int totkeys, ParticleCacheKey *parent_keys);
} ParticlePathModifier;
@@ -133,7 +127,7 @@ static void do_kink_spiral_deform(ParticleKey *state, const float dir[3], const
{
/* Creates a logarithmic spiral:
* r(theta) = a * exp(b * theta)
- *
+ *
* The "density" parameter b is defined by the shape parameter
* and goes up to the Golden Spiral for 1.0
* https://en.wikipedia.org/wiki/Golden_spiral
@@ -142,33 +136,33 @@ static void do_kink_spiral_deform(ParticleKey *state, const float dir[3], const
/* angle of the spiral against the curve (rotated opposite to make a smooth transition) */
const float start_angle = ((b != 0.0f) ? atanf(1.0f / b) :
(float)-M_PI_2) + (b > 0.0f ? -(float)M_PI_2 : (float)M_PI_2);
-
+
float spiral_axis[3], rot[3][3];
float vec[3];
-
+
float theta = freq * time * 2.0f * (float)M_PI;
float radius = amplitude * expf(b * theta);
-
+
/* a bit more intuitive than using negative frequency for this */
if (amplitude < 0.0f)
theta = -theta;
-
+
cross_v3_v3v3(spiral_axis, dir, kink);
normalize_v3(spiral_axis);
-
+
mul_v3_v3fl(vec, kink, -radius);
-
+
axis_angle_normalized_to_mat3(rot, spiral_axis, theta);
mul_m3_v3(rot, vec);
-
+
madd_v3_v3fl(vec, kink, amplitude);
-
+
axis_angle_normalized_to_mat3(rot, spiral_axis, -start_angle);
mul_m3_v3(rot, vec);
-
+
add_v3_v3v3(result, spiral_start, vec);
}
-
+
copy_v3_v3(state->co, result);
}
@@ -180,7 +174,7 @@ static void do_kink_spiral(ParticleThreadContext *ctx, ParticleTexture *ptex, co
const int seed = ctx->sim.psys->child_seed + (int)(cpa - ctx->sim.psys->child);
const int totkeys = ctx->segments + 1;
const int extrakeys = ctx->extra_segments;
-
+
float kink_amp_random = part->kink_amp_random;
float kink_amp = part->kink_amp * (1.0f - kink_amp_random * psys_frand(ctx->sim.psys, 93541 + seed));
float kink_freq = part->kink_freq;
@@ -189,11 +183,11 @@ static void do_kink_spiral(ParticleThreadContext *ctx, ParticleTexture *ptex, co
float rough1 = part->rough1;
float rough2 = part->rough2;
float rough_end = part->rough_end;
-
+
ParticlePathIterator iter;
ParticleCacheKey *key;
int k;
-
+
float dir[3];
float spiral_start[3] = {0.0f, 0.0f, 0.0f};
float spiral_start_time = 0.0f;
@@ -204,7 +198,7 @@ static void do_kink_spiral(ParticleThreadContext *ctx, ParticleTexture *ptex, co
float cut_time;
int start_index = 0, end_index = 0;
float kink_base[3];
-
+
if (ptex) {
kink_amp *= ptex->kink_amp;
kink_freq *= ptex->kink_freq;
@@ -212,44 +206,53 @@ static void do_kink_spiral(ParticleThreadContext *ctx, ParticleTexture *ptex, co
rough2 *= ptex->rough2;
rough_end *= ptex->roughe;
}
-
+
cut_time = (totkeys - 1) * ptex->length;
zero_v3(spiral_start);
-
+
for (k = 0, key = keys; k < totkeys-1; k++, key++) {
if ((float)(k + 1) >= cut_time) {
float fac = cut_time - (float)k;
ParticleCacheKey *par = parent_keys + k;
-
+
start_index = k + 1;
end_index = start_index + extrakeys;
-
+
spiral_start_time = ((float)k + fac) / (float)(totkeys - 1);
interp_v3_v3v3(spiral_start, key->co, (key+1)->co, fac);
-
+
interp_v3_v3v3(spiral_par_co, par->co, (par+1)->co, fac);
interp_v3_v3v3(spiral_par_vel, par->vel, (par+1)->vel, fac);
interp_qt_qtqt(spiral_par_rot, par->rot, (par+1)->rot, fac);
-
+
break;
}
}
-
+
zero_v3(dir);
-
+
zero_v3(kink_base);
kink_base[part->kink_axis] = 1.0f;
mul_mat3_m4_v3(ctx->sim.ob->obmat, kink_base);
-
+
+ /* Fill in invariant part of modifier context. */
+ ParticleChildModifierContext modifier_ctx = {NULL};
+ modifier_ctx.thread_ctx = ctx;
+ modifier_ctx.sim = &ctx->sim;
+ modifier_ctx.ptex = ptex;
+ modifier_ctx.cpa = cpa;
+ modifier_ctx.orco = orco;
+ modifier_ctx.parent_keys = parent_keys;
+
for (k = 0, key = keys; k < end_index; k++, key++) {
float par_time;
float *par_co, *par_vel, *par_rot;
-
+
psys_path_iter_get(&iter, keys, end_index, NULL, k);
if (k < start_index) {
sub_v3_v3v3(dir, (key+1)->co, key->co);
normalize_v3(dir);
-
+
par_time = (float)k / (float)(totkeys - 1);
par_co = parent_keys[k].co;
par_vel = parent_keys[k].vel;
@@ -258,36 +261,42 @@ static void do_kink_spiral(ParticleThreadContext *ctx, ParticleTexture *ptex, co
else {
float spiral_time = (float)(k - start_index) / (float)(extrakeys-1);
float kink[3], tmp[3];
-
+
/* use same time value for every point on the spiral */
par_time = spiral_start_time;
par_co = spiral_par_co;
par_vel = spiral_par_vel;
par_rot = spiral_par_rot;
-
+
project_v3_v3v3(tmp, kink_base, dir);
sub_v3_v3v3(kink, kink_base, tmp);
normalize_v3(kink);
-
+
if (kink_axis_random > 0.0f) {
float a = kink_axis_random * (psys_frand(ctx->sim.psys, 7112 + seed) * 2.0f - 1.0f) * (float)M_PI;
float rot[3][3];
-
+
axis_angle_normalized_to_mat3(rot, dir, a);
mul_m3_v3(rot, kink);
}
-
+
do_kink_spiral_deform((ParticleKey *)key, dir, kink, spiral_time, kink_freq, kink_shape, kink_amp, spiral_start);
}
-
- /* apply different deformations to the child path */
- do_child_modifiers(ctx, &ctx->sim, ptex, par_co, par_vel, par_rot, parent_orco, cpa, orco, hairmat, (ParticleKey *)key, par_time);
+
+ /* Fill in variant part of modifier context. */
+ modifier_ctx.par_co = par_co;
+ modifier_ctx.par_vel = par_vel;
+ modifier_ctx.par_rot = par_rot;
+ modifier_ctx.par_orco = parent_orco;
+
+ /* Apply different deformations to the child path/ */
+ do_child_modifiers(&modifier_ctx, hairmat, (ParticleKey *)key, par_time);
}
-
+
totlen = 0.0f;
for (k = 0, key = keys; k < end_index-1; k++, key++)
totlen += len_v3v3((key+1)->co, key->co);
-
+
*r_totkeys = end_index;
*r_max_length = totlen;
}
@@ -318,12 +327,12 @@ void psys_apply_child_modifiers(ParticleThreadContext *ctx, struct ListBase *mod
struct Material *ma = ctx->ma;
const bool draw_col_ma = (part->draw_col == PART_DRAW_COL_MAT);
const bool use_length_check = !ELEM(part->kink, PART_KINK_SPIRAL);
-
+
ParticlePathModifier *mod;
ParticleCacheKey *key;
int totkeys, k;
float max_length;
-
+
#if 0 /* TODO for the future: use true particle modifiers that work on the whole curve */
for (mod = modifiers->first; mod; mod = mod->next) {
mod->apply(keys, totkeys, parent_keys);
@@ -331,25 +340,38 @@ void psys_apply_child_modifiers(ParticleThreadContext *ctx, struct ListBase *mod
#else
(void)modifiers;
(void)mod;
-
+
if (part->kink == PART_KINK_SPIRAL) {
do_kink_spiral(ctx, ptex, parent_orco, cpa, orco, hairmat, keys, parent_keys, &totkeys, &max_length);
keys->segments = totkeys - 1;
}
else {
- ParticlePathIterator iter;
-
+ /* Fill in invariant part of modifier context. */
+ ParticleChildModifierContext modifier_ctx = {NULL};
+ modifier_ctx.thread_ctx = ctx;
+ modifier_ctx.sim = &ctx->sim;
+ modifier_ctx.ptex = ptex;
+ modifier_ctx.cpa = cpa;
+ modifier_ctx.orco = orco;
+ modifier_ctx.parent_keys = parent_keys;
+
totkeys = ctx->segments + 1;
max_length = ptex->length;
-
+
for (k = 0, key = keys; k < totkeys; k++, key++) {
- ParticleKey *par;
-
+ ParticlePathIterator iter;
psys_path_iter_get(&iter, keys, totkeys, parent_keys, k);
- par = (ParticleKey *)iter.parent_key;
-
- /* apply different deformations to the child path */
- do_child_modifiers(ctx, &ctx->sim, ptex, par->co, par->vel, iter.parent_rotation, parent_orco, cpa, orco, hairmat, (ParticleKey *)key, iter.time);
+
+ ParticleKey *par = (ParticleKey *)iter.parent_key;
+
+ /* Fill in variant part of modifier context. */
+ modifier_ctx.par_co = par->co;
+ modifier_ctx.par_vel = par->vel;
+ modifier_ctx.par_rot = iter.parent_rotation;
+ modifier_ctx.par_orco = parent_orco;
+
+ /* Apply different deformations to the child path. */
+ do_child_modifiers(&modifier_ctx, hairmat, (ParticleKey *)key, iter.time);
}
}
@@ -367,12 +389,12 @@ void psys_apply_child_modifiers(ParticleThreadContext *ctx, struct ListBase *mod
if (k >= 2) {
sub_v3_v3v3((key-1)->vel, key->co, (key-2)->co);
mul_v3_fl((key-1)->vel, 0.5);
-
+
if (ma && draw_col_ma)
get_strand_normal(ma, ornor, cur_length, (key-1)->vel);
}
-
- if (use_length_check && k > 1) {
+
+ if (use_length_check && k > 0) {
float dvec[3];
/* check if path needs to be cut before actual end of data points */
if (!check_path_length(k, keys, key, max_length, step_length, &cur_length, dvec)) {
@@ -388,7 +410,7 @@ void psys_apply_child_modifiers(ParticleThreadContext *ctx, struct ListBase *mod
/* last key */
sub_v3_v3v3(key->vel, key->co, (key-1)->co);
}
-
+
if (ma && draw_col_ma) {
copy_v3_v3(key->col, &ma->r);
get_strand_normal(ma, ornor, cur_length, key->vel);
@@ -419,7 +441,7 @@ void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3],
}
t = time * freq * (float)M_PI;
-
+
if (smooth_start) {
dt = fabsf(t);
/* smooth the beginning of kink */
@@ -434,7 +456,7 @@ void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3],
if (obmat)
mul_mat3_m4_v3(obmat, kink);
-
+
mul_qt_v3(par_rot, kink);
/* make sure kink is normal to strand */
@@ -450,12 +472,12 @@ void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3],
case PART_KINK_CURL:
{
float curl_offset[3];
-
+
/* rotate kink vector around strand tangent */
mul_v3_v3fl(curl_offset, kink, amplitude);
axis_angle_to_quat(q1, par_vel, t);
mul_qt_v3(q1, curl_offset);
-
+
interp_v3_v3v3(par_vec, state->co, par_co, flat);
add_v3_v3v3(result, par_vec, curl_offset);
break;
@@ -494,7 +516,7 @@ void do_kink(ParticleKey *state, const float par_co[3], const float par_vel[3],
float z_vec[3] = {0.f, 0.f, 1.f};
float vec_one[3], state_co[3];
float inp_y, inp_z, length;
-
+
if (par_rot) {
mul_qt_v3(par_rot, y_vec);
mul_qt_v3(par_rot, z_vec);
@@ -563,10 +585,10 @@ static float do_clump_level(float result[3], const float co[3], const float par_
float clumpfac, float clumppow, float pa_clump, CurveMapping *clumpcurve)
{
float clump = 0.0f;
-
+
if (clumpcurve) {
- clump = pa_clump * (1.0f - CLAMPIS(curvemapping_evaluateF(clumpcurve, 0, time), 0.0f, 1.0f));
-
+ clump = pa_clump * (1.0f - clamp_f(curvemapping_evaluateF(clumpcurve, 0, time), 0.0f, 1.0f));
+
interp_v3_v3v3(result, co, par_co, clump);
}
else if (clumpfac != 0.0f) {
@@ -584,7 +606,7 @@ static float do_clump_level(float result[3], const float co[3], const float par_
interp_v3_v3v3(result, co, par_co, clump);
}
-
+
return clump;
}
@@ -592,21 +614,21 @@ float do_clump(ParticleKey *state, const float par_co[3], float time, const floa
bool use_clump_noise, float clump_noise_size, CurveMapping *clumpcurve)
{
float clump;
-
+
if (use_clump_noise && clump_noise_size != 0.0f) {
float center[3], noisevec[3];
float da[4], pa[12];
-
+
mul_v3_v3fl(noisevec, orco_offset, 1.0f / clump_noise_size);
voronoi(noisevec[0], noisevec[1], noisevec[2], da, pa, 1.0f, 0);
mul_v3_fl(&pa[0], clump_noise_size);
add_v3_v3v3(center, par_co, &pa[0]);
-
+
do_clump_level(state->co, state->co, center, time, clumpfac, clumppow, pa_clump, clumpcurve);
}
-
+
clump = do_clump_level(state->co, state->co, par_co, time, clumpfac, clumppow, pa_clump, clumpcurve);
-
+
return clump;
}
@@ -651,27 +673,117 @@ static void do_rough_curve(const float loc[3], float mat[4][4], float time, floa
{
float rough[3];
float rco[3];
-
+
if (!roughcurve)
return;
-
- fac *= CLAMPIS(curvemapping_evaluateF(roughcurve, 0, time), 0.0f, 1.0f);
-
+
+ fac *= clamp_f(curvemapping_evaluateF(roughcurve, 0, time), 0.0f, 1.0f);
+
copy_v3_v3(rco, loc);
mul_v3_fl(rco, time);
rough[0] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[0], rco[1], rco[2], 2, 0, 2);
rough[1] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[1], rco[2], rco[0], 2, 0, 2);
rough[2] = -1.0f + 2.0f * BLI_gTurbulence(size, rco[2], rco[0], rco[1], 2, 0, 2);
-
+
madd_v3_v3fl(state->co, mat[0], fac * rough[0]);
madd_v3_v3fl(state->co, mat[1], fac * rough[1]);
madd_v3_v3fl(state->co, mat[2], fac * rough[2]);
}
-void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim, ParticleTexture *ptex,
- const float par_co[3], const float par_vel[3], const float par_rot[4], const float par_orco[3],
- ChildParticle *cpa, const float orco[3], float mat[4][4], ParticleKey *state, float t)
+static int twist_num_segments(const ParticleChildModifierContext *modifier_ctx)
{
+ ParticleThreadContext *thread_ctx = modifier_ctx->thread_ctx;
+ return (thread_ctx != NULL) ? thread_ctx->segments
+ : modifier_ctx->sim->psys->part->draw_step;
+}
+
+static void twist_get_axis(const ParticleChildModifierContext *modifier_ctx,
+ const float time, float r_axis[3])
+{
+ const int num_segments = twist_num_segments(modifier_ctx);
+ const int index = clamp_i(time * num_segments, 0, num_segments);
+ if (index > 0) {
+ sub_v3_v3v3(r_axis,
+ modifier_ctx->parent_keys[index].co,
+ modifier_ctx->parent_keys[index - 1].co);
+ }
+ else {
+ sub_v3_v3v3(r_axis,
+ modifier_ctx->parent_keys[index + 1].co,
+ modifier_ctx->parent_keys[index].co);
+ }
+}
+
+static float curvemapping_integrate_clamped(CurveMapping *curve,
+ float start, float end, float step)
+{
+ float integral = 0.0f;
+ float x = start;
+ while (x < end) {
+ float y = curvemapping_evaluateF(curve, 0, x);
+ y = clamp_f(y, 0.0f, 1.0f);
+ /* TODO(sergey): Clamp last step to end. */
+ integral += y * step;
+ x += step;
+ }
+ return integral;
+}
+
+static void do_twist(const ParticleChildModifierContext *modifier_ctx,
+ ParticleKey *state, const float time)
+{
+ ParticleThreadContext *thread_ctx = modifier_ctx->thread_ctx;
+ ParticleSimulationData *sim = modifier_ctx->sim;
+ ParticleTexture *ptex = modifier_ctx->ptex;
+ ParticleSettings *part = sim->psys->part;
+ /* Early output checks. */
+ if (part->childtype != PART_CHILD_PARTICLES) {
+ /* Interpolated children behave weird with twist. */
+ return;
+ }
+ if (part->twist == 0.0f) {
+ /* No twist along the strand. */
+ return;
+ }
+ /* Dependent on whether it's threaded update or not, curve comes
+ * from different places.
+ */
+ CurveMapping *twist_curve = NULL;
+ if (part->child_flag & PART_CHILD_USE_TWIST_CURVE) {
+ twist_curve = (thread_ctx != NULL) ? thread_ctx->twistcurve
+ : part->twistcurve;
+ }
+ /* Axis of rotation. */
+ float axis[3];
+ twist_get_axis(modifier_ctx, time, axis);
+ /* Angle of rotation. */
+ float angle = part->twist;
+ if (ptex != NULL) {
+ angle *= (ptex->twist - 0.5f) * 2.0f;
+ }
+ if (twist_curve != NULL) {
+ const int num_segments = twist_num_segments(modifier_ctx);
+ angle *= curvemapping_integrate_clamped(twist_curve,
+ 0.0f, time,
+ 1.0f / num_segments);
+ }
+ else {
+ angle *= time;
+ }
+ /* Perform rotation around parent curve. */
+ float vec[3];
+ sub_v3_v3v3(vec, state->co, modifier_ctx->par_co);
+ rotate_v3_v3v3fl(state->co, vec, axis, angle * 2.0f * M_PI);
+ add_v3_v3(state->co, modifier_ctx->par_co);
+}
+
+void do_child_modifiers(const ParticleChildModifierContext *modifier_ctx,
+ float mat[4][4], ParticleKey *state, float t)
+{
+ ParticleThreadContext *ctx = modifier_ctx->thread_ctx;
+ ParticleSimulationData *sim = modifier_ctx->sim;
+ ParticleTexture *ptex = modifier_ctx->ptex;
+ ChildParticle *cpa = modifier_ctx->cpa;
ParticleSettings *part = sim->psys->part;
CurveMapping *clumpcurve = NULL, *roughcurve = NULL;
int i = cpa - sim->psys->child;
@@ -700,6 +812,8 @@ void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim,
rough_end *= ptex->roughe;
}
+ do_twist(modifier_ctx, state, t);
+
if (part->flag & PART_CHILD_EFFECT)
/* state is safe to cast, since only co and vel are used */
guided = do_guides(sim->eval_ctx, sim->psys->part, sim->psys->effectors, (ParticleKey *)state, cpa->parent, t);
@@ -707,33 +821,51 @@ void do_child_modifiers(ParticleThreadContext *ctx, ParticleSimulationData *sim,
if (guided == 0) {
float orco_offset[3];
float clump;
-
- sub_v3_v3v3(orco_offset, orco, par_orco);
- clump = do_clump(state, par_co, t, orco_offset, part->clumpfac, part->clumppow, ptex ? ptex->clump : 1.f,
- part->child_flag & PART_CHILD_USE_CLUMP_NOISE, part->clump_noise_size, clumpcurve);
+
+ sub_v3_v3v3(orco_offset, modifier_ctx->orco, modifier_ctx->par_orco);
+ clump = do_clump(state,
+ modifier_ctx->par_co,
+ t,
+ orco_offset,
+ part->clumpfac,
+ part->clumppow,
+ ptex ? ptex->clump : 1.0f,
+ part->child_flag & PART_CHILD_USE_CLUMP_NOISE,
+ part->clump_noise_size,
+ clumpcurve);
if (kink_freq != 0.f) {
kink_amp *= (1.f - kink_amp_clump * clump);
-
- do_kink(state, par_co, par_vel, par_rot, t, kink_freq, part->kink_shape,
- kink_amp, part->kink_flat, part->kink, part->kink_axis,
- sim->ob->obmat, smooth_start);
+
+ do_kink(state,
+ modifier_ctx->par_co,
+ modifier_ctx->par_vel,
+ modifier_ctx->par_rot,
+ t,
+ kink_freq,
+ part->kink_shape,
+ kink_amp,
+ part->kink_flat,
+ part->kink,
+ part->kink_axis,
+ sim->ob->obmat,
+ smooth_start);
}
}
if (roughcurve) {
- do_rough_curve(orco, mat, t, rough1, part->rough1_size, roughcurve, state);
+ do_rough_curve(modifier_ctx->orco, mat, t, rough1, part->rough1_size, roughcurve, state);
}
else {
if (rough1 > 0.f)
- do_rough(orco, mat, t, rough1, part->rough1_size, 0.0, state);
-
+ do_rough(modifier_ctx->orco, mat, t, rough1, part->rough1_size, 0.0, state);
+
if (rough2 > 0.f) {
float vec[3];
psys_frand_vec(sim->psys, i + 27, vec);
do_rough(vec, mat, t, rough2, part->rough2_size, part->rough2_thres, state);
}
-
+
if (rough_end > 0.f) {
float vec[3];
psys_frand_vec(sim->psys, i + 27, vec);
diff --git a/source/blender/blenkernel/intern/particle_distribute.c b/source/blender/blenkernel/intern/particle_distribute.c
index ff8a638089f..c261b0dc22c 100644
--- a/source/blender/blenkernel/intern/particle_distribute.c
+++ b/source/blender/blenkernel/intern/particle_distribute.c
@@ -36,7 +36,7 @@
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
-#include "BLI_jitter.h"
+#include "BLI_jitter_2d.h"
#include "BLI_kdtree.h"
#include "BLI_math.h"
#include "BLI_math_geom.h"
@@ -57,7 +57,7 @@
#include "BKE_object.h"
#include "BKE_particle.h"
-static int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot);
+#include "DEG_depsgraph_query.h"
static void alloc_child_particles(ParticleSystem *psys, int tot)
{
@@ -80,12 +80,12 @@ static void alloc_child_particles(ParticleSystem *psys, int tot)
}
}
-static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, DerivedMesh *deformdm, ParticleSystem *psys)
+static void distribute_simple_children(Scene *scene, Object *ob, DerivedMesh *finaldm, DerivedMesh *deformdm, ParticleSystem *psys, const bool use_render_params)
{
ChildParticle *cpa = NULL;
int i, p;
- int child_nbr= psys_get_child_number(scene, psys);
- int totpart= psys_get_tot_child(scene, psys);
+ int child_nbr= psys_get_child_number(scene, psys, use_render_params);
+ int totpart= psys_get_tot_child(scene, psys, use_render_params);
alloc_child_particles(psys, totpart);
@@ -738,16 +738,10 @@ static void exec_distribute_child(TaskPool * __restrict UNUSED(pool), void *task
/* RNG skipping at the beginning */
cpa = psys->child;
for (p = 0; p < task->begin; ++p, ++cpa) {
- if (task->ctx->skip) /* simplification skip */
- BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->ctx->skip[p]);
-
BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP);
}
for (; p < task->end; ++p, ++cpa) {
- if (task->ctx->skip) /* simplification skip */
- BLI_rng_skip(task->rng, PSYS_RND_DIST_SKIP * task->ctx->skip[p]);
-
distribute_children_exec(task, cpa, p);
}
}
@@ -774,11 +768,15 @@ static int distribute_compare_orig_index(const void *p1, const void *p2, void *u
return 1;
}
-static void distribute_invalid(Scene *scene, ParticleSystem *psys, int from)
+static void distribute_invalid(ParticleSimulationData *sim, int from)
{
+ Scene *scene = sim->scene;
+ ParticleSystem *psys = sim->psys;
+ const bool use_render_params = (DEG_get_mode(sim->eval_ctx->depsgraph) == DAG_EVAL_RENDER);
+
if (from == PART_FROM_CHILD) {
ChildParticle *cpa;
- int p, totchild = psys_get_tot_child(scene, psys);
+ int p, totchild = psys_get_tot_child(scene, psys, use_render_params);
if (psys->child && totchild) {
for (p=0,cpa=psys->child; p<totchild; p++,cpa++) {
@@ -800,7 +798,7 @@ static void distribute_invalid(Scene *scene, ParticleSystem *psys, int from)
}
}
-/* Creates a distribution of coordinates on a DerivedMesh */
+/* Creates a distribution of coordinates on a DerivedMesh */
/* This is to denote functionality that does not yet work with mesh - only derived mesh */
static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, ParticleSimulationData *sim, int from)
{
@@ -841,13 +839,15 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
*/
psys_thread_context_init(ctx, sim);
+
+ const bool use_render_params = (DEG_get_mode(sim->eval_ctx->depsgraph) == DAG_EVAL_RENDER);
/* First handle special cases */
if (from == PART_FROM_CHILD) {
/* Simple children */
if (part->childtype != PART_CHILD_FACES) {
BLI_srandom(31415926 + psys->seed + psys->child_seed);
- distribute_simple_children(scene, ob, finaldm, sim->psmd->dm_deformed, psys);
+ distribute_simple_children(scene, ob, finaldm, sim->psmd->dm_deformed, psys, use_render_params);
return 0;
}
}
@@ -895,7 +895,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
BLI_kdtree_balance(tree);
- totpart = psys_get_tot_child(scene, psys);
+ totpart = psys_get_tot_child(scene, psys, use_render_params);
cfrom = from = PART_FROM_FACE;
}
else {
@@ -938,7 +938,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
totelem = (from == PART_FROM_VERT) ? dm->getNumVerts(dm) : dm->getNumTessFaces(dm);
if (totelem == 0) {
- distribute_invalid(scene, psys, children ? PART_FROM_CHILD : 0);
+ distribute_invalid(sim, children ? PART_FROM_CHILD : 0);
if (G.debug & G_DEBUG)
fprintf(stderr,"Particle distribution error: Nothing to emit from!\n");
@@ -950,9 +950,9 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
return 0;
}
- element_weight = MEM_callocN(sizeof(float)*totelem, "particle_distribution_weights");
- particle_element= MEM_callocN(sizeof(int)*totpart, "particle_distribution_indexes");
- jitter_offset = MEM_callocN(sizeof(float)*totelem, "particle_distribution_jitoff");
+ element_weight = MEM_callocN(sizeof(float) * totelem, "particle_distribution_weights");
+ particle_element = MEM_callocN(sizeof(int) * totpart, "particle_distribution_indexes");
+ jitter_offset = MEM_callocN(sizeof(float) * totelem, "particle_distribution_jitoff");
/* Calculate weights from face areas */
if ((part->flag&PART_EDISTR || children) && from != PART_FROM_VERT) {
@@ -1082,7 +1082,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
totmapped = i_mapped;
/* Finally assign elements to particles */
- if ((part->flag & PART_TRAND) || (part->simplify_flag & PART_SIMPLIFY_ENABLE)) {
+ if (part->flag & PART_TRAND) {
for (p = 0; p < totpart; p++) {
/* In theory element_sum[totmapped - 1] should be 1.0,
* but due to float errors this is not necessarily always true, so scale pos accordingly. */
@@ -1101,7 +1101,7 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
/* This is to address tricky issues with vertex-emitting when user tries (and expects) exact 1-1 vert/part
* distribution (see T47983 and its two example files). It allows us to consider pos as
* 'midpoint between v and v+1' (or 'p and p+1', depending whether we have more vertices than particles or not),
- * and avoid stumbling over float imprecisions in element_sum.
+ * and avoid stumbling over float impression in element_sum.
* Note: moved face and volume distribution to this as well (instead of starting at zero),
* for the same reasons, see T52682. */
pos = (totpart < totmapped) ? 0.5 / (double)totmapped : step * 0.5; /* We choose the smaller step. */
@@ -1176,7 +1176,6 @@ static int psys_thread_context_init_distribute(ParticleThreadContext *ctx, Parti
ctx->tpars= tpars;
if (children) {
- totpart= psys_render_simplify_distribution(ctx, totpart);
alloc_child_particles(psys, totpart);
}
@@ -1235,7 +1234,7 @@ static void distribute_particles_on_dm(ParticleSimulationData *sim, int from)
/* ready for future use, to emit particles without geometry */
static void distribute_particles_on_shape(ParticleSimulationData *sim, int UNUSED(from))
{
- distribute_invalid(sim->scene, sim->psys, 0);
+ distribute_invalid(sim, 0);
fprintf(stderr,"Shape emission not yet possible!\n");
}
@@ -1255,250 +1254,8 @@ void distribute_particles(ParticleSimulationData *sim, int from)
distribute_particles_on_shape(sim, from);
if (distr_error) {
- distribute_invalid(sim->scene, sim->psys, from);
+ distribute_invalid(sim, from);
fprintf(stderr,"Particle distribution error!\n");
}
}
-
-/* ======== Simplify ======== */
-
-static float psys_render_viewport_falloff(double rate, float dist, float width)
-{
- return pow(rate, dist / width);
-}
-
-static float psys_render_projected_area(ParticleSystem *psys, const float center[3], float area, double vprate, float *viewport)
-{
- ParticleRenderData *data = psys->renderdata;
- float co[4], view[3], ortho1[3], ortho2[3], w, dx, dy, radius;
-
- /* transform to view space */
- copy_v3_v3(co, center);
- co[3] = 1.0f;
- mul_m4_v4(data->viewmat, co);
-
- /* compute two vectors orthogonal to view vector */
- normalize_v3_v3(view, co);
- ortho_basis_v3v3_v3(ortho1, ortho2, view);
-
- /* compute on screen minification */
- w = co[2] * data->winmat[2][3] + data->winmat[3][3];
- dx = data->winx * ortho2[0] * data->winmat[0][0];
- dy = data->winy * ortho2[1] * data->winmat[1][1];
- w = sqrtf(dx * dx + dy * dy) / w;
-
- /* w squared because we are working with area */
- area = area * w * w;
-
- /* viewport of the screen test */
-
- /* project point on screen */
- mul_m4_v4(data->winmat, co);
- if (co[3] != 0.0f) {
- co[0] = 0.5f * data->winx * (1.0f + co[0] / co[3]);
- co[1] = 0.5f * data->winy * (1.0f + co[1] / co[3]);
- }
-
- /* screen space radius */
- radius = sqrtf(area / (float)M_PI);
-
- /* make smaller using fallof once over screen edge */
- *viewport = 1.0f;
-
- if (co[0] + radius < 0.0f)
- *viewport *= psys_render_viewport_falloff(vprate, -(co[0] + radius), data->winx);
- else if (co[0] - radius > data->winx)
- *viewport *= psys_render_viewport_falloff(vprate, (co[0] - radius) - data->winx, data->winx);
-
- if (co[1] + radius < 0.0f)
- *viewport *= psys_render_viewport_falloff(vprate, -(co[1] + radius), data->winy);
- else if (co[1] - radius > data->winy)
- *viewport *= psys_render_viewport_falloff(vprate, (co[1] - radius) - data->winy, data->winy);
-
- return area;
-}
-
-/* BMESH_TODO, for orig face data, we need to use MPoly */
-static int psys_render_simplify_distribution(ParticleThreadContext *ctx, int tot)
-{
- DerivedMesh *dm = ctx->dm;
- Mesh *me = (Mesh *)(ctx->sim.ob->data);
- MFace *mf, *mface;
- MVert *mvert;
- ParticleRenderData *data;
- ParticleRenderElem *elems, *elem;
- ParticleSettings *part = ctx->sim.psys->part;
- float *facearea, (*facecenter)[3], size[3], fac, powrate, scaleclamp;
- float co1[3], co2[3], co3[3], co4[3], lambda, arearatio, t, area, viewport;
- double vprate;
- int *facetotvert;
- int a, b, totorigface, totface, newtot, skipped;
-
- /* double lookup */
- const int *index_mf_to_mpoly;
- const int *index_mp_to_orig;
-
- if (part->ren_as != PART_DRAW_PATH || !(part->draw & PART_DRAW_REN_STRAND))
- return tot;
- if (!ctx->sim.psys->renderdata)
- return tot;
-
- data = ctx->sim.psys->renderdata;
- if (data->timeoffset)
- return 0;
- if (!(part->simplify_flag & PART_SIMPLIFY_ENABLE))
- return tot;
-
- mvert = dm->getVertArray(dm);
- mface = dm->getTessFaceArray(dm);
- totface = dm->getNumTessFaces(dm);
- totorigface = me->totpoly;
-
- if (totface == 0 || totorigface == 0)
- return tot;
-
- index_mf_to_mpoly = dm->getTessFaceDataArray(dm, CD_ORIGINDEX);
- index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
- if (index_mf_to_mpoly == NULL) {
- index_mp_to_orig = NULL;
- }
-
- facearea = MEM_callocN(sizeof(float) * totorigface, "SimplifyFaceArea");
- facecenter = MEM_callocN(sizeof(float[3]) * totorigface, "SimplifyFaceCenter");
- facetotvert = MEM_callocN(sizeof(int) * totorigface, "SimplifyFaceArea");
- elems = MEM_callocN(sizeof(ParticleRenderElem) * totorigface, "SimplifyFaceElem");
-
- if (data->elems)
- MEM_freeN(data->elems);
-
- data->do_simplify = true;
- data->elems = elems;
- data->index_mf_to_mpoly = index_mf_to_mpoly;
- data->index_mp_to_orig = index_mp_to_orig;
-
- /* compute number of children per original face */
- for (a = 0; a < tot; a++) {
- b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, ctx->index[a]) : ctx->index[a];
- if (b != ORIGINDEX_NONE) {
- elems[b].totchild++;
- }
- }
-
- /* compute areas and centers of original faces */
- for (mf = mface, a = 0; a < totface; a++, mf++) {
- b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, a) : a;
-
- if (b != ORIGINDEX_NONE) {
- copy_v3_v3(co1, mvert[mf->v1].co);
- copy_v3_v3(co2, mvert[mf->v2].co);
- copy_v3_v3(co3, mvert[mf->v3].co);
-
- add_v3_v3(facecenter[b], co1);
- add_v3_v3(facecenter[b], co2);
- add_v3_v3(facecenter[b], co3);
-
- if (mf->v4) {
- copy_v3_v3(co4, mvert[mf->v4].co);
- add_v3_v3(facecenter[b], co4);
- facearea[b] += area_quad_v3(co1, co2, co3, co4);
- facetotvert[b] += 4;
- }
- else {
- facearea[b] += area_tri_v3(co1, co2, co3);
- facetotvert[b] += 3;
- }
- }
- }
-
- for (a = 0; a < totorigface; a++)
- if (facetotvert[a] > 0)
- mul_v3_fl(facecenter[a], 1.0f / facetotvert[a]);
-
- /* for conversion from BU area / pixel area to reference screen size */
- BKE_mesh_texspace_get(me, 0, 0, size);
- fac = ((size[0] + size[1] + size[2]) / 3.0f) / part->simplify_refsize;
- fac = fac * fac;
-
- powrate = log(0.5f) / log(part->simplify_rate * 0.5f);
- if (part->simplify_flag & PART_SIMPLIFY_VIEWPORT)
- vprate = pow(1.0f - part->simplify_viewport, 5.0);
- else
- vprate = 1.0;
-
- /* set simplification parameters per original face */
- for (a = 0, elem = elems; a < totorigface; a++, elem++) {
- area = psys_render_projected_area(ctx->sim.psys, facecenter[a], facearea[a], vprate, &viewport);
- arearatio = fac * area / facearea[a];
-
- if ((arearatio < 1.0f || viewport < 1.0f) && elem->totchild) {
- /* lambda is percentage of elements to keep */
- lambda = (arearatio < 1.0f) ? powf(arearatio, powrate) : 1.0f;
- lambda *= viewport;
-
- lambda = MAX2(lambda, 1.0f / elem->totchild);
-
- /* compute transition region */
- t = part->simplify_transition;
- elem->t = (lambda - t < 0.0f) ? lambda : (lambda + t > 1.0f) ? 1.0f - lambda : t;
- elem->reduce = 1;
-
- /* scale at end and beginning of the transition region */
- elem->scalemax = (lambda + t < 1.0f) ? 1.0f / lambda : 1.0f / (1.0f - elem->t * elem->t / t);
- elem->scalemin = (lambda + t < 1.0f) ? 0.0f : elem->scalemax * (1.0f - elem->t / t);
-
- elem->scalemin = sqrtf(elem->scalemin);
- elem->scalemax = sqrtf(elem->scalemax);
-
- /* clamp scaling */
- scaleclamp = (float)min_ii(elem->totchild, 10);
- elem->scalemin = MIN2(scaleclamp, elem->scalemin);
- elem->scalemax = MIN2(scaleclamp, elem->scalemax);
-
- /* extend lambda to include transition */
- lambda = lambda + elem->t;
- if (lambda > 1.0f)
- lambda = 1.0f;
- }
- else {
- lambda = arearatio;
-
- elem->scalemax = 1.0f; //sqrt(lambda);
- elem->scalemin = 1.0f; //sqrt(lambda);
- elem->reduce = 0;
- }
-
- elem->lambda = lambda;
- elem->scalemin = sqrtf(elem->scalemin);
- elem->scalemax = sqrtf(elem->scalemax);
- elem->curchild = 0;
- }
-
- MEM_freeN(facearea);
- MEM_freeN(facecenter);
- MEM_freeN(facetotvert);
-
- /* move indices and set random number skipping */
- ctx->skip = MEM_callocN(sizeof(int) * tot, "SimplificationSkip");
-
- skipped = 0;
- for (a = 0, newtot = 0; a < tot; a++) {
- b = (index_mf_to_mpoly) ? DM_origindex_mface_mpoly(index_mf_to_mpoly, index_mp_to_orig, ctx->index[a]) : ctx->index[a];
-
- if (b != ORIGINDEX_NONE) {
- if (elems[b].curchild++ < ceil(elems[b].lambda * elems[b].totchild)) {
- ctx->index[newtot] = ctx->index[a];
- ctx->skip[newtot] = skipped;
- skipped = 0;
- newtot++;
- }
- else skipped++;
- }
- else skipped++;
- }
-
- for (a = 0, elem = elems; a < totorigface; a++, elem++)
- elem->curchild = 0;
-
- return newtot;
-}
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index ac10ad44bf1..ffe6617d561 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -48,7 +48,7 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_modifier_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_object_types.h"
#include "DNA_curve_types.h"
#include "DNA_scene_types.h"
@@ -58,7 +58,7 @@
#include "BLI_utildefines.h"
#include "BLI_edgehash.h"
#include "BLI_rand.h"
-#include "BLI_jitter.h"
+#include "BLI_jitter_2d.h"
#include "BLI_math.h"
#include "BLI_blenlib.h"
#include "BLI_kdtree.h"
@@ -76,7 +76,6 @@
#include "BKE_effect.h"
#include "BKE_library_query.h"
#include "BKE_particle.h"
-#include "BKE_global.h"
#include "BKE_collection.h"
#include "BKE_DerivedMesh.h"
@@ -91,6 +90,7 @@
#include "BKE_bvhutils.h"
#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
#include "PIL_time.h"
@@ -98,7 +98,7 @@
/* fluid sim particle import */
#ifdef WITH_MOD_FLUID
-#include "DNA_object_fluidsim.h"
+#include "DNA_object_fluidsim_types.h"
#include "LBM_fluidsim.h"
#include <zlib.h>
#include <string.h>
@@ -122,11 +122,11 @@ static int particles_are_dynamic(ParticleSystem *psys)
return ELEM(psys->part->phystype, PART_PHYS_NEWTON, PART_PHYS_BOIDS, PART_PHYS_FLUID);
}
-float psys_get_current_display_percentage(ParticleSystem *psys)
+float psys_get_current_display_percentage(ParticleSystem *psys, const bool use_render_params)
{
ParticleSettings *part=psys->part;
- if ((psys->renderdata && !particles_are_dynamic(psys)) || /* non-dynamic particles can be rendered fully */
+ if ((use_render_params && !particles_are_dynamic(psys)) || /* non-dynamic particles can be rendered fully */
(part->child_nbr && part->childtype) || /* display percentage applies to children */
(psys->pointcache->flag & PTCACHE_BAKING)) /* baking is always done with full amount */
{
@@ -286,24 +286,24 @@ static void realloc_particles(ParticleSimulationData *sim, int new_totpart)
}
}
-int psys_get_child_number(Scene *scene, ParticleSystem *psys)
+int psys_get_child_number(Scene *scene, ParticleSystem *psys, const bool use_render_params)
{
int nbr;
if (!psys->part->childtype)
return 0;
- if (psys->renderdata)
+ if (use_render_params)
nbr= psys->part->ren_child_nbr;
else
nbr= psys->part->child_nbr;
- return get_render_child_particle_number(&scene->r, nbr, psys->renderdata != NULL);
+ return get_render_child_particle_number(&scene->r, nbr, use_render_params);
}
-int psys_get_tot_child(Scene *scene, ParticleSystem *psys)
+int psys_get_tot_child(Scene *scene, ParticleSystem *psys, const bool use_render_params)
{
- return psys->totpart*psys_get_child_number(scene, psys);
+ return psys->totpart*psys_get_child_number(scene, psys, use_render_params);
}
/************************************************/
@@ -499,6 +499,8 @@ void psys_thread_context_free(ParticleThreadContext *ctx)
MEM_freeN(ctx->vg_rough2);
if (ctx->vg_roughe)
MEM_freeN(ctx->vg_roughe);
+ if (ctx->vg_twist)
+ MEM_freeN(ctx->vg_twist);
if (ctx->sim.psys->lattice_deform_data) {
end_latt_deform(ctx->sim.psys->lattice_deform_data);
@@ -510,7 +512,6 @@ void psys_thread_context_free(ParticleThreadContext *ctx)
if (ctx->jitoff) MEM_freeN(ctx->jitoff);
if (ctx->weight) MEM_freeN(ctx->weight);
if (ctx->index) MEM_freeN(ctx->index);
- if (ctx->skip) MEM_freeN(ctx->skip);
if (ctx->seams) MEM_freeN(ctx->seams);
//if (ctx->vertpart) MEM_freeN(ctx->vertpart);
BLI_kdtree_free(ctx->tree);
@@ -521,6 +522,9 @@ void psys_thread_context_free(ParticleThreadContext *ctx)
if (ctx->roughcurve != NULL) {
curvemapping_free(ctx->roughcurve);
}
+ if (ctx->twistcurve != NULL) {
+ curvemapping_free(ctx->twistcurve);
+ }
}
static void initialize_particle_texture(ParticleSimulationData *sim, ParticleData *pa, int p)
@@ -2898,10 +2902,12 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons
{
ParticleSystem *psys = sim->psys;
ParticleSettings *part = psys->part;
+#if 0
ParticleEditSettings *pset = &sim->scene->toolsettings->particle;
+#endif
int distr=0, alloc=0, skip=0;
- if ((psys->part->childtype && psys->totchild != psys_get_tot_child(sim->scene, psys)) || psys->recalc&PSYS_RECALC_RESET)
+ if ((psys->part->childtype && psys->totchild != psys_get_tot_child(sim->scene, psys, use_render_params)) || psys->recalc&PSYS_RECALC_RESET)
alloc=1;
if (alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (sim->ob && sim->ob->mode & OB_MODE_WEIGHT_PAINT)))
@@ -2911,7 +2917,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons
if (alloc)
realloc_particles(sim, sim->psys->totpart);
- if (psys_get_tot_child(sim->scene, psys)) {
+ if (psys_get_tot_child(sim->scene, psys, use_render_params)) {
/* don't generate children while computing the hair keys */
if (!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) {
distribute_particles(sim, PART_FROM_CHILD);
@@ -2928,22 +2934,25 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons
skip = 1; /* only hair, keyed and baked stuff can have paths */
else if (part->ren_as != PART_DRAW_PATH && !(part->type==PART_HAIR && ELEM(part->ren_as, PART_DRAW_OB, PART_DRAW_GR)))
skip = 1; /* particle visualization must be set as path */
- else if (!psys->renderdata) {
+ else {
if (part->draw_as != PART_DRAW_REND)
skip = 1; /* draw visualization */
else if (psys->pointcache->flag & PTCACHE_BAKING)
skip = 1; /* no need to cache paths while baking dynamics */
- else if (psys_in_edit_mode(sim->eval_ctx->view_layer, psys)) {
+
+#if 0 /* TODO(mai): something is very wrong with these conditionals, they dont make sense and the cache isnt updating */
+ else if (psys_in_edit_mode(sim->eval_ctx->depsgraph, 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)
skip = 1; /* in edit mode paths are needed for child particles and dynamic hair */
}
+#endif
}
/* particle instance modifier with "path" option need cached paths even if particle system doesn't */
- FOREACH_SCENE_OBJECT(sim->scene, ob)
+ FOREACH_SCENE_OBJECT_BEGIN(sim->scene, ob)
{
ModifierData *md = modifiers_findByType(ob, eModifierType_ParticleInstance);
if (md) {
@@ -2954,7 +2963,7 @@ static void psys_update_path_cache(ParticleSimulationData *sim, float cfra, cons
}
}
}
- FOREACH_SCENE_OBJECT_END
+ FOREACH_SCENE_OBJECT_END;
if (!skip) {
psys_cache_paths(sim, cfra, use_render_params);
@@ -3214,7 +3223,7 @@ static void hair_step(ParticleSimulationData *sim, float cfra, const bool use_re
ParticleSystem *psys = sim->psys;
ParticleSettings *part = psys->part;
PARTICLE_P;
- float disp = psys_get_current_display_percentage(psys);
+ float disp = psys_get_current_display_percentage(psys, use_render_params);
LOOP_PARTICLES {
pa->size = part->size;
@@ -3730,13 +3739,13 @@ static void dynamics_step(ParticleSimulationData *sim, float cfra)
free_collider_cache(&sim->colliders);
BLI_rng_free(rng);
}
-static void update_children(ParticleSimulationData *sim)
+static void update_children(ParticleSimulationData *sim, const bool use_render_params)
{
if ((sim->psys->part->type == PART_HAIR) && (sim->psys->flag & PSYS_HAIR_DONE)==0)
/* don't generate children while growing hair - waste of time */
psys_free_children(sim->psys);
else if (sim->psys->part->childtype) {
- if (sim->psys->totchild != psys_get_tot_child(sim->scene, sim->psys))
+ if (sim->psys->totchild != psys_get_tot_child(sim->scene, sim->psys, use_render_params))
distribute_particles(sim, PART_FROM_CHILD);
else {
/* Children are up to date, nothing to do. */
@@ -3746,7 +3755,7 @@ static void update_children(ParticleSimulationData *sim)
psys_free_children(sim->psys);
}
/* updates cached particles' alive & other flags etc..*/
-static void cached_step(ParticleSimulationData *sim, float cfra)
+static void cached_step(ParticleSimulationData *sim, float cfra, const bool use_render_params)
{
ParticleSystem *psys = sim->psys;
ParticleSettings *part = psys->part;
@@ -3756,7 +3765,7 @@ static void cached_step(ParticleSimulationData *sim, float cfra)
psys_update_effectors(sim);
- disp= psys_get_current_display_percentage(psys);
+ disp= psys_get_current_display_percentage(psys, use_render_params);
LOOP_PARTICLES {
psys_get_texture(sim, pa, &ptex, PAMAP_SIZE, cfra);
@@ -3978,8 +3987,8 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_
int cache_result = BKE_ptcache_read(pid, cache_cfra, true);
if (ELEM(cache_result, PTCACHE_READ_EXACT, PTCACHE_READ_INTERPOLATED)) {
- cached_step(sim, cfra);
- update_children(sim);
+ cached_step(sim, cfra, use_render_params);
+ update_children(sim, use_render_params);
psys_update_path_cache(sim, cfra, use_render_params);
BKE_ptcache_validate(cache, (int)cache_cfra);
@@ -3996,7 +4005,7 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_
}
else if (cache_result == PTCACHE_READ_OLD) {
psys->cfra = (float)cache->simframe;
- cached_step(sim, psys->cfra);
+ cached_step(sim, psys->cfra, use_render_params);
}
/* if on second frame, write cache for first frame */
@@ -4008,7 +4017,7 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_
/* 3. do dynamics */
/* set particles to be not calculated TODO: can't work with pointcache */
- disp= psys_get_current_display_percentage(psys);
+ disp= psys_get_current_display_percentage(psys, use_render_params);
LOOP_PARTICLES {
if (psys_frand(psys, p) > disp)
@@ -4064,7 +4073,7 @@ static void system_step(ParticleSimulationData *sim, float cfra, const bool use_
BKE_ptcache_write(pid, (int)cache_cfra);
}
- update_children(sim);
+ update_children(sim, use_render_params);
/* cleanup */
if (psys->lattice_deform_data) {
@@ -4307,7 +4316,7 @@ void particle_system_update(const struct EvaluationContext *eval_ctx, Scene *sce
case PART_PHYS_KEYED:
{
PARTICLE_P;
- float disp = psys_get_current_display_percentage(psys);
+ float disp = psys_get_current_display_percentage(psys, use_render_params);
bool free_unexisting = false;
/* Particles without dynamics haven't been reset yet because they don't use pointcache */
@@ -4369,8 +4378,7 @@ void particle_system_update(const struct EvaluationContext *eval_ctx, Scene *sce
psys->recalc = 0;
/* save matrix for duplicators, at rendertime the actual dupliobject's matrix is used so don't update! */
- if (psys->renderdata==0)
- invert_m4_m4(psys->imat, ob->obmat);
+ invert_m4_m4(psys->imat, ob->obmat);
BKE_particle_batch_cache_dirty(psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
}
@@ -4403,30 +4411,16 @@ void BKE_particlesystem_id_loop(ParticleSystem *psys, ParticleSystemIDFunc func,
/* **** Depsgraph evaluation **** */
-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 (%p)\n", __func__, ob->id.name, ob);
+ DEG_debug_print_eval(__func__, ob->id.name, ob);
+ for (ParticleSystem *psys = ob->particlesystem.first;
+ psys != NULL;
+ psys = psys->next)
+ {
+ psys->recalc |= (psys->part->id.recalc & DEG_TAG_PSYS_ALL);
}
BKE_ptcache_object_reset(scene, ob, PTCACHE_RESET_DEPSGRAPH);
}
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index 63f2c7e5452..14e0cfa75b5 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -1296,7 +1296,7 @@ void BKE_pbvh_get_grid_updates(PBVH *bvh, bool clear, void ***r_gridfaces, int *
pbvh_iter_end(&iter);
- const int tot = BLI_gset_size(face_set);
+ const int tot = BLI_gset_len(face_set);
if (tot == 0) {
*r_totface = 0;
*r_gridfaces = NULL;
@@ -1435,8 +1435,8 @@ void BKE_pbvh_node_num_verts(
if (r_uniquevert) *r_uniquevert = node->uniq_verts;
break;
case PBVH_BMESH:
- tot = BLI_gset_size(node->bm_unique_verts);
- if (r_totvert) *r_totvert = tot + BLI_gset_size(node->bm_other_verts);
+ tot = BLI_gset_len(node->bm_unique_verts);
+ if (r_totvert) *r_totvert = tot + BLI_gset_len(node->bm_other_verts);
if (r_uniquevert) *r_uniquevert = tot;
break;
}
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index e77edb21798..e32a5d0681e 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -255,7 +255,7 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde
const int cd_face_node_offset = bvh->cd_face_node_offset;
PBVHNode *n = &bvh->nodes[node_index];
- if (BLI_gset_size(n->bm_faces) <= bvh->leaf_limit) {
+ if (BLI_gset_len(n->bm_faces) <= bvh->leaf_limit) {
/* Node limit not exceeded */
pbvh_bmesh_node_finalize(bvh, node_index, cd_vert_node_offset, cd_face_node_offset);
return;
@@ -289,8 +289,8 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde
*c2 = &bvh->nodes[children + 1];
c1->flag |= PBVH_Leaf;
c2->flag |= PBVH_Leaf;
- c1->bm_faces = BLI_gset_ptr_new_ex("bm_faces", BLI_gset_size(n->bm_faces) / 2);
- c2->bm_faces = BLI_gset_ptr_new_ex("bm_faces", BLI_gset_size(n->bm_faces) / 2);
+ c1->bm_faces = BLI_gset_ptr_new_ex("bm_faces", BLI_gset_len(n->bm_faces) / 2);
+ c2->bm_faces = BLI_gset_ptr_new_ex("bm_faces", BLI_gset_len(n->bm_faces) / 2);
/* Partition the parent node's faces between the two children */
GSET_ITER (gs_iter, n->bm_faces) {
@@ -305,11 +305,11 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde
/* Enforce at least one primitive in each node */
GSet *empty = NULL, *other;
- if (BLI_gset_size(c1->bm_faces) == 0) {
+ if (BLI_gset_len(c1->bm_faces) == 0) {
empty = c1->bm_faces;
other = c2->bm_faces;
}
- else if (BLI_gset_size(c2->bm_faces) == 0) {
+ else if (BLI_gset_len(c2->bm_faces) == 0) {
empty = c2->bm_faces;
other = c1->bm_faces;
}
@@ -375,7 +375,7 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde
static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index)
{
GSet *bm_faces = bvh->nodes[node_index].bm_faces;
- const int bm_faces_size = BLI_gset_size(bm_faces);
+ const int bm_faces_size = BLI_gset_len(bm_faces);
if (bm_faces_size <= bvh->leaf_limit) {
/* Node limit not exceeded */
return false;
@@ -555,9 +555,9 @@ static int pbvh_bmesh_node_vert_use_count(PBVH *bvh, PBVHNode *node, BMVert *v)
#endif
#define pbvh_bmesh_node_vert_use_count_is_equal(bvh, node, v, n) \
- (pbvh_bmesh_node_vert_use_count_ex(bvh, node, v, (n) + 1) == n)
+ (pbvh_bmesh_node_vert_use_count_at_most(bvh, node, v, (n) + 1) == n)
-static int pbvh_bmesh_node_vert_use_count_ex(PBVH *bvh, PBVHNode *node, BMVert *v, const int count_max)
+static int pbvh_bmesh_node_vert_use_count_at_most(PBVH *bvh, PBVHNode *node, BMVert *v, const int count_max)
{
int count = 0;
BMFace *f;
@@ -1238,7 +1238,7 @@ static bool pbvh_bmesh_subdivide_long_edges(
bool any_subdivided = false;
while (!BLI_heap_is_empty(eq_ctx->q->heap)) {
- BMVert **pair = BLI_heap_popmin(eq_ctx->q->heap);
+ BMVert **pair = BLI_heap_pop_min(eq_ctx->q->heap);
BMVert *v1 = pair[0], *v2 = pair[1];
BMEdge *e;
@@ -1326,7 +1326,7 @@ static void pbvh_bmesh_collapse_edge(
/* Note: this could be done with BM_vert_splice(), but that
* requires handling other issues like duplicate edges, so doesn't
* really buy anything. */
- BLI_buffer_empty(deleted_faces);
+ BLI_buffer_clear(deleted_faces);
BMLoop *l;
@@ -1455,7 +1455,7 @@ static bool pbvh_bmesh_collapse_short_edges(
GHash *deleted_verts = BLI_ghash_ptr_new("deleted_verts");
while (!BLI_heap_is_empty(eq_ctx->q->heap)) {
- BMVert **pair = BLI_heap_popmin(eq_ctx->q->heap);
+ BMVert **pair = BLI_heap_pop_min(eq_ctx->q->heap);
BMVert *v1 = pair[0], *v2 = pair[1];
BLI_mempool_free(eq_ctx->pool, pair);
pair = NULL;
@@ -2011,10 +2011,10 @@ void BKE_pbvh_bmesh_node_save_orig(PBVHNode *node)
if (node->bm_orco)
return;
- const int totvert = BLI_gset_size(node->bm_unique_verts) +
- BLI_gset_size(node->bm_other_verts);
+ const int totvert = BLI_gset_len(node->bm_unique_verts) +
+ BLI_gset_len(node->bm_other_verts);
- const int tottri = BLI_gset_size(node->bm_faces);
+ const int tottri = BLI_gset_len(node->bm_faces);
node->bm_orco = MEM_mallocN(sizeof(*node->bm_orco) * totvert, __func__);
node->bm_ortri = MEM_mallocN(sizeof(*node->bm_ortri) * tottri, __func__);
@@ -2189,12 +2189,12 @@ static void pbvh_bmesh_verify(PBVH *bvh)
int totface = 0, totvert = 0;
for (int i = 0; i < bvh->totnode; i++) {
PBVHNode *n = &bvh->nodes[i];
- totface += n->bm_faces ? BLI_gset_size(n->bm_faces) : 0;
- totvert += n->bm_unique_verts ? BLI_gset_size(n->bm_unique_verts) : 0;
+ totface += n->bm_faces ? BLI_gset_len(n->bm_faces) : 0;
+ totvert += n->bm_unique_verts ? BLI_gset_len(n->bm_unique_verts) : 0;
}
- BLI_assert(totface == BLI_gset_size(faces_all));
- BLI_assert(totvert == BLI_gset_size(verts_all));
+ BLI_assert(totface == BLI_gset_len(faces_all));
+ BLI_assert(totvert == BLI_gset_len(verts_all));
}
{
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index b794fcfd929..50314daa014 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -38,9 +38,10 @@
#include "DNA_ID.h"
#include "DNA_dynamicpaint_types.h"
+#include "DNA_group_types.h"
#include "DNA_modifier_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_particle_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
@@ -972,20 +973,20 @@ static int ptcache_smoke_openvdb_write(struct OpenVDBWriter *writer, void *smoke
smoke_turbulence_export(sds->wt, &dens, &react, &flame, &fuel, &r, &g, &b, &tcu, &tcv, &tcw);
- wt_density_grid = OpenVDB_export_grid_fl(writer, "density", dens, sds->res_wt, sds->fluidmat_wt, NULL);
+ wt_density_grid = OpenVDB_export_grid_fl(writer, "density", dens, sds->res_wt, sds->fluidmat_wt, sds->clipping, NULL);
clip_grid = wt_density_grid;
if (fluid_fields & SM_ACTIVE_FIRE) {
- OpenVDB_export_grid_fl(writer, "flame", flame, sds->res_wt, sds->fluidmat_wt, wt_density_grid);
- OpenVDB_export_grid_fl(writer, "fuel", fuel, sds->res_wt, sds->fluidmat_wt, wt_density_grid);
- OpenVDB_export_grid_fl(writer, "react", react, sds->res_wt, sds->fluidmat_wt, wt_density_grid);
+ OpenVDB_export_grid_fl(writer, "flame", flame, sds->res_wt, sds->fluidmat_wt, sds->clipping, wt_density_grid);
+ OpenVDB_export_grid_fl(writer, "fuel", fuel, sds->res_wt, sds->fluidmat_wt, sds->clipping, wt_density_grid);
+ OpenVDB_export_grid_fl(writer, "react", react, sds->res_wt, sds->fluidmat_wt, sds->clipping, wt_density_grid);
}
if (fluid_fields & SM_ACTIVE_COLORS) {
- OpenVDB_export_grid_vec(writer, "color", r, g, b, sds->res_wt, sds->fluidmat_wt, VEC_INVARIANT, true, wt_density_grid);
+ OpenVDB_export_grid_vec(writer, "color", r, g, b, sds->res_wt, sds->fluidmat_wt, VEC_INVARIANT, true, sds->clipping, wt_density_grid);
}
- OpenVDB_export_grid_vec(writer, "texture coordinates", tcu, tcv, tcw, sds->res, sds->fluidmat, VEC_INVARIANT, false, wt_density_grid);
+ OpenVDB_export_grid_vec(writer, "texture coordinates", tcu, tcv, tcw, sds->res, sds->fluidmat, VEC_INVARIANT, false, sds->clipping, wt_density_grid);
}
if (sds->fluid) {
@@ -999,33 +1000,33 @@ static int ptcache_smoke_openvdb_write(struct OpenVDBWriter *writer, void *smoke
OpenVDBWriter_add_meta_fl(writer, "blender/smoke/dx", dx);
OpenVDBWriter_add_meta_fl(writer, "blender/smoke/dt", dt);
- const char *name = (!sds->wt) ? "density" : "density low";
- density_grid = OpenVDB_export_grid_fl(writer, name, dens, sds->res, sds->fluidmat, NULL);
+ const char *name = (!sds->wt) ? "density" : "density_low";
+ density_grid = OpenVDB_export_grid_fl(writer, name, dens, sds->res, sds->fluidmat, sds->clipping, NULL);
clip_grid = sds->wt ? clip_grid : density_grid;
- OpenVDB_export_grid_fl(writer, "shadow", sds->shadow, sds->res, sds->fluidmat, NULL);
+ OpenVDB_export_grid_fl(writer, "shadow", sds->shadow, sds->res, sds->fluidmat, sds->clipping, NULL);
if (fluid_fields & SM_ACTIVE_HEAT) {
- OpenVDB_export_grid_fl(writer, "heat", heat, sds->res, sds->fluidmat, clip_grid);
- OpenVDB_export_grid_fl(writer, "heat old", heatold, sds->res, sds->fluidmat, clip_grid);
+ OpenVDB_export_grid_fl(writer, "heat", heat, sds->res, sds->fluidmat, sds->clipping, clip_grid);
+ OpenVDB_export_grid_fl(writer, "heat_old", heatold, sds->res, sds->fluidmat, sds->clipping, clip_grid);
}
if (fluid_fields & SM_ACTIVE_FIRE) {
- name = (!sds->wt) ? "flame" : "flame low";
- OpenVDB_export_grid_fl(writer, name, flame, sds->res, sds->fluidmat, density_grid);
- name = (!sds->wt) ? "fuel" : "fuel low";
- OpenVDB_export_grid_fl(writer, name, fuel, sds->res, sds->fluidmat, density_grid);
- name = (!sds->wt) ? "react" : "react low";
- OpenVDB_export_grid_fl(writer, name, react, sds->res, sds->fluidmat, density_grid);
+ name = (!sds->wt) ? "flame" : "flame_low";
+ OpenVDB_export_grid_fl(writer, name, flame, sds->res, sds->fluidmat, sds->clipping, density_grid);
+ name = (!sds->wt) ? "fuel" : "fuel_low";
+ OpenVDB_export_grid_fl(writer, name, fuel, sds->res, sds->fluidmat, sds->clipping, density_grid);
+ name = (!sds->wt) ? "react" : "react_low";
+ OpenVDB_export_grid_fl(writer, name, react, sds->res, sds->fluidmat, sds->clipping, density_grid);
}
if (fluid_fields & SM_ACTIVE_COLORS) {
- name = (!sds->wt) ? "color" : "color low";
- OpenVDB_export_grid_vec(writer, name, r, g, b, sds->res, sds->fluidmat, VEC_INVARIANT, true, density_grid);
+ name = (!sds->wt) ? "color" : "color_low";
+ OpenVDB_export_grid_vec(writer, name, r, g, b, sds->res, sds->fluidmat, VEC_INVARIANT, true, sds->clipping, density_grid);
}
- OpenVDB_export_grid_vec(writer, "velocity", vx, vy, vz, sds->res, sds->fluidmat, VEC_CONTRAVARIANT_RELATIVE, false, clip_grid);
- OpenVDB_export_grid_ch(writer, "obstacles", obstacles, sds->res, sds->fluidmat, NULL);
+ OpenVDB_export_grid_vec(writer, "velocity", vx, vy, vz, sds->res, sds->fluidmat, VEC_CONTRAVARIANT_RELATIVE, false, sds->clipping, clip_grid);
+ OpenVDB_export_grid_ch(writer, "obstacles", obstacles, sds->res, sds->fluidmat, sds->clipping, NULL);
}
return 1;
@@ -1104,25 +1105,25 @@ static int ptcache_smoke_openvdb_read(struct OpenVDBReader *reader, void *smoke_
OpenVDB_import_grid_fl(reader, "shadow", &sds->shadow, sds->res);
- const char *name = (!sds->wt) ? "density" : "density low";
+ const char *name = (!sds->wt) ? "density" : "density_low";
OpenVDB_import_grid_fl(reader, name, &dens, sds->res);
if (cache_fields & SM_ACTIVE_HEAT) {
OpenVDB_import_grid_fl(reader, "heat", &heat, sds->res);
- OpenVDB_import_grid_fl(reader, "heat old", &heatold, sds->res);
+ OpenVDB_import_grid_fl(reader, "heat_old", &heatold, sds->res);
}
if (cache_fields & SM_ACTIVE_FIRE) {
- name = (!sds->wt) ? "flame" : "flame low";
+ name = (!sds->wt) ? "flame" : "flame_low";
OpenVDB_import_grid_fl(reader, name, &flame, sds->res);
- name = (!sds->wt) ? "fuel" : "fuel low";
+ name = (!sds->wt) ? "fuel" : "fuel_low";
OpenVDB_import_grid_fl(reader, name, &fuel, sds->res);
- name = (!sds->wt) ? "react" : "react low";
+ name = (!sds->wt) ? "react" : "react_low";
OpenVDB_import_grid_fl(reader, name, &react, sds->res);
}
if (cache_fields & SM_ACTIVE_COLORS) {
- name = (!sds->wt) ? "color" : "color low";
+ name = (!sds->wt) ? "color" : "color_low";
OpenVDB_import_grid_vec(reader, name, &r, &g, &b, sds->res);
}
@@ -1646,6 +1647,25 @@ void BKE_ptcache_id_from_rigidbody(PTCacheID *pid, Object *ob, RigidBodyWorld *r
pid->file_type = PTCACHE_FILE_PTCACHE;
}
+PTCacheID BKE_ptcache_id_find(Object *ob, Scene *scene, PointCache *cache)
+{
+ PTCacheID result = {0};
+
+ ListBase pidlist;
+ BKE_ptcache_ids_from_object(&pidlist, ob, scene, MAX_DUPLI_RECUR);
+
+ for (PTCacheID *pid = pidlist.first; pid; pid = pid->next) {
+ if (pid->cache == cache) {
+ result = *pid;
+ break;
+ }
+ }
+
+ BLI_freelistN(&pidlist);
+
+ return result;
+}
+
void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int duplis)
{
PTCacheID *pid;
@@ -1714,22 +1734,19 @@ void BKE_ptcache_ids_from_object(ListBase *lb, Object *ob, Scene *scene, int dup
BLI_addtail(lb, pid);
}
- if (scene && (duplis-- > 0) && (ob->transflag & OB_DUPLI)) {
- ListBase *lb_dupli_ob;
- /* don't update the dupli groups, we only want their pid's */
- if ((lb_dupli_ob = object_duplilist_ex(G.main->eval_ctx, scene, ob, false))) {
- DupliObject *dob;
- for (dob= lb_dupli_ob->first; dob; dob= dob->next) {
- if (dob->ob != ob) { /* avoids recursive loops with dupliframes: bug 22988 */
- ListBase lb_dupli_pid;
- BKE_ptcache_ids_from_object(&lb_dupli_pid, dob->ob, scene, duplis);
- BLI_movelisttolist(lb, &lb_dupli_pid);
- if (lb_dupli_pid.first)
- printf("Adding Dupli\n");
- }
- }
+ /* Consider all object in dupli groups to be part of the same object,
+ * for baking with linking dupligroups. Once we have better overrides
+ * this can be revisited so users select the local objects directly. */
+ if (scene && (duplis-- > 0) && (ob->dup_group)) {
+ Group *group = ob->dup_group;
+ Base *base = group->view_layer->object_bases.first;
- free_object_duplilist(lb_dupli_ob); /* does restore */
+ for (; base; base = base->next) {
+ if (base->object != ob) {
+ ListBase lb_dupli_pid;
+ BKE_ptcache_ids_from_object(&lb_dupli_pid, base->object, scene, duplis);
+ BLI_movelisttolist(lb, &lb_dupli_pid);
+ }
}
}
}
@@ -3662,7 +3679,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_graph_update_for_newframe(G.main->eval_ctx, depsgraph, bmain, scene, view_layer);
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
if (baker->update_progress) {
float progress = ((float)(CFRA - startframe)/(float)(endframe - startframe));
@@ -3748,7 +3765,7 @@ void BKE_ptcache_bake(PTCacheBaker *baker)
CFRA = cfrao;
if (bake) { /* already on cfra unless baking */
- BKE_scene_graph_update_for_newframe(bmain->eval_ctx, depsgraph, bmain, scene, view_layer);
+ BKE_scene_graph_update_for_newframe(depsgraph, bmain);
}
/* TODO: call redraw all windows somehow */
diff --git a/source/blender/blenkernel/intern/rigidbody.c b/source/blender/blenkernel/intern/rigidbody.c
index bd4b817c8cd..ff521260993 100644
--- a/source/blender/blenkernel/intern/rigidbody.c
+++ b/source/blender/blenkernel/intern/rigidbody.c
@@ -50,7 +50,7 @@
#include "DNA_group_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
-#include "DNA_object_force.h"
+#include "DNA_object_force_types.h"
#include "DNA_rigidbody_types.h"
#include "DNA_scene_types.h"
@@ -66,6 +66,8 @@
#include "BKE_rigidbody.h"
#include "BKE_scene.h"
+#include "DEG_depsgraph.h"
+
/* ************************************** */
/* Memory Management */
@@ -92,7 +94,7 @@ 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 */
if (rbw->constraints) {
- FOREACH_GROUP_OBJECT(rbw->constraints, object)
+ FOREACH_GROUP_OBJECT_BEGIN(rbw->constraints, object)
{
if (object->rigidbody_constraint) {
RigidBodyCon *rbc = object->rigidbody_constraint;
@@ -101,11 +103,11 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
}
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
if (rbw->group) {
- FOREACH_GROUP_OBJECT(rbw->group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(rbw->group, object)
{
if (object->rigidbody_object) {
RigidBodyOb *rbo = object->rigidbody_object;
@@ -114,7 +116,7 @@ void BKE_rigidbody_free_world(RigidBodyWorld *rbw)
}
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
/* free dynamics world */
RB_dworld_delete(rbw->physics_world);
@@ -702,6 +704,39 @@ static void rigidbody_validate_sim_object(RigidBodyWorld *rbw, Object *ob, bool
/* --------------------- */
+static void rigidbody_constraint_set_limits(RigidBodyCon *rbc, void (*set_limits)(rbConstraint*,int,float,float))
+{
+ if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X)
+ set_limits(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->limit_lin_x_lower, rbc->limit_lin_x_upper);
+ else
+ set_limits(rbc->physics_constraint, RB_LIMIT_LIN_X, 0.0f, -1.0f);
+
+ if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_Y)
+ set_limits(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->limit_lin_y_lower, rbc->limit_lin_y_upper);
+ else
+ set_limits(rbc->physics_constraint, RB_LIMIT_LIN_Y, 0.0f, -1.0f);
+
+ if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_Z)
+ set_limits(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->limit_lin_z_lower, rbc->limit_lin_z_upper);
+ else
+ set_limits(rbc->physics_constraint, RB_LIMIT_LIN_Z, 0.0f, -1.0f);
+
+ if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_X)
+ set_limits(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->limit_ang_x_lower, rbc->limit_ang_x_upper);
+ else
+ set_limits(rbc->physics_constraint, RB_LIMIT_ANG_X, 0.0f, -1.0f);
+
+ if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Y)
+ set_limits(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->limit_ang_y_lower, rbc->limit_ang_y_upper);
+ else
+ set_limits(rbc->physics_constraint, RB_LIMIT_ANG_Y, 0.0f, -1.0f);
+
+ if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Z)
+ set_limits(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->limit_ang_z_lower, rbc->limit_ang_z_upper);
+ else
+ set_limits(rbc->physics_constraint, RB_LIMIT_ANG_Z, 0.0f, -1.0f);
+}
+
/**
* Create physics sim representation of constraint given rigid body constraint settings
*
@@ -820,40 +855,13 @@ static void rigidbody_validate_sim_constraint(RigidBodyWorld *rbw, Object *ob, b
RB_constraint_set_damping_6dof_spring(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->spring_damping_ang_z);
RB_constraint_set_equilibrium_6dof_spring(rbc->physics_constraint);
- ATTR_FALLTHROUGH;
- case RBC_TYPE_6DOF:
- if (rbc->type == RBC_TYPE_6DOF) /* a litte awkward but avoids duplicate code for limits */
- rbc->physics_constraint = RB_constraint_new_6dof(loc, rot, rb1, rb2);
-
- if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_X)
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_X, rbc->limit_lin_x_lower, rbc->limit_lin_x_upper);
- else
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_X, 0.0f, -1.0f);
- if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_Y)
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Y, rbc->limit_lin_y_lower, rbc->limit_lin_y_upper);
- else
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Y, 0.0f, -1.0f);
-
- if (rbc->flag & RBC_FLAG_USE_LIMIT_LIN_Z)
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Z, rbc->limit_lin_z_lower, rbc->limit_lin_z_upper);
- else
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_LIN_Z, 0.0f, -1.0f);
-
- if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_X)
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_X, rbc->limit_ang_x_lower, rbc->limit_ang_x_upper);
- else
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_X, 0.0f, -1.0f);
-
- if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Y)
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Y, rbc->limit_ang_y_lower, rbc->limit_ang_y_upper);
- else
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Y, 0.0f, -1.0f);
+ rigidbody_constraint_set_limits(rbc, RB_constraint_set_limits_6dof_spring);
+ break;
+ case RBC_TYPE_6DOF:
+ rbc->physics_constraint = RB_constraint_new_6dof(loc, rot, rb1, rb2);
- if (rbc->flag & RBC_FLAG_USE_LIMIT_ANG_Z)
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Z, rbc->limit_ang_z_lower, rbc->limit_ang_z_upper);
- else
- RB_constraint_set_limits_6dof(rbc->physics_constraint, RB_LIMIT_ANG_Z, 0.0f, -1.0f);
+ rigidbody_constraint_set_limits(rbc, RB_constraint_set_limits_6dof);
break;
case RBC_TYPE_MOTOR:
rbc->physics_constraint = RB_constraint_new_motor(loc, rot, rb1, rb2);
@@ -1148,7 +1156,7 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob)
/* remove object from rigid body constraints */
if (rbw->constraints) {
- FOREACH_GROUP_OBJECT(rbw->constraints, obt)
+ FOREACH_GROUP_OBJECT_BEGIN(rbw->constraints, obt)
{
if (obt && obt->rigidbody_constraint) {
rbc = obt->rigidbody_constraint;
@@ -1157,7 +1165,7 @@ void BKE_rigidbody_remove_object(Scene *scene, Object *ob)
}
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
}
@@ -1201,12 +1209,12 @@ static void rigidbody_update_ob_array(RigidBodyWorld *rbw)
}
i = 0;
- FOREACH_GROUP_OBJECT(rbw->group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(rbw->group, object)
{
rbw->objects[i] = object;
i++;
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
static void rigidbody_update_sim_world(Scene *scene, RigidBodyWorld *rbw)
@@ -1332,7 +1340,7 @@ static void rigidbody_update_simulation(const struct EvaluationContext *eval_ctx
* Memory management needs redesign here, this is just a dirty workaround.
*/
if (rebuild && rbw->constraints) {
- FOREACH_GROUP_OBJECT(rbw->constraints, ob)
+ FOREACH_GROUP_OBJECT_BEGIN(rbw->constraints, ob)
{
RigidBodyCon *rbc = ob->rigidbody_constraint;
if (rbc && rbc->physics_constraint) {
@@ -1341,11 +1349,11 @@ static void rigidbody_update_simulation(const struct EvaluationContext *eval_ctx
rbc->physics_constraint = NULL;
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
/* update objects */
- FOREACH_GROUP_OBJECT(rbw->group, ob)
+ FOREACH_GROUP_OBJECT_BEGIN(rbw->group, ob)
{
if (ob->type == OB_MESH) {
/* validate that we've got valid object set up here... */
@@ -1388,13 +1396,13 @@ static void rigidbody_update_simulation(const struct EvaluationContext *eval_ctx
rigidbody_update_sim_ob(eval_ctx, scene, rbw, ob, rbo);
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
/* update constraints */
if (rbw->constraints == NULL) /* no constraints, move on */
return;
- FOREACH_GROUP_OBJECT(rbw->constraints, ob)
+ FOREACH_GROUP_OBJECT_BEGIN(rbw->constraints, ob)
{
/* validate that we've got valid object set up here... */
RigidBodyCon *rbc = ob->rigidbody_constraint;
@@ -1422,12 +1430,12 @@ static void rigidbody_update_simulation(const struct EvaluationContext *eval_ctx
rbc->flag &= ~RBC_FLAG_NEEDS_VALIDATE;
}
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
static void rigidbody_update_simulation_post_step(RigidBodyWorld *rbw)
{
- FOREACH_GROUP_BASE(rbw->group, base)
+ FOREACH_GROUP_BASE_BEGIN(rbw->group, base)
{
Object *ob = base->object;
RigidBodyOb *rbo = ob->rigidbody_object;
@@ -1688,11 +1696,7 @@ void BKE_rigidbody_rebuild_sim(const struct EvaluationContext *eval_ctx,
Scene *scene)
{
float ctime = BKE_scene_frame_get(scene);
-
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s at %f\n", __func__, ctime);
- }
-
+ DEG_debug_print_eval_time(__func__, scene->id.name, scene, ctime);
/* rebuild sim data (i.e. after resetting to start of timeline) */
if (BKE_scene_check_rigidbody_active(scene)) {
BKE_rigidbody_rebuild_world(eval_ctx, scene, ctime);
@@ -1703,11 +1707,7 @@ void BKE_rigidbody_eval_simulation(const struct EvaluationContext *eval_ctx,
Scene *scene)
{
float ctime = BKE_scene_frame_get(scene);
-
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s at %f\n", __func__, ctime);
- }
-
+ DEG_debug_print_eval_time(__func__, scene->id.name, scene, ctime);
/* evaluate rigidbody sim */
if (BKE_scene_check_rigidbody_active(scene)) {
BKE_rigidbody_do_simulation(eval_ctx, scene, ctime);
@@ -1720,11 +1720,7 @@ void BKE_rigidbody_object_sync_transforms(const struct EvaluationContext *UNUSED
{
RigidBodyWorld *rbw = scene->rigidbody_world;
float ctime = BKE_scene_frame_get(scene);
-
- if (G.debug & G_DEBUG_DEPSGRAPH) {
- printf("%s on %s\n", __func__, ob->id.name);
- }
-
+ DEG_debug_print_eval_time(__func__, ob->id.name, ob, ctime);
/* read values pushed into RBO from sim/cache... */
BKE_rigidbody_sync_transforms(rbw, ob, ctime);
}
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 16e9844241d..9a7c10d31de 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -151,6 +151,83 @@ static void remove_sequencer_fcurves(Scene *sce)
}
}
+/* flag -- copying options (see BKE_library.h's LIB_ID_COPY_... flags for more). */
+ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag)
+{
+ if (toolsettings == NULL) {
+ return NULL;
+ }
+ ToolSettings *ts = MEM_dupallocN(toolsettings);
+ if (ts->vpaint) {
+ ts->vpaint = MEM_dupallocN(ts->vpaint);
+ BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint, flag);
+ }
+ if (ts->wpaint) {
+ ts->wpaint = MEM_dupallocN(ts->wpaint);
+ BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint, flag);
+ }
+ if (ts->sculpt) {
+ ts->sculpt = MEM_dupallocN(ts->sculpt);
+ BKE_paint_copy(&ts->sculpt->paint, &ts->sculpt->paint, flag);
+ }
+ if (ts->uvsculpt) {
+ ts->uvsculpt = MEM_dupallocN(ts->uvsculpt);
+ BKE_paint_copy(&ts->uvsculpt->paint, &ts->uvsculpt->paint, flag);
+ }
+
+ BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint, flag);
+ ts->imapaint.paintcursor = NULL;
+ ts->particle.paintcursor = NULL;
+ ts->particle.scene = NULL;
+ ts->particle.object = NULL;
+
+ /* duplicate Grease Pencil Drawing Brushes */
+ BLI_listbase_clear(&ts->gp_brushes);
+ for (bGPDbrush *brush = toolsettings->gp_brushes.first; brush; brush = brush->next) {
+ bGPDbrush *newbrush = BKE_gpencil_brush_duplicate(brush);
+ BLI_addtail(&ts->gp_brushes, newbrush);
+ }
+
+ /* duplicate Grease Pencil interpolation curve */
+ ts->gp_interpolate.custom_ipo = curvemapping_copy(ts->gp_interpolate.custom_ipo);
+ return ts;
+}
+
+void BKE_toolsettings_free(ToolSettings *toolsettings)
+{
+ if (toolsettings == NULL) {
+ return;
+ }
+ if (toolsettings->vpaint) {
+ BKE_paint_free(&toolsettings->vpaint->paint);
+ MEM_freeN(toolsettings->vpaint);
+ }
+ if (toolsettings->wpaint) {
+ BKE_paint_free(&toolsettings->wpaint->paint);
+ MEM_freeN(toolsettings->wpaint);
+ }
+ if (toolsettings->sculpt) {
+ BKE_paint_free(&toolsettings->sculpt->paint);
+ MEM_freeN(toolsettings->sculpt);
+ }
+ if (toolsettings->uvsculpt) {
+ BKE_paint_free(&toolsettings->uvsculpt->paint);
+ MEM_freeN(toolsettings->uvsculpt);
+ }
+ BKE_paint_free(&toolsettings->imapaint.paint);
+
+ /* free Grease Pencil Drawing Brushes */
+ BKE_gpencil_free_brushes(&toolsettings->gp_brushes);
+ BLI_freelistN(&toolsettings->gp_brushes);
+
+ /* free Grease Pencil interpolation curve */
+ if (toolsettings->gp_interpolate.custom_ipo) {
+ curvemapping_free(toolsettings->gp_interpolate.custom_ipo);
+ }
+
+ MEM_freeN(toolsettings);
+}
+
/**
* Only copy internal data of Scene 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.
@@ -166,7 +243,6 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons
sce_dst->ed = NULL;
sce_dst->depsgraph_hash = NULL;
- sce_dst->obedit = NULL;
sce_dst->fps_info = NULL;
/* layers and collections */
@@ -224,41 +300,7 @@ void BKE_scene_copy_data(Main *bmain, Scene *sce_dst, const Scene *sce_src, cons
curvemapping_copy_data(&sce_dst->r.mblur_shutter_curve, &sce_src->r.mblur_shutter_curve);
/* tool settings */
- if (sce_dst->toolsettings != NULL) {
- ToolSettings *ts = sce_dst->toolsettings = MEM_dupallocN(sce_dst->toolsettings);
- if (ts->vpaint) {
- ts->vpaint = MEM_dupallocN(ts->vpaint);
- BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint, flag_subdata);
- }
- if (ts->wpaint) {
- ts->wpaint = MEM_dupallocN(ts->wpaint);
- BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint, flag_subdata);
- }
- if (ts->sculpt) {
- ts->sculpt = MEM_dupallocN(ts->sculpt);
- BKE_paint_copy(&ts->sculpt->paint, &ts->sculpt->paint, flag_subdata);
- }
- if (ts->uvsculpt) {
- ts->uvsculpt = MEM_dupallocN(ts->uvsculpt);
- BKE_paint_copy(&ts->uvsculpt->paint, &ts->uvsculpt->paint, flag_subdata);
- }
-
- BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint, flag_subdata);
- ts->imapaint.paintcursor = NULL;
- ts->particle.paintcursor = NULL;
- ts->particle.scene = NULL;
- ts->particle.object = NULL;
-
- /* duplicate Grease Pencil Drawing Brushes */
- BLI_listbase_clear(&ts->gp_brushes);
- for (bGPDbrush *brush = sce_src->toolsettings->gp_brushes.first; brush; brush = brush->next) {
- bGPDbrush *newbrush = BKE_gpencil_brush_duplicate(brush);
- BLI_addtail(&ts->gp_brushes, newbrush);
- }
-
- /* duplicate Grease Pencil interpolation curve */
- ts->gp_interpolate.custom_ipo = curvemapping_copy(ts->gp_interpolate.custom_ipo);
- }
+ sce_dst->toolsettings = BKE_toolsettings_copy(sce_dst->toolsettings, flag_subdata);
/* make a private copy of the avicodecdata */
if (sce_src->r.avicodecdata) {
@@ -297,7 +339,6 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
/* TODO this should/could most likely be replaced by call to more generic code at some point...
* But for now, let's keep it well isolated here. */
if (type == SCE_COPY_EMPTY) {
- ToolSettings *ts;
ListBase rv;
sce_copy = BKE_scene_add(bmain, sce->id.name + 2);
@@ -332,46 +373,7 @@ Scene *BKE_scene_copy(Main *bmain, Scene *sce, int type)
curvemapping_copy_data(&sce_copy->r.mblur_shutter_curve, &sce->r.mblur_shutter_curve);
/* tool settings */
- sce_copy->toolsettings = MEM_dupallocN(sce->toolsettings);
-
- ts = sce_copy->toolsettings;
- if (ts) {
- if (ts->vpaint) {
- ts->vpaint = MEM_dupallocN(ts->vpaint);
- BKE_paint_copy(&ts->vpaint->paint, &ts->vpaint->paint, 0);
- }
- if (ts->wpaint) {
- ts->wpaint = MEM_dupallocN(ts->wpaint);
- BKE_paint_copy(&ts->wpaint->paint, &ts->wpaint->paint, 0);
- }
- if (ts->sculpt) {
- ts->sculpt = MEM_dupallocN(ts->sculpt);
- BKE_paint_copy(&ts->sculpt->paint, &ts->sculpt->paint, 0);
- }
- if (ts->uvsculpt) {
- ts->uvsculpt = MEM_dupallocN(ts->uvsculpt);
- BKE_paint_copy(&ts->uvsculpt->paint, &ts->uvsculpt->paint, 0);
- }
-
- BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint, 0);
- ts->imapaint.paintcursor = NULL;
- id_us_plus((ID *)ts->imapaint.stencil);
- id_us_plus((ID *)ts->imapaint.clone);
- id_us_plus((ID *)ts->imapaint.canvas);
- ts->particle.paintcursor = NULL;
- ts->particle.scene = NULL;
- ts->particle.object = NULL;
-
- /* duplicate Grease Pencil Drawing Brushes */
- BLI_listbase_clear(&ts->gp_brushes);
- for (bGPDbrush *brush = sce->toolsettings->gp_brushes.first; brush; brush = brush->next) {
- bGPDbrush *newbrush = BKE_gpencil_brush_duplicate(brush);
- BLI_addtail(&ts->gp_brushes, newbrush);
- }
-
- /* duplicate Grease Pencil interpolation curve */
- ts->gp_interpolate.custom_ipo = curvemapping_copy(ts->gp_interpolate.custom_ipo);
- }
+ sce_copy->toolsettings = BKE_toolsettings_copy(sce->toolsettings, 0);
/* make a private copy of the avicodecdata */
if (sce->r.avicodecdata) {
@@ -493,37 +495,8 @@ void BKE_scene_free_ex(Scene *sce, const bool do_id_user)
BLI_freelistN(&sce->markers);
BLI_freelistN(&sce->r.views);
- if (sce->toolsettings) {
- if (sce->toolsettings->vpaint) {
- BKE_paint_free(&sce->toolsettings->vpaint->paint);
- MEM_freeN(sce->toolsettings->vpaint);
- }
- if (sce->toolsettings->wpaint) {
- BKE_paint_free(&sce->toolsettings->wpaint->paint);
- MEM_freeN(sce->toolsettings->wpaint);
- }
- if (sce->toolsettings->sculpt) {
- BKE_paint_free(&sce->toolsettings->sculpt->paint);
- MEM_freeN(sce->toolsettings->sculpt);
- }
- if (sce->toolsettings->uvsculpt) {
- BKE_paint_free(&sce->toolsettings->uvsculpt->paint);
- MEM_freeN(sce->toolsettings->uvsculpt);
- }
- BKE_paint_free(&sce->toolsettings->imapaint.paint);
-
- /* free Grease Pencil Drawing Brushes */
- BKE_gpencil_free_brushes(&sce->toolsettings->gp_brushes);
- BLI_freelistN(&sce->toolsettings->gp_brushes);
-
- /* free Grease Pencil interpolation curve */
- if (sce->toolsettings->gp_interpolate.custom_ipo) {
- curvemapping_free(sce->toolsettings->gp_interpolate.custom_ipo);
- }
-
- MEM_freeN(sce->toolsettings);
- sce->toolsettings = NULL;
- }
+ BKE_toolsettings_free(sce->toolsettings);
+ sce->toolsettings = NULL;
BKE_scene_free_depsgraph_hash(sce);
@@ -618,7 +591,7 @@ void BKE_scene_init(Scene *sce)
*/
sce->r.color_mgt_flag |= R_COLOR_MANAGEMENT;
- sce->r.gauss = 1.0;
+ sce->r.gauss = 1.5f;
/* deprecated but keep for upwards compat */
sce->r.postgamma = 1.0;
@@ -982,21 +955,17 @@ void BKE_scene_set_background(Main *bmain, Scene *scene)
/* check for cyclic sets, for reading old files but also for definite security (py?) */
BKE_scene_validate_setscene(bmain, scene);
- /* can happen when switching modes in other scenes */
- if (scene->obedit && !(scene->obedit->mode & OB_MODE_EDIT))
- scene->obedit = NULL;
-
/* deselect objects (for dataselect) */
for (ob = bmain->object.first; ob; ob = ob->id.next)
ob->flag &= ~(SELECT | OB_FROMGROUP);
/* group flags again */
for (group = bmain->group.first; group; group = group->id.next) {
- FOREACH_GROUP_OBJECT(group, object)
+ FOREACH_GROUP_OBJECT_BEGIN(group, object)
{
object->flag |= OB_FROMGROUP;
}
- FOREACH_GROUP_OBJECT_END
+ FOREACH_GROUP_OBJECT_END;
}
/* copy layers and flags from bases to objects */
@@ -1381,7 +1350,10 @@ static bool check_rendered_viewport_visible(Main *bmain)
return false;
}
-static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene)
+/* TODO(campbell): shouldn't we be able to use 'eval_ctx->view_layer' here?
+ * Currently this is NULL on load, so don't. */
+static void prepare_mesh_for_viewport_render(
+ Main *bmain, const ViewLayer *view_layer)
{
/* This is needed to prepare mesh to be used by the render
* engine from the viewport rendering. We do loading here
@@ -1392,7 +1364,7 @@ static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene)
* call loading of the edit data for the mesh objects.
*/
- Object *obedit = scene->obedit;
+ Object *obedit = OBEDIT_FROM_VIEW_LAYER(view_layer);
if (obedit) {
Mesh *mesh = obedit->data;
if ((obedit->type == OB_MESH) &&
@@ -1401,7 +1373,11 @@ 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}));
+ BM_mesh_bm_to_me(
+ bm, mesh,
+ (&(struct BMeshToMeshParams){
+ .calc_object_remap = true,
+ }));
DEG_id_tag_update(&mesh->id, 0);
}
}
@@ -1411,17 +1387,12 @@ static void prepare_mesh_for_viewport_render(Main *bmain, Scene *scene)
/* TODO(sergey): This actually should become view_layer_graph or so.
* Same applies to update_for_newframe.
*/
-void BKE_scene_graph_update_tagged(EvaluationContext *eval_ctx,
- Depsgraph *depsgraph,
- Main *bmain,
- Scene *scene,
- ViewLayer *view_layer)
+void BKE_scene_graph_update_tagged(Depsgraph *depsgraph,
+ Main *bmain)
{
- /* 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);
- }
+ Scene *scene = DEG_get_input_scene(depsgraph);
+ ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
+
/* TODO(sergey): Some functions here are changing global state,
* for example, clearing update tags from bmain.
*/
@@ -1430,13 +1401,13 @@ void BKE_scene_graph_update_tagged(EvaluationContext *eval_ctx,
/* 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);
+ prepare_mesh_for_viewport_render(bmain, view_layer);
/* Flush recalc flags to dependencies. */
DEG_graph_flush_update(bmain, depsgraph);
/* Update all objects: drivers, matrices, displists, etc. flags set
* by depgraph or manual, no layer check here, gets correct flushed.
*/
- DEG_evaluate_on_refresh(eval_ctx, depsgraph);
+ DEG_evaluate_on_refresh(depsgraph);
/* Update sound system animation (TODO, move to depsgraph). */
BKE_sound_update_scene(bmain, scene);
/* Inform editors about possible changes. */
@@ -1446,17 +1417,12 @@ void BKE_scene_graph_update_tagged(EvaluationContext *eval_ctx,
}
/* applies changes right away, does all sets too */
-void BKE_scene_graph_update_for_newframe(EvaluationContext *eval_ctx,
- Depsgraph *depsgraph,
- Main *bmain,
- Scene *scene,
- ViewLayer *view_layer)
+void BKE_scene_graph_update_for_newframe(Depsgraph *depsgraph,
+ Main *bmain)
{
- /* 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);
- }
+ Scene *scene = DEG_get_input_scene(depsgraph);
+ ViewLayer *view_layer = DEG_get_input_view_layer(depsgraph);
+
/* TODO(sergey): Some functions here are changing global state,
* for example, clearing update tags from bmain.
*/
@@ -1481,7 +1447,7 @@ void BKE_scene_graph_update_for_newframe(EvaluationContext *eval_ctx,
/* Update all objects: drivers, matrices, displists, etc. flags set
* by depgraph or manual, no layer check here, gets correct flushed.
*/
- DEG_evaluate_on_framechange(eval_ctx, bmain, depsgraph, ctime);
+ DEG_evaluate_on_framechange(bmain, depsgraph, ctime);
/* Update sound system animation (TODO, move to depsgraph). */
BKE_sound_update_scene(bmain, scene);
/* Notify editors and python about recalc. */
@@ -2222,7 +2188,7 @@ Depsgraph *BKE_scene_get_depsgraph(Scene *scene,
{
*key_ptr = MEM_mallocN(sizeof(DepsgraphKey), __func__);
**key_ptr = key;
- *depsgraph_ptr = DEG_graph_new();
+ *depsgraph_ptr = DEG_graph_new(scene, view_layer, DAG_EVAL_VIEWPORT);
}
depsgraph = *depsgraph_ptr;
}
diff --git a/source/blender/blenkernel/intern/screen.c b/source/blender/blenkernel/intern/screen.c
index 754f59d2e33..c1b3a4ae0c8 100644
--- a/source/blender/blenkernel/intern/screen.c
+++ b/source/blender/blenkernel/intern/screen.c
@@ -39,8 +39,6 @@
#include "MEM_guardedalloc.h"
-#include "GPU_compositing.h"
-
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
@@ -182,7 +180,7 @@ ARegion *BKE_area_region_copy(SpaceType *st, ARegion *ar)
BLI_listbase_clear(&newar->panels_category);
BLI_listbase_clear(&newar->panels_category_active);
BLI_listbase_clear(&newar->ui_lists);
- newar->swinid = 0;
+ newar->visible = 0;
newar->manipulator_map = NULL;
newar->regiontimer = NULL;
newar->headerstr = NULL;
@@ -684,29 +682,6 @@ float BKE_screen_view3d_zoom_from_fac(float zoomfac)
return ((sqrtf(4.0f * zoomfac) - (float)M_SQRT2) * 50.0f);
}
-void BKE_screen_gpu_fx_validate(GPUFXSettings *fx_settings)
-{
- /* currently we use DOF from the camera _only_,
- * so we never allocate this, only copy from the Camera */
-#if 0
- if ((fx_settings->dof == NULL) &&
- (fx_settings->fx_flag & GPU_FX_FLAG_DOF))
- {
- GPUDOFSettings *fx_dof;
- fx_dof = fx_settings->dof = MEM_callocN(sizeof(GPUDOFSettings), __func__);
- }
-#endif
-
- if ((fx_settings->ssao == NULL) &&
- (fx_settings->fx_flag & GPU_FX_FLAG_SSAO))
- {
- GPUSSAOSettings *fx_ssao;
- fx_ssao = fx_settings->ssao = MEM_callocN(sizeof(GPUSSAOSettings), __func__);
-
- GPU_fx_compositor_init_ssao_settings(fx_ssao);
- }
-}
-
bool BKE_screen_is_fullscreen_area(const bScreen *screen)
{
return ELEM(screen->state, SCREENMAXIMIZED, SCREENFULL);
diff --git a/source/blender/blenkernel/intern/seqeffects.c b/source/blender/blenkernel/intern/seqeffects.c
index ee80438db64..49f120de250 100644
--- a/source/blender/blenkernel/intern/seqeffects.c
+++ b/source/blender/blenkernel/intern/seqeffects.c
@@ -52,6 +52,7 @@
#include "IMB_imbuf_types.h"
#include "IMB_imbuf.h"
#include "IMB_colormanagement.h"
+#include "IMB_metadata.h"
#include "BLI_math_color_blend.h"
diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c
index 424f4269f3c..58b83a754d8 100644
--- a/source/blender/blenkernel/intern/sequencer.c
+++ b/source/blender/blenkernel/intern/sequencer.c
@@ -86,6 +86,7 @@
#include "IMB_imbuf.h"
#include "IMB_imbuf_types.h"
#include "IMB_colormanagement.h"
+#include "IMB_metadata.h"
#include "BKE_context.h"
#include "BKE_sound.h"
@@ -946,6 +947,8 @@ void BKE_sequence_reload_new_file(Scene *scene, Sequence *seq, const bool lock_r
return;
}
+ IMB_anim_load_metadata(sanim->anim);
+
seq->len = IMB_anim_get_duration(sanim->anim, seq->strip->proxy ? seq->strip->proxy->tc : IMB_TC_RECORD_RUN);
seq->anim_preseek = IMB_anim_get_preseek(sanim->anim);
@@ -1680,6 +1683,11 @@ static bool seq_proxy_get_fname(Editing *ed, Sequence *seq, int cfra, int render
else if (seq->type == SEQ_TYPE_IMAGE) {
fname[0] = 0;
}
+ else {
+ /* We could make a name here, except non-movie's don't generate proxies,
+ * cancel until other types of sequence strips are supported. */
+ return false;
+ }
BLI_path_append(dir, sizeof(dir), fname);
BLI_path_abs(name, G.main->name);
}
@@ -2954,7 +2962,7 @@ static ImBuf *seq_render_movie_strip(const SeqRenderData *context, Sequence *seq
int totviews;
int i;
- if (totfiles != BLI_listbase_count_ex(&seq->anims, totfiles + 1))
+ if (totfiles != BLI_listbase_count_at_most(&seq->anims, totfiles + 1))
goto monoview_movie;
totviews = BKE_scene_multiview_num_views_get(&context->scene->r);
@@ -3264,9 +3272,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. */
+ /* Get view layer for the strip. */
ViewLayer *view_layer = BKE_view_layer_from_scene_get(scene);
- Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
+ /* Depsgraph will be NULL when doing rendering. */
+ Depsgraph *depsgraph = NULL;
orig_data.scemode = scene->r.scemode;
orig_data.cfra = scene->r.cfra;
@@ -3323,14 +3332,16 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
context->scene->r.seq_prev_type = 3 /* == OB_SOLID */;
/* opengl offscreen render */
- 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);
+ RenderEngineType *engine_type = RE_engines_find(scene->view_render.engine_id);
+ depsgraph = BKE_scene_get_depsgraph(scene, view_layer, true);
+ BKE_scene_graph_update_for_newframe(depsgraph, context->bmain);
ibuf = sequencer_view3d_cb(
/* set for OpenGL render (NULL when scrubbing) */
- context->eval_ctx, scene, view_layer, camera, width, height, IB_rect,
+ context->eval_ctx, scene, view_layer, engine_type,
+ 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);
+ context->gpu_offscreen, err_out);
if (ibuf == NULL) {
fprintf(stderr, "seq_render_scene_strip failed to get opengl buffer: %s\n", err_out);
}
@@ -3355,15 +3366,7 @@ static ImBuf *seq_render_scene_strip(const SeqRenderData *context, Sequence *seq
if (re == NULL)
re = RE_NewSceneRender(scene);
- /* 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);
+ RE_BlenderFrame(re, context->bmain, scene, view_layer, camera, scene->lay, frame, false);
/* restore previous state after it was toggled on & off by RE_BlenderFrame */
G.is_rendering = is_rendering;
@@ -3421,8 +3424,8 @@ finally:
scene->r.cfra = orig_data.cfra;
scene->r.subframe = orig_data.subframe;
- if (is_frame_update) {
- BKE_scene_graph_update_for_newframe(context->eval_ctx, depsgraph, context->bmain, scene, view_layer);
+ if (is_frame_update && (depsgraph != NULL)) {
+ BKE_scene_graph_update_for_newframe(depsgraph, context->bmain);
}
#ifdef DURIAN_CAMERA_SWITCH
@@ -5167,6 +5170,40 @@ void BKE_sequence_init_colorspace(Sequence *seq)
}
}
+float BKE_sequence_get_fps(Scene *scene, Sequence *seq)
+{
+ switch (seq->type) {
+ case SEQ_TYPE_MOVIE:
+ {
+ seq_open_anim_file(scene, seq, true);
+ if (BLI_listbase_is_empty(&seq->anims)) {
+ return 0.0f;
+ }
+ StripAnim *strip_anim = seq->anims.first;
+ if (strip_anim->anim == NULL) {
+ return 0.0f;
+ }
+ short frs_sec;
+ float frs_sec_base;
+ if (IMB_anim_get_fps(strip_anim->anim, &frs_sec, &frs_sec_base, true)) {
+ return (float)frs_sec / frs_sec_base;
+ }
+ break;
+ }
+ case SEQ_TYPE_MOVIECLIP:
+ if (seq->clip != NULL) {
+ return BKE_movieclip_get_fps(seq->clip);
+ }
+ break;
+ case SEQ_TYPE_SCENE:
+ if (seq->scene != NULL) {
+ return (float)seq->scene->r.frs_sec / seq->scene->r.frs_sec_base;
+ }
+ break;
+ }
+ return 0.0f;
+}
+
/* NOTE: this function doesn't fill in image names */
Sequence *BKE_sequencer_add_image_strip(bContext *C, ListBase *seqbasep, SeqLoadInfo *seq_load)
{
@@ -5359,6 +5396,8 @@ Sequence *BKE_sequencer_add_movie_strip(bContext *C, ListBase *seqbasep, SeqLoad
}
}
+ IMB_anim_load_metadata(anim_arr[0]);
+
seq->anim_preseek = IMB_anim_get_preseek(anim_arr[0]);
BLI_strncpy(seq->name + 2, "Movie", SEQ_NAME_MAXSTR - 2);
BKE_sequence_base_unique_name_recursive(&scene->ed->seqbase, seq);
diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c
index 9f9818127bc..9215d56eb30 100644
--- a/source/blender/blenkernel/intern/smoke.c
+++ b/source/blender/blenkernel/intern/smoke.c
@@ -72,7 +72,6 @@
#include "BKE_customdata.h"
#include "BKE_deform.h"
#include "BKE_DerivedMesh.h"
-#include "BKE_global.h"
#include "BKE_effect.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
@@ -170,11 +169,11 @@ void smoke_reallocate_highres_fluid(SmokeDomainSettings *sds, float dx, int res[
}
/* smoke_turbulence_init uses non-threadsafe functions from fftw3 lib (like fftw_plan & co). */
- BLI_lock_thread(LOCK_FFTW);
+ BLI_thread_lock(LOCK_FFTW);
sds->wt = smoke_turbulence_init(res, sds->amplify + 1, sds->noise, BKE_tempdir_session(), use_fire, use_colors);
- BLI_unlock_thread(LOCK_FFTW);
+ BLI_thread_unlock(LOCK_FFTW);
sds->res_wt[0] = res[0] * (sds->amplify + 1);
sds->res_wt[1] = res[1] * (sds->amplify + 1);
@@ -525,8 +524,8 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
smd->domain->burning_rate = 0.75f;
smd->domain->flame_smoke = 1.0f;
smd->domain->flame_vorticity = 0.5f;
- smd->domain->flame_ignition = 1.25f;
- smd->domain->flame_max_temp = 1.75f;
+ smd->domain->flame_ignition = 1.5f;
+ smd->domain->flame_max_temp = 3.0f;
/* color */
smd->domain->flame_smoke_color[0] = 0.7f;
smd->domain->flame_smoke_color[1] = 0.7f;
@@ -553,6 +552,8 @@ void smokeModifier_createType(struct SmokeModifierData *smd)
smd->domain->coba = NULL;
smd->domain->coba_field = FLUID_FIELD_DENSITY;
+
+ smd->domain->clipping = 1e-3f;
}
else if (smd->type & MOD_SMOKE_TYPE_FLOW)
{
@@ -1287,6 +1288,8 @@ static void emit_from_particles(
curvemapping_changed_all(psys->part->clumpcurve);
if ((psys->part->child_flag & PART_CHILD_USE_ROUGH_CURVE) && psys->part->roughcurve)
curvemapping_changed_all(psys->part->roughcurve);
+ if ((psys->part->child_flag & PART_CHILD_USE_TWIST_CURVE) && psys->part->twistcurve)
+ curvemapping_changed_all(psys->part->twistcurve);
/* initialize particle cache */
if (psys->part->type == PART_HAIR) {
diff --git a/source/blender/blenkernel/intern/softbody.c b/source/blender/blenkernel/intern/softbody.c
index 3cfa8787f4b..1fb95bd3115 100644
--- a/source/blender/blenkernel/intern/softbody.c
+++ b/source/blender/blenkernel/intern/softbody.c
@@ -1580,12 +1580,12 @@ static void sb_sfesf_threads_run(const struct EvaluationContext *eval_ctx, Scene
sb_threads[i].tot= totthread;
}
if (totthread > 1) {
- BLI_init_threads(&threads, exec_scan_for_ext_spring_forces, totthread);
+ BLI_threadpool_init(&threads, exec_scan_for_ext_spring_forces, totthread);
for (i=0; i<totthread; i++)
- BLI_insert_thread(&threads, &sb_threads[i]);
+ BLI_threadpool_insert(&threads, &sb_threads[i]);
- BLI_end_threads(&threads);
+ BLI_threadpool_end(&threads);
}
else
exec_scan_for_ext_spring_forces(&sb_threads[0]);
@@ -2192,12 +2192,12 @@ static void sb_cf_threads_run(Scene *scene, Object *ob, float forcetime, float t
if (totthread > 1) {
- BLI_init_threads(&threads, exec_softbody_calc_forces, totthread);
+ BLI_threadpool_init(&threads, exec_softbody_calc_forces, totthread);
for (i=0; i<totthread; i++)
- BLI_insert_thread(&threads, &sb_threads[i]);
+ BLI_threadpool_insert(&threads, &sb_threads[i]);
- BLI_end_threads(&threads);
+ BLI_threadpool_end(&threads);
}
else
exec_softbody_calc_forces(&sb_threads[0]);
diff --git a/source/blender/blenkernel/intern/speaker.c b/source/blender/blenkernel/intern/speaker.c
index 9d604a9382a..1d2e12f34ac 100644
--- a/source/blender/blenkernel/intern/speaker.c
+++ b/source/blender/blenkernel/intern/speaker.c
@@ -32,7 +32,6 @@
#include "BLI_utildefines.h"
#include "BKE_animsys.h"
-#include "BKE_global.h"
#include "BKE_library.h"
#include "BKE_library_query.h"
#include "BKE_library_remap.h"
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 1c3ff352126..9280341b4e4 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -361,7 +361,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
#ifdef USE_DYNSIZE
CCGVertHDL fverts[nverts];
#else
- BLI_array_empty(fverts);
+ BLI_array_clear(fverts);
BLI_array_grow_items(fverts, nverts);
#endif
@@ -400,7 +400,7 @@ static int ss_sync_from_uv(CCGSubSurf *ss, CCGSubSurf *origss, DerivedMesh *dm,
#ifdef USE_DYNSIZE
CCGVertHDL fverts[nverts];
#else
- BLI_array_empty(fverts);
+ BLI_array_clear(fverts);
BLI_array_grow_items(fverts, nverts);
#endif
@@ -744,7 +744,7 @@ static void ss_sync_ccg_from_derivedmesh(CCGSubSurf *ss,
#ifdef USE_DYNSIZE
CCGVertHDL fVerts[mp->totloop];
#else
- BLI_array_empty(fVerts);
+ BLI_array_clear(fVerts);
BLI_array_grow_items(fVerts, mp->totloop);
#endif
@@ -4583,7 +4583,7 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
*((int *)ccgSubSurf_getFaceUserData(ss, f)) = vertNum;
#ifndef USE_DYNSIZE
- BLI_array_empty(loopidx);
+ BLI_array_clear(loopidx);
BLI_array_grow_items(loopidx, numVerts);
#endif
for (s = 0; s < numVerts; s++) {
@@ -4591,7 +4591,7 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
}
#ifndef USE_DYNSIZE
- BLI_array_empty(vertidx);
+ BLI_array_clear(vertidx);
BLI_array_grow_items(vertidx, numVerts);
#endif
for (s = 0; s < numVerts; s++) {
diff --git a/source/blender/blenkernel/intern/text.c b/source/blender/blenkernel/intern/text.c
index 4ae9818f891..cd9b8ae339d 100644
--- a/source/blender/blenkernel/intern/text.c
+++ b/source/blender/blenkernel/intern/text.c
@@ -120,13 +120,56 @@
*
*/
+
+/* Undo opcodes */
+
+enum {
+ /* Complex editing */
+ /* 1 - opcode is followed by 1 byte for ascii character and opcode (repeat)) */
+ /* 2 - opcode is followed by 2 bytes for utf-8 character and opcode (repeat)) */
+ /* 3 - opcode is followed by 3 bytes for utf-8 character and opcode (repeat)) */
+ /* 4 - opcode is followed by 4 bytes for unicode character and opcode (repeat)) */
+ UNDO_INSERT_1 = 013,
+ UNDO_INSERT_2 = 014,
+ UNDO_INSERT_3 = 015,
+ UNDO_INSERT_4 = 016,
+
+ UNDO_BS_1 = 017,
+ UNDO_BS_2 = 020,
+ UNDO_BS_3 = 021,
+ UNDO_BS_4 = 022,
+
+ UNDO_DEL_1 = 023,
+ UNDO_DEL_2 = 024,
+ UNDO_DEL_3 = 025,
+ UNDO_DEL_4 = 026,
+
+ /* Text block (opcode is followed
+ * by 4 character length ID + the text
+ * block itself + the 4 character length
+ * ID (repeat) and opcode (repeat)) */
+ UNDO_DBLOCK = 027, /* Delete block */
+ UNDO_IBLOCK = 030, /* Insert block */
+
+ /* Misc */
+ UNDO_INDENT = 032,
+ UNDO_UNINDENT = 033,
+ UNDO_COMMENT = 034,
+ UNDO_UNCOMMENT = 035,
+
+ UNDO_MOVE_LINES_UP = 036,
+ UNDO_MOVE_LINES_DOWN = 037,
+
+ UNDO_DUPLICATE = 040,
+};
+
/***/
static void txt_pop_first(Text *text);
static void txt_pop_last(Text *text);
-static void txt_undo_add_blockop(Text *text, int op, const char *buf);
+static void txt_undo_add_blockop(Text *text, TextUndoBuf *utxt, int op, const char *buf);
static void txt_delete_line(Text *text, TextLine *line);
-static void txt_delete_sel(Text *text);
+static void txt_delete_sel(Text *text, TextUndoBuf *utxt);
static void txt_make_dirty(Text *text);
/***/
@@ -144,13 +187,6 @@ int txt_get_undostate(void)
return undoing;
}
-static void init_undo_text(Text *text)
-{
- text->undo_pos = -1;
- text->undo_len = TXT_INIT_UNDO;
- text->undo_buf = MEM_mallocN(text->undo_len, "undo buf");
-}
-
/**
* \note caller must handle `undo_buf` and `compiled` members.
*/
@@ -178,7 +214,6 @@ void BKE_text_free(Text *text)
BKE_text_free_lines(text);
MEM_SAFE_FREE(text->name);
- MEM_SAFE_FREE(text->undo_buf);
#ifdef WITH_PYTHON
BPY_text_free_code(text);
#endif
@@ -192,8 +227,6 @@ void BKE_text_init(Text *ta)
ta->name = NULL;
- init_undo_text(ta);
-
ta->nlines = 1;
ta->flags = TXT_ISDIRTY | TXT_ISMEM;
if ((U.flag & USER_TXT_TABSTOSPACES_DISABLE) == 0)
@@ -375,10 +408,6 @@ bool BKE_text_reload(Text *text)
txt_make_dirty(text);
/* clear undo buffer */
- MEM_freeN(text->undo_buf);
- init_undo_text(text);
-
-
if (BLI_stat(filepath_abs, &st) != -1) {
text->mtime = st.st_mtime;
}
@@ -427,8 +456,6 @@ Text *BKE_text_load_ex(Main *bmain, const char *file, const char *relpath, const
}
/* clear undo buffer */
- init_undo_text(ta);
-
if (BLI_stat(filepath_abs, &st) != -1) {
ta->mtime = st.st_mtime;
}
@@ -482,8 +509,6 @@ void BKE_text_copy_data(Main *UNUSED(bmain), Text *ta_dst, const Text *ta_src, c
ta_dst->curl = ta_dst->sell = ta_dst->lines.first;
ta_dst->curc = ta_dst->selc = 0;
-
- init_undo_text(ta_dst);
}
Text *BKE_text_copy(Main *bmain, const Text *ta)
@@ -498,25 +523,29 @@ void BKE_text_make_local(Main *bmain, Text *text, const bool lib_local)
BKE_id_make_local_generic(bmain, &text->id, true, lib_local);
}
-void BKE_text_clear(Text *text) /* called directly from rna */
+void BKE_text_clear(Text *text, TextUndoBuf *utxt) /* called directly from rna */
{
int oldstate;
- oldstate = txt_get_undostate();
- txt_set_undostate(1);
+ if (utxt) {
+ oldstate = txt_get_undostate();
+ }
+ txt_set_undostate(utxt != NULL);
+
txt_sel_all(text);
- txt_delete_sel(text);
+ txt_delete_sel(text, utxt);
+
txt_set_undostate(oldstate);
txt_make_dirty(text);
}
-void BKE_text_write(Text *text, const char *str) /* called directly from rna */
+void BKE_text_write(Text *text, TextUndoBuf *utxt, const char *str) /* called directly from rna */
{
int oldstate;
oldstate = txt_get_undostate();
- txt_insert_buf(text, str);
+ txt_insert_buf(text, utxt, str);
txt_move_eof(text, 0);
txt_set_undostate(oldstate);
@@ -1109,7 +1138,7 @@ bool txt_has_sel(Text *text)
return ((text->curl != text->sell) || (text->curc != text->selc));
}
-static void txt_delete_sel(Text *text)
+static void txt_delete_sel(Text *text, TextUndoBuf *utxt)
{
TextLine *tmpl;
char *buf;
@@ -1123,7 +1152,7 @@ static void txt_delete_sel(Text *text)
if (!undoing) {
buf = txt_sel_to_buf(text);
- txt_undo_add_blockop(text, UNDO_DBLOCK, buf);
+ txt_undo_add_blockop(text, utxt, UNDO_DBLOCK, buf);
MEM_freeN(buf);
}
@@ -1364,7 +1393,7 @@ char *txt_sel_to_buf(Text *text)
return buf;
}
-void txt_insert_buf(Text *text, const char *in_buffer)
+void txt_insert_buf(Text *text, TextUndoBuf *utxt, const char *in_buffer)
{
int l = 0, u, len;
size_t i = 0, j;
@@ -1373,22 +1402,22 @@ void txt_insert_buf(Text *text, const char *in_buffer)
if (!in_buffer) return;
- txt_delete_sel(text);
+ txt_delete_sel(text, utxt);
len = strlen(in_buffer);
buffer = BLI_strdupn(in_buffer, len);
len += txt_extended_ascii_as_utf8(&buffer);
- if (!undoing) txt_undo_add_blockop(text, UNDO_IBLOCK, buffer);
+ if (!undoing) txt_undo_add_blockop(text, utxt, UNDO_IBLOCK, buffer);
u = undoing;
undoing = 1;
/* Read the first line (or as close as possible */
while (buffer[i] && buffer[i] != '\n')
- txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, &i));
+ txt_add_raw_char(text, utxt, BLI_str_utf8_as_unicode_step(buffer, &i));
- if (buffer[i] == '\n') txt_split_curline(text);
+ if (buffer[i] == '\n') txt_split_curline(text, utxt);
else { undoing = u; MEM_freeN(buffer); return; }
i++;
@@ -1406,7 +1435,7 @@ void txt_insert_buf(Text *text, const char *in_buffer)
}
else {
for (j = i - l; j < i && j < len; )
- txt_add_raw_char(text, BLI_str_utf8_as_unicode_step(buffer, &j));
+ txt_add_raw_char(text, utxt, BLI_str_utf8_as_unicode_step(buffer, &j));
break;
}
}
@@ -1420,33 +1449,47 @@ void txt_insert_buf(Text *text, const char *in_buffer)
/* Undo functions */
/******************/
-static bool max_undo_test(Text *text, int x)
+static bool max_undo_test(TextUndoBuf *utxt, int x)
{
- while (text->undo_pos + x >= text->undo_len) {
- if (text->undo_len * 2 > TXT_MAX_UNDO) {
- /* XXX error("Undo limit reached, buffer cleared\n"); */
- MEM_freeN(text->undo_buf);
- init_undo_text(text);
- return false;
- }
- else {
- void *tmp = text->undo_buf;
- text->undo_buf = MEM_callocN(text->undo_len * 2, "undo buf");
- memcpy(text->undo_buf, tmp, text->undo_len);
- text->undo_len *= 2;
- MEM_freeN(tmp);
- }
- }
+ /* Normally over-allocating is preferred,
+ * however in this case the buffer is small enough and re-allocation
+ * fast enough for each undo step that it's not a problem to allocate each time.
+ * This also saves on some memory when we have many text buffers
+ * that would have an empty undo memory allocated.
+ */
+ /* Add one for the null terminator. */
+ utxt->len = utxt->pos + x + 1;
+ if (utxt->len > TXT_MAX_UNDO) {
+ /* XXX error("Undo limit reached, buffer cleared\n"); */
+ MEM_freeN(utxt->buf);
+ return false;
+ }
+ else {
+ /* Small reallocations on each undo step is fine. */
+ utxt->buf = MEM_recallocN(utxt->buf, utxt->len);
+ }
return true;
}
+static void txt_undo_end(Text *UNUSED(text), TextUndoBuf *utxt)
+{
+ int undo_pos_end = utxt->pos + 1;
+ BLI_assert(undo_pos_end + 1 == utxt->len);
+ utxt->buf[undo_pos_end] = '\0';
+}
+
+/* Call once undo is done. */
+#ifndef NDEBUG
+
+#endif
+
#if 0 /* UNUSED */
-static void dump_buffer(Text *text)
+static void dump_buffer(TextUndoBuf *utxt)
{
int i = 0;
-
- while (i++ < text->undo_pos) printf("%d: %d %c\n", i, text->undo_buf[i], text->undo_buf[i]);
+
+ while (i++ < utxt->undo_pos) printf("%d: %d %c\n", i, utxt->buf[i], utxt->buf[i]);
}
/* Note: this function is outdated and must be updated if needed for future use */
@@ -1461,10 +1504,10 @@ void txt_print_undo(Text *text)
printf("---< Undo Buffer >---\n");
- printf("UndoPosition is %d\n", text->undo_pos);
+ printf("UndoPosition is %d\n", utxt->pos);
- while (i <= text->undo_pos) {
- op = text->undo_buf[i];
+ while (i <= utxt->pos) {
+ op = utxt->buf[i];
if (op == UNDO_INSERT_1) {
ops = "Insert ascii ";
@@ -1530,15 +1573,15 @@ void txt_print_undo(Text *text)
printf(" - Char is ");
switch (op) {
case UNDO_INSERT_1: case UNDO_BS_1: case UNDO_DEL_1:
- printf("%c", text->undo_buf[i]);
+ printf("%c", utxt->buf[i]);
i++;
break;
case UNDO_INSERT_2: case UNDO_BS_2: case UNDO_DEL_2:
- printf("%c%c", text->undo_buf[i], text->undo_buf[i + 1]);
+ printf("%c%c", utxt->buf[i], utxt->buf[i + 1]);
i += 2;
break;
case UNDO_INSERT_3: case UNDO_BS_3: case UNDO_DEL_3:
- printf("%c%c%c", text->undo_buf[i], text->undo_buf[i + 1], text->undo_buf[i + 2]);
+ printf("%c%c%c", utxt->buf[i], utxt->buf[i + 1], utxt->buf[i + 2]);
i += 3;
break;
case UNDO_INSERT_4: case UNDO_BS_4: case UNDO_DEL_4:
@@ -1546,10 +1589,10 @@ void txt_print_undo(Text *text)
unsigned int uc;
char c[BLI_UTF8_MAX + 1];
size_t c_len;
- uc = text->undo_buf[i]; i++;
- uc = uc + (text->undo_buf[i] << 8); i++;
- uc = uc + (text->undo_buf[i] << 16); i++;
- uc = uc + (text->undo_buf[i] << 24); i++;
+ uc = utxt->buf[i]; i++;
+ uc = uc + (utxt->buf[i] << 8); i++;
+ uc = uc + (utxt->buf[i] << 16); i++;
+ uc = uc + (utxt->buf[i] << 24); i++;
c_len = BLI_str_utf8_from_unicode(uc, c);
c[c_len] = '\0';
puts(c);
@@ -1560,44 +1603,44 @@ void txt_print_undo(Text *text)
else if (op == UNDO_DBLOCK || op == UNDO_IBLOCK) {
i++;
- linep = text->undo_buf[i]; i++;
- linep = linep + (text->undo_buf[i] << 8); i++;
- linep = linep + (text->undo_buf[i] << 16); i++;
- linep = linep + (text->undo_buf[i] << 24); i++;
+ linep = utxt->buf[i]; i++;
+ linep = linep + (utxt->buf[i] << 8); i++;
+ linep = linep + (utxt->buf[i] << 16); i++;
+ linep = linep + (utxt->buf[i] << 24); i++;
printf(" (length %d) <", linep);
while (linep > 0) {
- putchar(text->undo_buf[i]);
+ putchar(utxt->buf[i]);
linep--; i++;
}
- linep = text->undo_buf[i]; i++;
- linep = linep + (text->undo_buf[i] << 8); i++;
- linep = linep + (text->undo_buf[i] << 16); i++;
- linep = linep + (text->undo_buf[i] << 24); i++;
+ linep = utxt->buf[i]; i++;
+ linep = linep + (utxt->buf[i] << 8); i++;
+ linep = linep + (utxt->buf[i] << 16); i++;
+ linep = linep + (utxt->buf[i] << 24); i++;
printf("> (%d)", linep);
}
else if (op == UNDO_INDENT || op == UNDO_UNINDENT) {
i++;
- charp = text->undo_buf[i]; i++;
- charp = charp + (text->undo_buf[i] << 8); i++;
+ charp = utxt->buf[i]; i++;
+ charp = charp + (utxt->buf[i] << 8); i++;
- linep = text->undo_buf[i]; i++;
- linep = linep + (text->undo_buf[i] << 8); i++;
- linep = linep + (text->undo_buf[i] << 16); i++;
- linep = linep + (text->undo_buf[i] << 24); i++;
+ linep = utxt->buf[i]; i++;
+ linep = linep + (utxt->buf[i] << 8); i++;
+ linep = linep + (utxt->buf[i] << 16); i++;
+ linep = linep + (utxt->buf[i] << 24); i++;
printf("to <%d, %d> ", linep, charp);
- charp = text->undo_buf[i]; i++;
- charp = charp + (text->undo_buf[i] << 8); i++;
+ charp = utxt->buf[i]; i++;
+ charp = charp + (utxt->buf[i] << 8); i++;
- linep = text->undo_buf[i]; i++;
- linep = linep + (text->undo_buf[i] << 8); i++;
- linep = linep + (text->undo_buf[i] << 16); i++;
- linep = linep + (text->undo_buf[i] << 24); i++;
+ linep = utxt->buf[i]; i++;
+ linep = linep + (utxt->buf[i] << 8); i++;
+ linep = linep + (utxt->buf[i] << 16); i++;
+ linep = linep + (utxt->buf[i] << 24); i++;
printf("from <%d, %d>", linep, charp);
}
@@ -1628,104 +1671,114 @@ static void txt_undo_store_uint32(char *undo_buf, int *undo_pos, unsigned int va
(*undo_pos)++;
}
-/* store the cur cursor to the undo buffer */
-static void txt_undo_store_cur(Text *text)
+/* store the cur cursor to the undo buffer (6 bytes)*/
+static void txt_undo_store_cur(Text *text, TextUndoBuf *utxt)
{
- txt_undo_store_uint16(text->undo_buf, &text->undo_pos, text->curc);
- txt_undo_store_uint32(text->undo_buf, &text->undo_pos, txt_get_span(text->lines.first, text->curl));
+ txt_undo_store_uint16(utxt->buf, &utxt->pos, text->curc);
+ txt_undo_store_uint32(utxt->buf, &utxt->pos, txt_get_span(text->lines.first, text->curl));
}
-/* store the sel cursor to the undo buffer */
-static void txt_undo_store_sel(Text *text)
+/* store the sel cursor to the undo buffer (6 bytes) */
+static void txt_undo_store_sel(Text *text, TextUndoBuf *utxt)
{
- txt_undo_store_uint16(text->undo_buf, &text->undo_pos, text->selc);
- txt_undo_store_uint32(text->undo_buf, &text->undo_pos, txt_get_span(text->lines.first, text->sell));
+ txt_undo_store_uint16(utxt->buf, &utxt->pos, text->selc);
+ txt_undo_store_uint32(utxt->buf, &utxt->pos, txt_get_span(text->lines.first, text->sell));
}
-/* store both cursors to the undo buffer */
-static void txt_undo_store_cursors(Text *text)
+/* store both cursors to the undo buffer (12 bytes) */
+static void txt_undo_store_cursors(Text *text, TextUndoBuf *utxt)
{
- txt_undo_store_cur(text);
- txt_undo_store_sel(text);
+ txt_undo_store_cur(text, utxt);
+ txt_undo_store_sel(text, utxt);
}
/* store an operator along with a block of data */
-static void txt_undo_add_blockop(Text *text, int op, const char *buf)
+static void txt_undo_add_blockop(Text *text, TextUndoBuf *utxt, int op, const char *buf)
{
unsigned int length = strlen(buf);
-
- if (!max_undo_test(text, length + 11 + 12))
- return;
-
- text->undo_pos++;
- text->undo_buf[text->undo_pos] = op;
- text->undo_pos++;
-
- txt_undo_store_cursors(text);
-
- txt_undo_store_uint32(text->undo_buf, &text->undo_pos, length);
-
- strncpy(text->undo_buf + text->undo_pos, buf, length);
- text->undo_pos += length;
- txt_undo_store_uint32(text->undo_buf, &text->undo_pos, length);
- text->undo_buf[text->undo_pos] = op;
-
- text->undo_buf[text->undo_pos + 1] = 0;
+ if (!max_undo_test(utxt, 2 + 12 + 4 + length + 4 + 1)) {
+ return;
+ }
+ /* 2 bytes */
+ utxt->pos++;
+ utxt->buf[utxt->pos] = op;
+ utxt->pos++;
+ /* 12 bytes */
+ txt_undo_store_cursors(text, utxt);
+ /* 4 bytes */
+ txt_undo_store_uint32(utxt->buf, &utxt->pos, length);
+ /* 'length' bytes */
+ strncpy(utxt->buf + utxt->pos, buf, length);
+ utxt->pos += length;
+ /* 4 bytes */
+ txt_undo_store_uint32(utxt->buf, &utxt->pos, length);
+ /* 1 byte */
+ utxt->buf[utxt->pos] = op;
+
+ txt_undo_end(text, utxt);
}
/* store a regular operator */
-void txt_undo_add_op(Text *text, int op)
+void txt_undo_add_op(Text *text, TextUndoBuf *utxt, int op)
{
- if (!max_undo_test(text, 15))
+ if (!max_undo_test(utxt, 2 + 12 + 1)) {
return;
+ }
- text->undo_pos++;
- text->undo_buf[text->undo_pos] = op;
+ /* 2 bytes */
+ utxt->pos++;
+ utxt->buf[utxt->pos] = op;
+ utxt->pos++;
+ /* 12 bytes */
+ txt_undo_store_cursors(text, utxt);
+ /* 1 byte */
+ utxt->buf[utxt->pos] = op;
- text->undo_pos++;
-
- txt_undo_store_cursors(text);
-
- text->undo_buf[text->undo_pos] = op;
- text->undo_buf[text->undo_pos + 1] = 0;
+ txt_undo_end(text, utxt);
}
/* store an operator for a single character */
-static void txt_undo_add_charop(Text *text, int op_start, unsigned int c)
+static void txt_undo_add_charop(Text *text, TextUndoBuf *utxt, int op_start, unsigned int c)
{
char utf8[BLI_UTF8_MAX];
size_t i, utf8_size = BLI_str_utf8_from_unicode(c, utf8);
- if (!max_undo_test(text, 3 + utf8_size + 12))
- return;
-
- text->undo_pos++;
-
- if (utf8_size < 4) {
- text->undo_buf[text->undo_pos] = op_start + utf8_size - 1;
- text->undo_pos++;
-
- txt_undo_store_cur(text);
-
+ if (utf8_size < 4 && 0) {
+ if (!max_undo_test(utxt, 2 + 6 + utf8_size + 1)) {
+ return;
+ }
+ /* 2 bytes */
+ utxt->pos++;
+ utxt->buf[utxt->pos] = op_start + utf8_size - 1;
+ utxt->pos++;
+ /* 6 bytes */
+ txt_undo_store_cur(text, utxt);
+ /* 'utf8_size' bytes */
for (i = 0; i < utf8_size; i++) {
- text->undo_buf[text->undo_pos] = utf8[i];
- text->undo_pos++;
+ utxt->buf[utxt->pos] = utf8[i];
+ utxt->pos++;
}
-
- text->undo_buf[text->undo_pos] = op_start + utf8_size - 1;
+ /* 1 byte */
+ utxt->buf[utxt->pos] = op_start + utf8_size - 1;
}
else {
- text->undo_buf[text->undo_pos] = op_start + 3;
- text->undo_pos++;
-
- txt_undo_store_cursors(text);
-
- txt_undo_store_uint32(text->undo_buf, &text->undo_pos, c);
- text->undo_buf[text->undo_pos] = op_start + 3;
+ if (!max_undo_test(utxt, 2 + 6 + 4 + 1)) {
+ return;
+ }
+ /* 2 bytes */
+ utxt->pos++;
+ utxt->buf[utxt->pos] = op_start + 3;
+ utxt->pos++;
+ /* 6 bytes */
+ txt_undo_store_cur(text, utxt);
+ /* 4 bytes */
+ txt_undo_store_uint32(utxt->buf, &utxt->pos, c);
+ /* 1 byte */
+ utxt->buf[utxt->pos] = op_start + 3;
}
- text->undo_buf[text->undo_pos + 1] = 0;
+ txt_undo_end(text, utxt);
}
/* extends Link */
@@ -1739,7 +1792,7 @@ struct LinkInt {
* of the lines that should not be indented back.
*/
static void txt_undo_add_unprefix_op(
- Text *text, char undo_op,
+ Text *text, TextUndoBuf *utxt, char undo_op,
const ListBase *line_index_mask, const int line_index_mask_len)
{
struct LinkInt *idata;
@@ -1747,30 +1800,35 @@ static void txt_undo_add_unprefix_op(
BLI_assert(BLI_listbase_count(line_index_mask) == line_index_mask_len);
/* OP byte + UInt32 count + counted UInt32 line numbers + UInt32 count + 12-bytes selection + OP byte */
- if (!max_undo_test(text, 1 + 4 + (line_index_mask_len * 4) + 4 + 12 + 1)) {
+ if (!max_undo_test(utxt, 2 + 4 + (line_index_mask_len * 4) + 4 + 12 + 1)) {
return;
}
- /* Opening buffer sequence with OP */
- text->undo_pos++;
- text->undo_buf[text->undo_pos] = undo_op;
- text->undo_pos++;
- /* Adding number of line numbers to read */
- txt_undo_store_uint32(text->undo_buf, &text->undo_pos, line_index_mask_len);
+ /* 2 bytes */
+ utxt->pos++;
+ utxt->buf[utxt->pos] = undo_op;
+ utxt->pos++;
+ /* Adding number of line numbers to read
+ * 4 bytes */
+ txt_undo_store_uint32(utxt->buf, &utxt->pos, line_index_mask_len);
- /* Adding linenumbers of lines that shall not be indented if undoing */
+ /* Adding linenumbers of lines that shall not be indented if undoing.
+ * 'line_index_mask_len * 4' bytes */
for (idata = line_index_mask->first; idata; idata = idata->next) {
- txt_undo_store_uint32(text->undo_buf, &text->undo_pos, idata->value);
- }
-
- /* Adding number of line numbers to read again */
- txt_undo_store_uint32(text->undo_buf, &text->undo_pos, line_index_mask_len);
- /* Adding current selection */
- txt_undo_store_cursors(text);
- /* Closing with OP (same as above) */
- text->undo_buf[text->undo_pos] = undo_op;
+ txt_undo_store_uint32(utxt->buf, &utxt->pos, idata->value);
+ }
+
+ /* Adding number of line numbers to read again.
+ * 4 bytes */
+ txt_undo_store_uint32(utxt->buf, &utxt->pos, line_index_mask_len);
+ /* Adding current selection.
+ * 12 bytes */
+ txt_undo_store_cursors(text, utxt);
+ /* Closing with OP (same as above).
+ * 1 byte */
+ utxt->buf[utxt->pos] = undo_op;
/* Marking as last undo operation */
- text->undo_buf[text->undo_pos + 1] = 0;
+ txt_undo_end(text, utxt);
}
static unsigned short txt_undo_read_uint16(const char *undo_buf, int *undo_pos)
@@ -1913,7 +1971,7 @@ static unsigned int txt_redo_read_unicode(const char *undo_buf, int *undo_pos, s
unicode = BLI_str_utf8_as_unicode(utf8);
break;
case 4: /* 32-bit unicode symbol */
- unicode = txt_undo_read_uint32(undo_buf, undo_pos);
+ unicode = txt_redo_read_uint32(undo_buf, undo_pos);
break;
default:
/* should never happen */
@@ -1925,9 +1983,9 @@ static unsigned int txt_redo_read_unicode(const char *undo_buf, int *undo_pos, s
return unicode;
}
-void txt_do_undo(Text *text)
+void txt_do_undo(Text *text, TextUndoBuf *utxt)
{
- int op = text->undo_buf[text->undo_pos];
+ int op = utxt->buf[utxt->pos];
int prev_flags;
unsigned int linep;
unsigned int uni_char;
@@ -1936,11 +1994,11 @@ void txt_do_undo(Text *text)
unsigned short charp;
char *buf;
- if (text->undo_pos < 0) {
+ if (utxt->pos < 0) {
return;
}
- text->undo_pos--;
+ utxt->pos--;
undoing = 1;
@@ -1949,16 +2007,16 @@ void txt_do_undo(Text *text)
case UNDO_INSERT_2:
case UNDO_INSERT_3:
case UNDO_INSERT_4:
- text->undo_pos -= op - UNDO_INSERT_1 + 1;
+ utxt->pos -= op - UNDO_INSERT_1 + 1;
/* get and restore the cursors */
- txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc);
+ txt_undo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, curln, curc, 1);
- txt_delete_char(text);
+ txt_delete_char(text, utxt);
- text->undo_pos--;
+ utxt->pos--;
break;
case UNDO_BS_1:
@@ -1966,16 +2024,16 @@ void txt_do_undo(Text *text)
case UNDO_BS_3:
case UNDO_BS_4:
charp = op - UNDO_BS_1 + 1;
- uni_char = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp);
+ uni_char = txt_undo_read_unicode(utxt->buf, &utxt->pos, charp);
/* get and restore the cursors */
- txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc);
+ txt_undo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, curln, curc, 1);
- txt_add_char(text, uni_char);
+ txt_add_char(text, utxt, uni_char);
- text->undo_pos--;
+ utxt->pos--;
break;
case UNDO_DEL_1:
@@ -1983,50 +2041,50 @@ void txt_do_undo(Text *text)
case UNDO_DEL_3:
case UNDO_DEL_4:
charp = op - UNDO_DEL_1 + 1;
- uni_char = txt_undo_read_unicode(text->undo_buf, &text->undo_pos, charp);
+ uni_char = txt_undo_read_unicode(utxt->buf, &utxt->pos, charp);
/* get and restore the cursors */
- txt_undo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc);
+ txt_undo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, curln, curc, 1);
- txt_add_char(text, uni_char);
+ txt_add_char(text, utxt, uni_char);
txt_move_left(text, 0);
- text->undo_pos--;
+ utxt->pos--;
break;
case UNDO_DBLOCK:
{
int i;
/* length of the string in the buffer */
- linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
+ linep = txt_undo_read_uint32(utxt->buf, &utxt->pos);
buf = MEM_mallocN(linep + 1, "dblock buffer");
for (i = 0; i < linep; i++) {
- buf[(linep - 1) - i] = text->undo_buf[text->undo_pos];
- text->undo_pos--;
+ buf[(linep - 1) - i] = utxt->buf[utxt->pos];
+ utxt->pos--;
}
buf[i] = 0;
/* skip over the length that was stored again */
- text->undo_pos -= 4;
+ utxt->pos -= 4;
/* Get the cursor positions */
- txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
+ txt_undo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
/* move cur to location that needs buff inserted */
txt_move_to(text, curln, curc, 0);
- txt_insert_buf(text, buf);
+ txt_insert_buf(text, utxt, buf);
MEM_freeN(buf);
/* restore the cursors */
txt_move_to(text, curln, curc, 0);
txt_move_to(text, selln, selc, 1);
- text->undo_pos--;
+ utxt->pos--;
break;
}
@@ -2034,23 +2092,23 @@ void txt_do_undo(Text *text)
{
int i;
/* length of the string in the buffer */
- linep = txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
+ linep = txt_undo_read_uint32(utxt->buf, &utxt->pos);
/* txt_backspace_char removes utf8-characters, not bytes */
buf = MEM_mallocN(linep + 1, "iblock buffer");
for (i = 0; i < linep; i++) {
- buf[(linep - 1) - i] = text->undo_buf[text->undo_pos];
- text->undo_pos--;
+ buf[(linep - 1) - i] = utxt->buf[utxt->pos];
+ utxt->pos--;
}
buf[i] = 0;
linep = BLI_strlen_utf8(buf);
MEM_freeN(buf);
/* skip over the length that was stored again */
- text->undo_pos -= 4;
+ utxt->pos -= 4;
/* get and restore the cursors */
- txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
+ txt_undo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, selln, selc, 1);
@@ -2066,9 +2124,9 @@ void txt_do_undo(Text *text)
text->flags = prev_flags;
}
- txt_delete_selected(text);
+ txt_delete_selected(text, utxt);
- text->undo_pos--;
+ utxt->pos--;
break;
}
case UNDO_INDENT:
@@ -2077,37 +2135,37 @@ void txt_do_undo(Text *text)
case UNDO_MOVE_LINES_UP:
case UNDO_MOVE_LINES_DOWN:
/* get and restore the cursors */
- txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
+ txt_undo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, selln, selc, 1);
if (op == UNDO_INDENT) {
- txt_unindent(text);
+ txt_unindent(text, utxt);
}
else if (op == UNDO_COMMENT) {
- txt_uncomment(text);
+ txt_uncomment(text, utxt);
}
else if (op == UNDO_DUPLICATE) {
txt_delete_line(text, text->curl->next);
}
else if (op == UNDO_MOVE_LINES_UP) {
- txt_move_lines(text, TXT_MOVE_LINE_DOWN);
+ txt_move_lines(text, utxt, TXT_MOVE_LINE_DOWN);
}
else if (op == UNDO_MOVE_LINES_DOWN) {
- txt_move_lines(text, TXT_MOVE_LINE_UP);
+ txt_move_lines(text, utxt, TXT_MOVE_LINE_UP);
}
- text->undo_pos--;
+ utxt->pos--;
break;
case UNDO_UNINDENT:
case UNDO_UNCOMMENT:
{
- void (*txt_prefix_fn)(Text *);
- void (*txt_unprefix_fn)(Text *);
+ void (*txt_prefix_fn)(Text *, TextUndoBuf *);
+ void (*txt_unprefix_fn)(Text *, TextUndoBuf *);
int count;
int i;
/* Get and restore the cursors */
- txt_undo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
+ txt_undo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, selln, selc, 1);
@@ -2121,30 +2179,30 @@ void txt_do_undo(Text *text)
txt_unprefix_fn = txt_uncomment;
}
- txt_prefix_fn(text);
+ txt_prefix_fn(text, utxt);
/* Get the count */
- count = txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
+ count = txt_undo_read_uint32(utxt->buf, &utxt->pos);
/* Iterate! */
txt_pop_sel(text);
for (i = 0; i < count; i++) {
- txt_move_to(text, txt_undo_read_uint32(text->undo_buf, &text->undo_pos), 0, 0);
+ txt_move_to(text, txt_undo_read_uint32(utxt->buf, &utxt->pos), 0, 0);
/* Un-un-unindent/comment */
- txt_unprefix_fn(text);
+ txt_unprefix_fn(text, utxt);
}
/* Restore selection */
txt_move_to(text, curln, curc, 0);
txt_move_to(text, selln, selc, 1);
/* Jumo over count */
- txt_undo_read_uint32(text->undo_buf, &text->undo_pos);
+ txt_undo_read_uint32(utxt->buf, &utxt->pos);
/* Jump over closing OP byte */
- text->undo_pos--;
+ utxt->pos--;
break;
}
default:
//XXX error("Undo buffer error - resetting");
- text->undo_pos = -1;
+ utxt->pos = -1;
break;
}
@@ -2152,7 +2210,7 @@ void txt_do_undo(Text *text)
undoing = 0;
}
-void txt_do_redo(Text *text)
+void txt_do_redo(Text *text, TextUndoBuf *utxt)
{
char op;
char *buf;
@@ -2162,11 +2220,11 @@ void txt_do_redo(Text *text)
unsigned int curln, selln;
unsigned short curc, selc;
- text->undo_pos++;
- op = text->undo_buf[text->undo_pos];
+ utxt->pos++;
+ op = utxt->buf[utxt->pos];
if (!op) {
- text->undo_pos--;
+ utxt->pos--;
return;
}
@@ -2177,35 +2235,35 @@ void txt_do_redo(Text *text)
case UNDO_INSERT_2:
case UNDO_INSERT_3:
case UNDO_INSERT_4:
- text->undo_pos++;
+ utxt->pos++;
/* get and restore the cursors */
- txt_redo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc);
+ txt_redo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, curln, curc, 1);
charp = op - UNDO_INSERT_1 + 1;
- uni_uchar = txt_redo_read_unicode(text->undo_buf, &text->undo_pos, charp);
+ uni_uchar = txt_redo_read_unicode(utxt->buf, &utxt->pos, charp);
- txt_add_char(text, uni_uchar);
+ txt_add_char(text, utxt, uni_uchar);
break;
case UNDO_BS_1:
case UNDO_BS_2:
case UNDO_BS_3:
case UNDO_BS_4:
- text->undo_pos++;
+ utxt->pos++;
/* get and restore the cursors */
- txt_redo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc);
+ txt_redo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, curln, curc, 1);
- text->undo_pos += op - UNDO_BS_1 + 1;
+ utxt->pos += op - UNDO_BS_1 + 1;
/* move right so we backspace the correct char */
txt_move_right(text, 0);
- txt_backspace_char(text);
+ txt_backspace_char(text, utxt);
break;
@@ -2213,60 +2271,60 @@ void txt_do_redo(Text *text)
case UNDO_DEL_2:
case UNDO_DEL_3:
case UNDO_DEL_4:
- text->undo_pos++;
+ utxt->pos++;
/* get and restore the cursors */
- txt_redo_read_cur(text->undo_buf, &text->undo_pos, &curln, &curc);
+ txt_redo_read_cur(utxt->buf, &utxt->pos, &curln, &curc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, curln, curc, 1);
- text->undo_pos += op - UNDO_DEL_1 + 1;
+ utxt->pos += op - UNDO_DEL_1 + 1;
- txt_delete_char(text);
+ txt_delete_char(text, utxt);
break;
case UNDO_DBLOCK:
- text->undo_pos++;
+ utxt->pos++;
/* get and restore the cursors */
- txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
+ txt_redo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, selln, selc, 1);
/* length of the block */
- linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
+ linep = txt_redo_read_uint32(utxt->buf, &utxt->pos);
- text->undo_pos += linep;
+ utxt->pos += linep;
/* skip over the length that was stored again */
- text->undo_pos += 4;
+ utxt->pos += 4;
- txt_delete_sel(text);
+ txt_delete_sel(text, utxt);
break;
case UNDO_IBLOCK:
- text->undo_pos++;
+ utxt->pos++;
/* get and restore the cursors */
- txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
+ txt_redo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, curln, curc, 1);
/* length of the block */
- linep = txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
+ linep = txt_redo_read_uint32(utxt->buf, &utxt->pos);
buf = MEM_mallocN(linep + 1, "iblock buffer");
- memcpy(buf, &text->undo_buf[text->undo_pos], linep);
- text->undo_pos += linep;
+ memcpy(buf, &utxt->buf[utxt->pos], linep);
+ utxt->pos += linep;
buf[linep] = 0;
- txt_insert_buf(text, buf);
+ txt_insert_buf(text, utxt, buf);
MEM_freeN(buf);
/* skip over the length that was stored again */
- text->undo_pos += 4;
+ utxt->pos += 4;
break;
@@ -2276,38 +2334,38 @@ void txt_do_redo(Text *text)
case UNDO_DUPLICATE:
case UNDO_MOVE_LINES_UP:
case UNDO_MOVE_LINES_DOWN:
- text->undo_pos++;
+ utxt->pos++;
/* get and restore the cursors */
- txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
+ txt_redo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, selln, selc, 1);
if (op == UNDO_INDENT) {
- txt_indent(text);
+ txt_indent(text, utxt);
}
else if (op == UNDO_COMMENT) {
- txt_comment(text);
+ txt_comment(text, utxt);
}
else if (op == UNDO_UNCOMMENT) {
- txt_uncomment(text);
+ txt_uncomment(text, utxt);
}
else if (op == UNDO_DUPLICATE) {
- txt_duplicate_line(text);
+ txt_duplicate_line(text, utxt);
}
else if (op == UNDO_MOVE_LINES_UP) {
/* offset the cursor by + 1 */
txt_move_to(text, curln + 1, curc, 0);
txt_move_to(text, selln + 1, selc, 1);
- txt_move_lines(text, TXT_MOVE_LINE_UP);
+ txt_move_lines(text, utxt, TXT_MOVE_LINE_UP);
}
else if (op == UNDO_MOVE_LINES_DOWN) {
/* offset the cursor by - 1 */
txt_move_to(text, curln - 1, curc, 0);
txt_move_to(text, selln - 1, selc, 1);
- txt_move_lines(text, TXT_MOVE_LINE_DOWN);
+ txt_move_lines(text, utxt, TXT_MOVE_LINE_DOWN);
}
/* re-restore the cursors since they got moved when redoing */
@@ -2320,24 +2378,24 @@ void txt_do_redo(Text *text)
int count;
int i;
- text->undo_pos++;
+ utxt->pos++;
/* Scan all the stuff described in txt_undo_add_unindent_op */
- count = txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
+ count = txt_redo_read_uint32(utxt->buf, &utxt->pos);
for (i = 0; i < count; i++) {
- txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
+ txt_redo_read_uint32(utxt->buf, &utxt->pos);
}
/* Count again */
- txt_redo_read_uint32(text->undo_buf, &text->undo_pos);
+ txt_redo_read_uint32(utxt->buf, &utxt->pos);
/* Get the selection and re-unindent */
- txt_redo_read_cursors(text->undo_buf, &text->undo_pos, &curln, &curc, &selln, &selc);
+ txt_redo_read_cursors(utxt->buf, &utxt->pos, &curln, &curc, &selln, &selc);
txt_move_to(text, curln, curc, 0);
txt_move_to(text, selln, selc, 1);
- txt_unindent(text);
+ txt_unindent(text, utxt);
break;
}
default:
//XXX error("Undo buffer error - resetting");
- text->undo_pos = -1;
+ utxt->pos = -1;
break;
}
@@ -2349,16 +2407,16 @@ void txt_do_redo(Text *text)
/* Line editing functions */
/**************************/
-void txt_split_curline(Text *text)
+void txt_split_curline(Text *text, TextUndoBuf *utxt)
{
TextLine *ins;
char *left, *right;
if (!text->curl) return;
- txt_delete_sel(text);
+ txt_delete_sel(text, utxt);
- if (!undoing) txt_undo_add_charop(text, UNDO_INSERT_1, '\n');
+ if (!undoing) txt_undo_add_charop(text, utxt, UNDO_INSERT_1, '\n');
/* Make the two half strings */
@@ -2430,7 +2488,7 @@ static void txt_combine_lines(Text *text, TextLine *linea, TextLine *lineb)
txt_clean_text(text);
}
-void txt_duplicate_line(Text *text)
+void txt_duplicate_line(Text *text, TextUndoBuf *utxt)
{
TextLine *textline;
@@ -2443,18 +2501,18 @@ void txt_duplicate_line(Text *text)
txt_make_dirty(text);
txt_clean_text(text);
- if (!undoing) txt_undo_add_op(text, UNDO_DUPLICATE);
+ if (!undoing) txt_undo_add_op(text, utxt, UNDO_DUPLICATE);
}
}
-void txt_delete_char(Text *text)
+void txt_delete_char(Text *text, TextUndoBuf *utxt)
{
unsigned int c = '\n';
if (!text->curl) return;
if (txt_has_sel(text)) { /* deleting a selection */
- txt_delete_sel(text);
+ txt_delete_sel(text, utxt);
txt_make_dirty(text);
return;
}
@@ -2480,24 +2538,24 @@ void txt_delete_char(Text *text)
txt_make_dirty(text);
txt_clean_text(text);
- if (!undoing) txt_undo_add_charop(text, UNDO_DEL_1, c);
+ if (!undoing) txt_undo_add_charop(text, utxt, UNDO_DEL_1, c);
}
-void txt_delete_word(Text *text)
+void txt_delete_word(Text *text, TextUndoBuf *utxt)
{
txt_jump_right(text, true, true);
- txt_delete_sel(text);
+ txt_delete_sel(text, utxt);
txt_make_dirty(text);
}
-void txt_backspace_char(Text *text)
+void txt_backspace_char(Text *text, TextUndoBuf *utxt)
{
unsigned int c = '\n';
if (!text->curl) return;
if (txt_has_sel(text)) { /* deleting a selection */
- txt_delete_sel(text);
+ txt_delete_sel(text, utxt);
txt_make_dirty(text);
return;
}
@@ -2529,13 +2587,13 @@ void txt_backspace_char(Text *text)
txt_make_dirty(text);
txt_clean_text(text);
- if (!undoing) txt_undo_add_charop(text, UNDO_BS_1, c);
+ if (!undoing) txt_undo_add_charop(text, utxt, UNDO_BS_1, c);
}
-void txt_backspace_word(Text *text)
+void txt_backspace_word(Text *text, TextUndoBuf *utxt)
{
txt_jump_left(text, true, true);
- txt_delete_sel(text);
+ txt_delete_sel(text, utxt);
txt_make_dirty(text);
}
@@ -2544,17 +2602,17 @@ void txt_backspace_word(Text *text)
* Remember to change this string according to max tab size */
static char tab_to_spaces[] = " ";
-static void txt_convert_tab_to_spaces(Text *text)
+static void txt_convert_tab_to_spaces(Text *text, TextUndoBuf *utxt)
{
/* sb aims to pad adjust the tab-width needed so that the right number of spaces
* is added so that the indention of the line is the right width (i.e. aligned
* to multiples of TXT_TABSIZE)
*/
const char *sb = &tab_to_spaces[text->curc % TXT_TABSIZE];
- txt_insert_buf(text, sb);
+ txt_insert_buf(text, utxt, sb);
}
-static bool txt_add_char_intern(Text *text, unsigned int add, bool replace_tabs)
+static bool txt_add_char_intern(Text *text, TextUndoBuf *utxt, unsigned int add, bool replace_tabs)
{
char *tmp, ch[BLI_UTF8_MAX];
size_t add_len;
@@ -2562,19 +2620,19 @@ static bool txt_add_char_intern(Text *text, unsigned int add, bool replace_tabs)
if (!text->curl) return 0;
if (add == '\n') {
- txt_split_curline(text);
+ txt_split_curline(text, utxt);
return true;
}
/* insert spaces rather than tabs */
if (add == '\t' && replace_tabs) {
- txt_convert_tab_to_spaces(text);
+ txt_convert_tab_to_spaces(text, utxt);
return true;
}
- txt_delete_sel(text);
+ txt_delete_sel(text, utxt);
- if (!undoing) txt_undo_add_charop(text, UNDO_INSERT_1, add);
+ if (!undoing) txt_undo_add_charop(text, utxt, UNDO_INSERT_1, add);
add_len = BLI_str_utf8_from_unicode(add, ch);
@@ -2596,23 +2654,23 @@ static bool txt_add_char_intern(Text *text, unsigned int add, bool replace_tabs)
return 1;
}
-bool txt_add_char(Text *text, unsigned int add)
+bool txt_add_char(Text *text, TextUndoBuf *utxt, unsigned int add)
{
- return txt_add_char_intern(text, add, (text->flags & TXT_TABSTOSPACES) != 0);
+ return txt_add_char_intern(text, utxt, add, (text->flags & TXT_TABSTOSPACES) != 0);
}
-bool txt_add_raw_char(Text *text, unsigned int add)
+bool txt_add_raw_char(Text *text, TextUndoBuf *utxt, unsigned int add)
{
- return txt_add_char_intern(text, add, 0);
+ return txt_add_char_intern(text, utxt, add, 0);
}
-void txt_delete_selected(Text *text)
+void txt_delete_selected(Text *text, TextUndoBuf *utxt)
{
- txt_delete_sel(text);
+ txt_delete_sel(text, utxt);
txt_make_dirty(text);
}
-bool txt_replace_char(Text *text, unsigned int add)
+bool txt_replace_char(Text *text, TextUndoBuf *utxt, unsigned int add)
{
unsigned int del;
size_t del_size = 0, add_size;
@@ -2622,7 +2680,7 @@ bool txt_replace_char(Text *text, unsigned int add)
/* If text is selected or we're at the end of the line just use txt_add_char */
if (text->curc == text->curl->len || txt_has_sel(text) || add == '\n') {
- return txt_add_char(text, add);
+ return txt_add_char(text, utxt, add);
}
del = BLI_str_utf8_as_unicode_and_size(text->curl->line + text->curc, &del_size);
@@ -2650,10 +2708,10 @@ bool txt_replace_char(Text *text, unsigned int add)
/* Should probably create a new op for this */
if (!undoing) {
- txt_undo_add_charop(text, UNDO_INSERT_1, add);
+ txt_undo_add_charop(text, utxt, UNDO_INSERT_1, add);
text->curc -= add_size;
txt_pop_sel(text);
- txt_undo_add_charop(text, UNDO_DEL_1, del);
+ txt_undo_add_charop(text, utxt, UNDO_DEL_1, del);
text->curc += add_size;
txt_pop_sel(text);
}
@@ -2793,7 +2851,7 @@ static void txt_select_unprefix(
/* caller must handle undo */
}
-void txt_comment(Text *text)
+void txt_comment(Text *text, TextUndoBuf *utxt)
{
const char *prefix = "#";
@@ -2804,11 +2862,11 @@ void txt_comment(Text *text)
txt_select_prefix(text, prefix);
if (!undoing) {
- txt_undo_add_op(text, UNDO_COMMENT);
+ txt_undo_add_op(text, utxt, UNDO_COMMENT);
}
}
-void txt_uncomment(Text *text)
+void txt_uncomment(Text *text, TextUndoBuf *utxt)
{
const char *prefix = "#";
ListBase line_index_mask;
@@ -2821,13 +2879,13 @@ void txt_uncomment(Text *text)
txt_select_unprefix(text, prefix, &line_index_mask, &line_index_mask_len);
if (!undoing) {
- txt_undo_add_unprefix_op(text, UNDO_UNCOMMENT, &line_index_mask, line_index_mask_len);
+ txt_undo_add_unprefix_op(text, utxt, UNDO_UNCOMMENT, &line_index_mask, line_index_mask_len);
}
BLI_freelistN(&line_index_mask);
}
-void txt_indent(Text *text)
+void txt_indent(Text *text, TextUndoBuf *utxt)
{
const char *prefix = (text->flags & TXT_TABSTOSPACES) ? tab_to_spaces : "\t";
@@ -2838,11 +2896,11 @@ void txt_indent(Text *text)
txt_select_prefix(text, prefix);
if (!undoing) {
- txt_undo_add_op(text, UNDO_INDENT);
+ txt_undo_add_op(text, utxt, UNDO_INDENT);
}
}
-void txt_unindent(Text *text)
+void txt_unindent(Text *text, TextUndoBuf *utxt)
{
const char *prefix = (text->flags & TXT_TABSTOSPACES) ? tab_to_spaces : "\t";
ListBase line_index_mask;
@@ -2855,13 +2913,13 @@ void txt_unindent(Text *text)
txt_select_unprefix(text, prefix, &line_index_mask, &line_index_mask_len);
if (!undoing) {
- txt_undo_add_unprefix_op(text, UNDO_UNINDENT, &line_index_mask, line_index_mask_len);
+ txt_undo_add_unprefix_op(text, utxt, UNDO_UNINDENT, &line_index_mask, line_index_mask_len);
}
BLI_freelistN(&line_index_mask);
}
-void txt_move_lines(struct Text *text, const int direction)
+void txt_move_lines(struct Text *text, TextUndoBuf *utxt, const int direction)
{
TextLine *line_other;
@@ -2888,7 +2946,7 @@ void txt_move_lines(struct Text *text, const int direction)
txt_clean_text(text);
if (!undoing) {
- txt_undo_add_op(text, (direction == TXT_MOVE_LINE_DOWN) ? UNDO_MOVE_LINES_DOWN : UNDO_MOVE_LINES_UP);
+ txt_undo_add_op(text, utxt, (direction == TXT_MOVE_LINE_DOWN) ? UNDO_MOVE_LINES_DOWN : UNDO_MOVE_LINES_UP);
}
}
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index fcedd880615..250408642bb 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -55,7 +55,6 @@
#include "IMB_imbuf.h"
-#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_colorband.h"
@@ -412,6 +411,7 @@ void BKE_texture_mtex_default(MTex *mtex)
mtex->kinkfac = 1.0f;
mtex->kinkampfac = 1.0f;
mtex->roughfac = 1.0f;
+ mtex->twistfac = 1.0f;
mtex->padensfac = 1.0f;
mtex->lifefac = 1.0f;
mtex->sizefac = 1.0f;
@@ -1206,17 +1206,17 @@ void BKE_texture_get_value(
BKE_texture_get_value_ex(scene, texture, tex_co, texres, NULL, use_color_management);
}
-static void texture_nodes_fetch_images_for_pool(bNodeTree *ntree, struct ImagePool *pool)
+static void texture_nodes_fetch_images_for_pool(Tex *texture, bNodeTree *ntree, struct ImagePool *pool)
{
for (bNode *node = ntree->nodes.first; node; node = node->next) {
if (node->type == SH_NODE_TEX_IMAGE && node->id != NULL) {
Image *image = (Image *)node->id;
- BKE_image_pool_acquire_ibuf(image, NULL, pool);
+ BKE_image_pool_acquire_ibuf(image, &texture->iuser, pool);
}
else if (node->type == NODE_GROUP && node->id != NULL) {
/* TODO(sergey): Do we need to control recursion here? */
bNodeTree *nested_tree = (bNodeTree *)node->id;
- texture_nodes_fetch_images_for_pool(nested_tree, pool);
+ texture_nodes_fetch_images_for_pool(texture, nested_tree, pool);
}
}
}
@@ -1225,12 +1225,12 @@ static void texture_nodes_fetch_images_for_pool(bNodeTree *ntree, struct ImagePo
void BKE_texture_fetch_images_for_pool(Tex *texture, struct ImagePool *pool)
{
if (texture->nodetree != NULL) {
- texture_nodes_fetch_images_for_pool(texture->nodetree, pool);
+ texture_nodes_fetch_images_for_pool(texture, texture->nodetree, pool);
}
else {
if (texture->type == TEX_IMAGE) {
if (texture->ima != NULL) {
- BKE_image_pool_acquire_ibuf(texture->ima, NULL, pool);
+ BKE_image_pool_acquire_ibuf(texture->ima, &texture->iuser, pool);
}
}
}
diff --git a/source/blender/blenkernel/intern/tracking_region_tracker.c b/source/blender/blenkernel/intern/tracking_region_tracker.c
index dd7def16ca8..106dd125575 100644
--- a/source/blender/blenkernel/intern/tracking_region_tracker.c
+++ b/source/blender/blenkernel/intern/tracking_region_tracker.c
@@ -189,7 +189,7 @@ void tracking_configure_tracker(const MovieTrackingTrack *track, float *mask,
options->image1_mask = NULL;
}
-/* Peform tracking from a reference_marker to destination_ibuf.
+/* Perform tracking from a reference_marker to destination_ibuf.
* Uses marker as an initial position guess.
*
* Returns truth if tracker returned success, puts result
diff --git a/source/blender/blenkernel/intern/tracking_util.c b/source/blender/blenkernel/intern/tracking_util.c
index d8e98291117..8c1b846db84 100644
--- a/source/blender/blenkernel/intern/tracking_util.c
+++ b/source/blender/blenkernel/intern/tracking_util.c
@@ -787,9 +787,9 @@ static ImBuf *accessor_get_ibuf(TrackingImageAccessor *accessor,
* in the cache which is nice on the one hand (faster re-use of the
* frames) but on the other hand it bumps the memory usage up.
*/
- BLI_lock_thread(LOCK_MOVIECLIP);
+ BLI_thread_lock(LOCK_MOVIECLIP);
IMB_float_from_rect(orig_ibuf);
- BLI_unlock_thread(LOCK_MOVIECLIP);
+ BLI_thread_unlock(LOCK_MOVIECLIP);
final_ibuf = orig_ibuf;
}
/* Downscale if needed. */
diff --git a/source/blender/blenkernel/intern/undo_system.c b/source/blender/blenkernel/intern/undo_system.c
new file mode 100644
index 00000000000..fd62650e898
--- /dev/null
+++ b/source/blender/blenkernel/intern/undo_system.c
@@ -0,0 +1,846 @@
+/*
+ * ***** 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/undo_system.c
+ * \ingroup bke
+ *
+ * Used by ED_undo.h, internal implementation.
+ */
+
+#include <string.h>
+
+#include "CLG_log.h"
+
+#include "BLI_utildefines.h"
+#include "BLI_sys_types.h"
+#include "BLI_listbase.h"
+#include "BLI_string.h"
+#include "BLI_sort_utils.h"
+
+#include "DNA_listBase.h"
+#include "DNA_windowmanager_types.h"
+
+#include "BKE_context.h"
+#include "BKE_global.h"
+#include "BKE_library_override.h"
+#include "BKE_main.h"
+#include "BKE_undo_system.h"
+
+#include "MEM_guardedalloc.h"
+
+#define undo_stack _wm_undo_stack_disallow /* pass in as a variable always. */
+
+/** Odd requirement of Blender that we always keep a memfile undo in the stack. */
+#define WITH_GLOBAL_UNDO_KEEP_ONE
+
+/** Make sure all ID's created at the point we add an undo step that uses ID's. */
+#define WITH_GLOBAL_UNDO_ENSURE_UPDATED
+
+/** We only need this locally. */
+static CLG_LogRef LOG = {"bke.undosys"};
+
+/* -------------------------------------------------------------------- */
+/** \name Internal Nested Undo Checks
+ *
+ * Make sure we're not running undo operations from 'step_encode', 'step_decode' callbacks.
+ * bugs caused by this situation aren't _that_ hard to spot but aren't always so obvious.
+ * Best we have a check which shows the problem immediately.
+ *
+ * \{ */
+#define WITH_NESTED_UNDO_CHECK
+
+#ifdef WITH_NESTED_UNDO_CHECK
+static bool g_undo_callback_running = false;
+# define UNDO_NESTED_ASSERT(state) BLI_assert(g_undo_callback_running == state)
+# define UNDO_NESTED_CHECK_BEGIN { \
+ UNDO_NESTED_ASSERT(false); \
+ g_undo_callback_running = true; \
+} ((void)0)
+# define UNDO_NESTED_CHECK_END { \
+ UNDO_NESTED_ASSERT(true); \
+ g_undo_callback_running = false; \
+} ((void)0)
+#else
+# define UNDO_NESTED_ASSERT(state) ((void)0)
+# define UNDO_NESTED_CHECK_BEGIN ((void)0)
+# define UNDO_NESTED_CHECK_END ((void)0)
+#endif
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Public Undo Types
+ *
+ * Unfortunately we need this for a handful of places.
+ */
+const UndoType *BKE_UNDOSYS_TYPE_IMAGE = NULL;
+const UndoType *BKE_UNDOSYS_TYPE_MEMFILE = NULL;
+const UndoType *BKE_UNDOSYS_TYPE_PAINTCURVE = NULL;
+const UndoType *BKE_UNDOSYS_TYPE_PARTICLE = NULL;
+const UndoType *BKE_UNDOSYS_TYPE_SCULPT = NULL;
+const UndoType *BKE_UNDOSYS_TYPE_TEXT = NULL;
+/** \} */
+
+/* UndoType */
+
+static ListBase g_undo_types = {NULL, NULL};
+
+static const UndoType *BKE_undosys_type_from_context(bContext *C)
+{
+ for (const UndoType *ut = g_undo_types.first; ut; ut = ut->next) {
+ /* No poll means we don't check context. */
+ if (ut->poll && ut->poll(C)) {
+ return ut;
+ }
+ }
+ return NULL;
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Internal Callback Wrappers
+ *
+ * #UndoRefID is simply a way to avoid inlining name copy and lookups,
+ * since it's easy to forget a single case when done inline (crashing in some cases).
+ *
+ * \{ */
+
+static void undosys_id_ref_store(void *UNUSED(user_data), UndoRefID *id_ref)
+{
+ BLI_assert(id_ref->name[0] == '\0');
+ if (id_ref->ptr) {
+ BLI_strncpy(id_ref->name, id_ref->ptr->name, sizeof(id_ref->name));
+ /* Not needed, just prevents stale data access. */
+ id_ref->ptr = NULL;
+ }
+}
+
+static void undosys_id_ref_resolve(void *user_data, UndoRefID *id_ref)
+{
+ /* Note: we could optimize this, for now it's not too bad since it only runs when we access undo! */
+ Main *bmain = user_data;
+ ListBase *lb = which_libbase(bmain, GS(id_ref->name));
+ for (ID *id = lb->first; id; id = id->next) {
+ if (STREQ(id_ref->name, id->name) && (id->lib == NULL)) {
+ id_ref->ptr = id;
+ break;
+ }
+ }
+}
+
+static bool undosys_step_encode(bContext *C, UndoStep *us)
+{
+ CLOG_INFO(&LOG, 2, "addr=%p, name='%s', type='%s'", us, us->name, us->type->name);
+ UNDO_NESTED_CHECK_BEGIN;
+ bool ok = us->type->step_encode(C, us);
+ UNDO_NESTED_CHECK_END;
+ if (ok) {
+ if (us->type->step_foreach_ID_ref != NULL) {
+ /* Don't use from context yet because sometimes context is fake and not all members are filled in. */
+ Main *bmain = G.main;
+ us->type->step_foreach_ID_ref(us, undosys_id_ref_store, bmain);
+ }
+ }
+ if (ok == false) {
+ CLOG_INFO(&LOG, 2, "encode callback didn't create undo step");
+ }
+ return ok;
+}
+
+static void undosys_step_decode(bContext *C, UndoStep *us, int dir)
+{
+ CLOG_INFO(&LOG, 2, "addr=%p, name='%s', type='%s'", us, us->name, us->type->name);
+ if (us->type->step_foreach_ID_ref) {
+ /* Don't use from context yet because sometimes context is fake and not all members are filled in. */
+ Main *bmain = G.main;
+ us->type->step_foreach_ID_ref(us, undosys_id_ref_resolve, bmain);
+ }
+
+ UNDO_NESTED_CHECK_BEGIN;
+ us->type->step_decode(C, us, dir);
+ UNDO_NESTED_CHECK_END;
+}
+
+static void undosys_step_free_and_unlink(UndoStack *ustack, UndoStep *us)
+{
+ CLOG_INFO(&LOG, 2, "addr=%p, name='%s', type='%s'", us, us->name, us->type->name);
+ UNDO_NESTED_CHECK_BEGIN;
+ us->type->step_free(us);
+ UNDO_NESTED_CHECK_END;
+
+ BLI_remlink(&ustack->steps, us);
+ MEM_freeN(us);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Undo Stack
+ * \{ */
+
+#ifndef NDEBUG
+static void undosys_stack_validate(UndoStack *ustack, bool expect_non_empty)
+{
+ if (ustack->step_active != NULL) {
+ BLI_assert(!BLI_listbase_is_empty(&ustack->steps));
+ BLI_assert(BLI_findindex(&ustack->steps, ustack->step_active) != -1);
+ }
+ if (expect_non_empty) {
+ BLI_assert(!BLI_listbase_is_empty(&ustack->steps));
+ }
+}
+#else
+static void undosys_stack_validate(UndoStack *ustack, bool expect_non_empty)
+{
+ UNUSED_VARS(ustack, expect_non_empty);
+}
+#endif
+
+UndoStack *BKE_undosys_stack_create(void)
+{
+ UndoStack *ustack = MEM_callocN(sizeof(UndoStack), __func__);
+ return ustack;
+}
+
+void BKE_undosys_stack_destroy(UndoStack *ustack)
+{
+ BKE_undosys_stack_clear(ustack);
+ MEM_freeN(ustack);
+}
+
+void BKE_undosys_stack_clear(UndoStack *ustack)
+{
+ UNDO_NESTED_ASSERT(false);
+ CLOG_INFO(&LOG, 1, "steps=%d", BLI_listbase_count(&ustack->steps));
+ for (UndoStep *us = ustack->steps.last, *us_prev; us; us = us_prev) {
+ us_prev = us->prev;
+ undosys_step_free_and_unlink(ustack, us);
+ }
+ BLI_listbase_clear(&ustack->steps);
+ ustack->step_active = NULL;
+}
+
+static bool undosys_stack_push_main(UndoStack *ustack, const char *name, struct Main *bmain)
+{
+ UNDO_NESTED_ASSERT(false);
+ CLOG_INFO(&LOG, 1, "'%s'", name);
+ bContext *C_temp = CTX_create();
+ CTX_data_main_set(C_temp, bmain);
+ bool ok = BKE_undosys_step_push_with_type(ustack, C_temp, name, BKE_UNDOSYS_TYPE_MEMFILE);
+ CTX_free(C_temp);
+ return ok;
+}
+
+void BKE_undosys_stack_init_from_main(UndoStack *ustack, struct Main *bmain)
+{
+ UNDO_NESTED_ASSERT(false);
+ undosys_stack_push_main(ustack, "original", bmain);
+}
+
+/* name optional */
+bool BKE_undosys_stack_has_undo(UndoStack *ustack, const char *name)
+{
+ if (name) {
+ UndoStep *us = BLI_rfindstring(&ustack->steps, name, offsetof(UndoStep, name));
+ return us && us->prev;
+ }
+
+ return !BLI_listbase_is_empty(&ustack->steps);
+}
+
+UndoStep *BKE_undosys_stack_active_with_type(UndoStack *ustack, const UndoType *ut)
+{
+ UndoStep *us = ustack->step_active;
+ while (us && (us->type != ut)) {
+ us = us->prev;
+ }
+ return us;
+}
+
+UndoStep *BKE_undosys_stack_init_or_active_with_type(UndoStack *ustack, const UndoType *ut)
+{
+ UNDO_NESTED_ASSERT(false);
+ CLOG_INFO(&LOG, 1, "type='%s'", ut->name);
+ if (ustack->step_init && (ustack->step_init->type == ut)) {
+ return ustack->step_init;
+ }
+ return BKE_undosys_stack_active_with_type(ustack, ut);
+}
+
+/**
+ * \param steps: Limit the number of undo steps.
+ * \param memory_limit: Limit the amount of memory used by the undo stack.
+ */
+void BKE_undosys_stack_limit_steps_and_memory(UndoStack *ustack, int steps, size_t memory_limit)
+{
+ UNDO_NESTED_ASSERT(false);
+ if (!(steps || memory_limit)) {
+ return;
+ }
+
+ CLOG_INFO(&LOG, 1, "steps=%d, memory_limit=%zu", steps, memory_limit);
+ UndoStep *us;
+#ifdef WITH_GLOBAL_UNDO_KEEP_ONE
+ UndoStep *us_exclude = NULL;
+#endif
+ /* keep at least two (original + other) */
+ size_t data_size_all = 0;
+ size_t us_count = 0;
+ for (us = ustack->steps.last; us && us->prev; us = us->prev) {
+ if (memory_limit) {
+ data_size_all += us->data_size;
+ if (data_size_all > memory_limit) {
+ break;
+ }
+ }
+ if (steps) {
+ if (us_count == steps) {
+ break;
+ }
+ if (us->skip == false) {
+ us_count += 1;
+ }
+ }
+ }
+
+ if (us) {
+ if (us->prev && us->prev->prev) {
+ us = us->prev;
+ }
+
+#ifdef WITH_GLOBAL_UNDO_KEEP_ONE
+ /* Hack, we need to keep at least one BKE_UNDOSYS_TYPE_MEMFILE. */
+ if (us->type != BKE_UNDOSYS_TYPE_MEMFILE) {
+ us_exclude = us->prev;
+ while (us_exclude && us->type != BKE_UNDOSYS_TYPE_MEMFILE) {
+ us_exclude = us_exclude->prev;
+ }
+ if (us_exclude) {
+ BLI_remlink(&ustack->steps, us_exclude);
+ }
+ }
+#endif
+ /* Free from first to last, free functions may update de-duplication info (see #MemFileUndoStep). */
+ while (ustack->steps.first != us) {
+ UndoStep *us_first = ustack->steps.first;
+ BLI_assert(us_first != ustack->step_active);
+ undosys_step_free_and_unlink(ustack, us_first);
+ }
+
+#ifdef WITH_GLOBAL_UNDO_KEEP_ONE
+ if (us_exclude) {
+ BLI_addhead(&ustack->steps, us_exclude);
+ }
+#endif
+ }
+}
+
+/** \} */
+
+UndoStep *BKE_undosys_step_push_init_with_type(UndoStack *ustack, bContext *C, const char *name, const UndoType *ut)
+{
+ UNDO_NESTED_ASSERT(false);
+ /* We could detect and clean this up (but it should never happen!). */
+ BLI_assert(ustack->step_init == NULL);
+ if (ut->step_encode_init) {
+ undosys_stack_validate(ustack, false);
+ UndoStep *us = MEM_callocN(ut->step_size, __func__);
+ CLOG_INFO(&LOG, 1, "addr=%p, name='%s', type='%s'", us, name, ut->name);
+ if (name != NULL) {
+ BLI_strncpy(us->name, name, sizeof(us->name));
+ }
+ us->type = ut;
+ ustack->step_init = us;
+ ut->step_encode_init(C, us);
+ undosys_stack_validate(ustack, true);
+ return us;
+ }
+ else {
+ return NULL;
+ }
+}
+
+UndoStep *BKE_undosys_step_push_init(UndoStack *ustack, bContext *C, const char *name)
+{
+ UNDO_NESTED_ASSERT(false);
+ /* We could detect and clean this up (but it should never happen!). */
+ BLI_assert(ustack->step_init == NULL);
+ const UndoType *ut = BKE_undosys_type_from_context(C);
+ if (ut == NULL) {
+ return NULL;
+ }
+ return BKE_undosys_step_push_init_with_type(ustack, C, name, ut);
+}
+
+bool BKE_undosys_step_push_with_type(UndoStack *ustack, bContext *C, const char *name, const UndoType *ut)
+{
+ UNDO_NESTED_ASSERT(false);
+ undosys_stack_validate(ustack, false);
+ bool is_not_empty = ustack->step_active != NULL;
+
+ /* Might not be final place for this to be called - probably only want to call it from some
+ * undo handlers, not all of them? */
+ BKE_main_override_static_operations_create(CTX_data_main(C));
+
+ /* Remove all undos after (also when 'ustack->step_active == NULL'). */
+ while (ustack->steps.last != ustack->step_active) {
+ UndoStep *us_iter = ustack->steps.last;
+ undosys_step_free_and_unlink(ustack, us_iter);
+ undosys_stack_validate(ustack, is_not_empty);
+ }
+
+ if (ustack->step_active) {
+ BLI_assert(BLI_findindex(&ustack->steps, ustack->step_active) != -1);
+ }
+
+#ifdef WITH_GLOBAL_UNDO_ENSURE_UPDATED
+ if (ut->step_foreach_ID_ref != NULL) {
+ Main *bmain = G.main;
+ if (bmain->is_memfile_undo_written == false) {
+ const char *name_internal = "MemFile Internal";
+ if (undosys_stack_push_main(ustack, name_internal, bmain)) {
+ UndoStep *us = ustack->steps.last;
+ BLI_assert(STREQ(us->name, name_internal));
+ us->skip = true;
+ }
+ }
+ }
+#endif
+
+ UndoStep *us = ustack->step_init ? ustack->step_init : MEM_callocN(ut->step_size, __func__);
+ ustack->step_init = NULL;
+ if (us->name[0] == '\0') {
+ BLI_strncpy(us->name, name, sizeof(us->name));
+ }
+ us->type = ut;
+ /* initialized, not added yet. */
+
+ if (undosys_step_encode(C, us)) {
+ ustack->step_active = us;
+ BLI_addtail(&ustack->steps, us);
+ undosys_stack_validate(ustack, true);
+ return true;
+ }
+ else {
+ MEM_freeN(us);
+ undosys_stack_validate(ustack, true);
+ return false;
+ }
+}
+
+bool BKE_undosys_step_push(UndoStack *ustack, bContext *C, const char *name)
+{
+ UNDO_NESTED_ASSERT(false);
+ const UndoType *ut = ustack->step_init ? ustack->step_init->type : BKE_undosys_type_from_context(C);
+ if (ut == NULL) {
+ return false;
+ }
+ return BKE_undosys_step_push_with_type(ustack, C, name, ut);
+}
+
+
+/**
+ * Useful when we want to diff against previous undo data but can't be sure the types match.
+ */
+UndoStep *BKE_undosys_step_same_type_next(UndoStep *us)
+{
+ if (us) {
+ const UndoType *ut = us->type;
+ while ((us = us->next)) {
+ if (us->type == ut) {
+ return us;
+ }
+ }
+
+ }
+ return us;
+}
+
+/**
+ * Useful when we want to diff against previous undo data but can't be sure the types match.
+ */
+UndoStep *BKE_undosys_step_same_type_prev(UndoStep *us)
+{
+ if (us) {
+ const UndoType *ut = us->type;
+ while ((us = us->prev)) {
+ if (us->type == ut) {
+ return us;
+ }
+ }
+
+ }
+ return us;
+}
+
+UndoStep *BKE_undosys_step_find_by_name_with_type(UndoStack *ustack, const char *name, const UndoType *ut)
+{
+ for (UndoStep *us = ustack->steps.last; us; us = us->prev) {
+ if (us->type == ut) {
+ if (STREQ(name, us->name)) {
+ return us;
+ }
+ }
+ }
+ return NULL;
+}
+
+UndoStep *BKE_undosys_step_find_by_name(UndoStack *ustack, const char *name)
+{
+ return BLI_rfindstring(&ustack->steps, name, offsetof(UndoStep, name));
+}
+
+UndoStep *BKE_undosys_step_find_by_type(UndoStack *ustack, const UndoType *ut)
+{
+ for (UndoStep *us = ustack->steps.last; us; us = us->prev) {
+ if (us->type == ut) {
+ return us;
+ }
+ }
+ return NULL;
+}
+
+bool BKE_undosys_step_undo_with_data_ex(
+ UndoStack *ustack, bContext *C, UndoStep *us,
+ bool use_skip)
+{
+ UNDO_NESTED_ASSERT(false);
+ if (us) {
+ undosys_stack_validate(ustack, true);
+ }
+ UndoStep *us_prev = us ? us->prev : NULL;
+ if (us && us->type->mode == BKE_UNDOTYPE_MODE_STORE) {
+ /* The current state is a copy, we need to load the previous state. */
+ us = us_prev;
+ }
+
+ if (us != NULL) {
+ CLOG_INFO(&LOG, 1, "addr=%p, name='%s', type='%s'", us, us->name, us->type->name);
+ undosys_step_decode(C, us, -1);
+ ustack->step_active = us_prev;
+ undosys_stack_validate(ustack, true);
+ if (use_skip) {
+ if (ustack->step_active && ustack->step_active->skip) {
+ CLOG_INFO(&LOG, 2, "undo continue with skip %p '%s', type='%s'", us, us->name, us->type->name);
+ BKE_undosys_step_undo_with_data(ustack, C, ustack->step_active);
+ }
+ }
+ return true;
+ }
+ return false;
+}
+bool BKE_undosys_step_undo_with_data(UndoStack *ustack, bContext *C, UndoStep *us)
+{
+ return BKE_undosys_step_undo_with_data_ex(ustack, C, us, true);
+}
+
+bool BKE_undosys_step_undo(UndoStack *ustack, bContext *C)
+{
+ return BKE_undosys_step_undo_with_data(ustack, C, ustack->step_active);
+}
+
+void BKE_undosys_step_undo_from_index(UndoStack *ustack, bContext *C, int index)
+{
+ UndoStep *us = BLI_findlink(&ustack->steps, index);
+ BLI_assert(us->skip == false);
+ BKE_undosys_step_load_data(ustack, C, us);
+}
+
+bool BKE_undosys_step_redo_with_data_ex(
+ UndoStack *ustack, bContext *C, UndoStep *us,
+ bool use_skip)
+{
+ UNDO_NESTED_ASSERT(false);
+ UndoStep *us_next = us ? us->next : NULL;
+ /* Unlike undo accumulate, we always use the next. */
+ us = us_next;
+
+ if (us != NULL) {
+ CLOG_INFO(&LOG, 1, "addr=%p, name='%s', type='%s'", us, us->name, us->type->name);
+ undosys_step_decode(C, us, 1);
+ ustack->step_active = us_next;
+ if (use_skip) {
+ if (ustack->step_active && ustack->step_active->skip) {
+ CLOG_INFO(&LOG, 2, "redo continue with skip %p '%s', type='%s'", us, us->name, us->type->name);
+ BKE_undosys_step_redo_with_data(ustack, C, ustack->step_active);
+ }
+ }
+ return true;
+ }
+ return false;
+}
+bool BKE_undosys_step_redo_with_data(UndoStack *ustack, bContext *C, UndoStep *us)
+{
+ return BKE_undosys_step_redo_with_data_ex(ustack, C, us, true);
+}
+
+bool BKE_undosys_step_redo(UndoStack *ustack, bContext *C)
+{
+ return BKE_undosys_step_redo_with_data(ustack, C, ustack->step_active);
+}
+
+bool BKE_undosys_step_load_data(UndoStack *ustack, bContext *C, UndoStep *us)
+{
+ UNDO_NESTED_ASSERT(false);
+ const int index_active = BLI_findindex(&ustack->steps, ustack->step_active);
+ const int index_target = BLI_findindex(&ustack->steps, us);
+ BLI_assert(!ELEM(-1, index_active, index_target));
+ bool ok = true;
+
+ if (index_target < index_active) {
+ uint i = index_active - index_target;
+ while (i-- && ok) {
+ ok = BKE_undosys_step_undo_with_data_ex(ustack, C, ustack->step_active, false);
+ }
+ }
+ else if (index_target > index_active) {
+ uint i = index_target - index_active;
+ while (i-- && ok) {
+ ok = BKE_undosys_step_redo_with_data_ex(ustack, C, ustack->step_active, false);
+ }
+ }
+
+ if (ok) {
+ BLI_assert(ustack->step_active == us);
+ }
+
+ return ok;
+}
+
+bool BKE_undosys_step_undo_compat_only(UndoStack *ustack, bContext *C, int step)
+{
+ if (step == 0) {
+ return BKE_undosys_step_undo_with_data(ustack, C, ustack->step_active);
+ }
+ else if (step == 1) {
+ return BKE_undosys_step_undo(ustack, C);
+ }
+ else {
+ return BKE_undosys_step_redo(ustack, C);
+ }
+}
+/**
+ * Similar to #WM_operatortype_append
+ */
+UndoType *BKE_undosys_type_append(void (*undosys_fn)(UndoType *))
+{
+ UndoType *ut;
+
+ ut = MEM_callocN(sizeof(UndoType), __func__);
+
+ undosys_fn(ut);
+
+ BLI_assert(ut->mode != 0);
+
+ BLI_addtail(&g_undo_types, ut);
+
+ return ut;
+}
+
+void BKE_undosys_type_free_all(void)
+{
+ UndoType *ut;
+ while ((ut = BLI_pophead(&g_undo_types))) {
+ MEM_freeN(ut);
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name ID Reference Utilities
+ *
+ * Unfortunately we need this for a handful of places.
+ */
+
+static void UNUSED_FUNCTION(BKE_undosys_foreach_ID_ref(
+ UndoStack *ustack, UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data))
+{
+ for (UndoStep *us = ustack->steps.first; us; us = us->next) {
+ const UndoType *ut = us->type;
+ if (ut->step_foreach_ID_ref != NULL) {
+ ut->step_foreach_ID_ref(us, foreach_ID_ref_fn, user_data);
+ }
+ }
+}
+
+typedef struct UndoIDPtrMapItem {
+ /** Never changes (matches undo data). Use as sort key for binary search. */
+ const void *ptr;
+ /** Write the new pointers here. */
+ uint index;
+} UndoIDPtrMapItem;
+
+typedef struct UndoIDPtrMap {
+ UndoRefID *refs;
+ /**
+ * Pointer map, update 'dst' members before use.
+ * This is always sorted (adds some overhead when adding, in practice it's acceptable since).
+ */
+ UndoIDPtrMapItem *pmap;
+
+ /** Length for both 'refs' & 'pmap' */
+ uint len;
+ uint len_alloc;
+} UndoIDPtrMap;
+
+#ifdef DEBUG
+# define PMAP_DEFAULT_ALLOC 1
+#else
+# define PMAP_DEFAULT_ALLOC 32
+#endif
+
+void BKE_undosys_ID_map_foreach_ID_ref(
+ UndoIDPtrMap *map,
+ UndoTypeForEachIDRefFn foreach_ID_ref_fn, void *user_data)
+{
+ for (uint i = 0; i < map->len; i++) {
+ foreach_ID_ref_fn(user_data, &map->refs[i]);
+ }
+}
+
+/**
+ * Return true when found, otherwise index is set to the index we should insert.
+ */
+static bool undosys_ID_map_lookup_index(const UndoIDPtrMap *map, const void *key, uint *r_index)
+{
+ const UndoIDPtrMapItem *pmap = map->pmap;
+ const uint len = map->len;
+ if (len == 0) {
+ if (*r_index) {
+ *r_index = 0;
+ }
+ return false;
+ }
+ int min = 0, max = len - 1;
+ while (min <= max) {
+ const uint mid = (min + max) / 2;
+ if (pmap[mid].ptr < key) {
+ min = mid + 1;
+ }
+ else if (pmap[mid].ptr == key) {
+ if (r_index) {
+ *r_index = mid;
+ }
+ return true;
+ }
+ else if (pmap[mid].ptr > key) {
+ max = mid - 1;
+ }
+ }
+ if (r_index) {
+ *r_index = min;
+ }
+ return false;
+}
+
+/**
+ * A set of ID's use for efficient decoding, so we can map pointers back to the newly loaded data
+ * without performing full look ups each time.
+ *
+ * This can be used as an old_pointer -> new_pointer lookup.
+ */
+UndoIDPtrMap *BKE_undosys_ID_map_create(void)
+{
+ UndoIDPtrMap *map = MEM_mallocN(sizeof(*map), __func__);
+ map->len_alloc = PMAP_DEFAULT_ALLOC;
+ map->refs = MEM_mallocN(sizeof(*map->refs) * map->len_alloc, __func__);
+ map->pmap = MEM_mallocN(sizeof(*map->pmap) * map->len_alloc, __func__);
+ map->len = 0;
+ return map;
+}
+void BKE_undosys_ID_map_destroy(UndoIDPtrMap *idpmap)
+{
+ MEM_SAFE_FREE(idpmap->refs);
+ MEM_SAFE_FREE(idpmap->pmap);
+ MEM_freeN(idpmap);
+}
+
+void BKE_undosys_ID_map_add(UndoIDPtrMap *map, ID *id)
+{
+ uint index;
+ if (id->lib != NULL) {
+ return;
+ }
+
+ if (undosys_ID_map_lookup_index(map, id, &index)) {
+ return; /* exists. */
+ }
+
+ const uint len_src = map->len;
+ const uint len_dst = map->len + 1;
+ if (len_dst > map->len_alloc) {
+ map->len_alloc *= 2;
+ BLI_assert(map->len_alloc >= len_dst);
+ map->pmap = MEM_reallocN(map->pmap, sizeof(*map->pmap) * map->len_alloc);
+ map->refs = MEM_reallocN(map->refs, sizeof(*map->refs) * map->len_alloc);
+ }
+
+#if 0 /* Will be done automatically in callback. */
+ BLI_strncpy(map->refs[len_src].name, id->name, sizeof(id->name));
+#else
+ map->refs[len_src].name[0] = '\0';
+#endif
+ map->refs[len_src].ptr = id;
+
+ if (len_src != 0 && index != len_src) {
+ memmove(&map->pmap[index + 1], &map->pmap[index], sizeof(*map->pmap) * (len_src - index));
+ }
+ map->pmap[index].ptr = id;
+ map->pmap[index].index = len_src;
+
+ map->len = len_dst;
+}
+
+ID *BKE_undosys_ID_map_lookup(const UndoIDPtrMap *map, const ID *id_src)
+{
+ /* We should only ever lookup indices which exist! */
+ uint index;
+ if (!undosys_ID_map_lookup_index(map, id_src, &index)) {
+ BLI_assert(0);
+ }
+ index = map->pmap[index].index;
+ ID *id_dst = map->refs[index].ptr;
+ BLI_assert(id_dst != NULL);
+ BLI_assert(STREQ(id_dst->name, map->refs[index].name));
+ return id_dst;
+}
+
+void BKE_undosys_ID_map_add_with_prev(UndoIDPtrMap *map, ID *id, ID **id_prev)
+{
+ if (id == *id_prev) {
+ return;
+ }
+ *id_prev = id;
+ BKE_undosys_ID_map_add(map, id);
+}
+
+ID *BKE_undosys_ID_map_lookup_with_prev(const UndoIDPtrMap *map, ID *id_src, ID *id_prev_match[2])
+{
+ if (id_src == id_prev_match[0]) {
+ return id_prev_match[1];
+ }
+ else {
+ ID *id_dst = BKE_undosys_ID_map_lookup(map, id_src);
+ id_prev_match[0] = id_src;
+ id_prev_match[1] = id_dst;
+ return id_dst;
+ }
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/workspace.c b/source/blender/blenkernel/intern/workspace.c
index 8554cf0fb28..afceea9dd5f 100644
--- a/source/blender/blenkernel/intern/workspace.c
+++ b/source/blender/blenkernel/intern/workspace.c
@@ -38,6 +38,7 @@
#include "BKE_main.h"
#include "BKE_scene.h"
#include "BKE_screen.h"
+#include "BKE_object.h"
#include "BKE_workspace.h"
#include "DNA_object_types.h"
@@ -45,6 +46,8 @@
#include "DNA_screen_types.h"
#include "DNA_workspace_types.h"
+#include "DEG_depsgraph.h"
+
#include "MEM_guardedalloc.h"
@@ -166,6 +169,7 @@ void BKE_workspace_free(WorkSpace *workspace)
BKE_workspace_relations_free(&workspace->hook_layout_relations);
BKE_workspace_relations_free(&workspace->scene_viewlayer_relations);
+ BLI_freelistN(&workspace->owner_ids);
BLI_freelistN(&workspace->layouts);
BLI_freelistN(&workspace->transform_orientations);
@@ -353,22 +357,22 @@ WorkSpaceLayout *BKE_workspace_layout_iter_circular(
WorkSpaceLayout *iter_layout;
if (iter_backward) {
- BLI_LISTBASE_CIRCULAR_BACKWARD_BEGIN(&workspace->layouts, iter_layout, start)
+ 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);
+ LISTBASE_CIRCULAR_BACKWARD_END(&workspace->layouts, iter_layout, start);
}
else {
- BLI_LISTBASE_CIRCULAR_FORWARD_BEGIN(&workspace->layouts, iter_layout, start)
+ 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)
+ LISTBASE_CIRCULAR_FORWARD_END(&workspace->layouts, iter_layout, start)
}
return NULL;
@@ -413,21 +417,6 @@ void BKE_workspace_active_screen_set(WorkSpaceInstanceHook *hook, WorkSpace *wor
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);
@@ -510,8 +499,7 @@ void BKE_workspace_use_scene_settings_set(WorkSpace *workspace, bool value)
/* Update / evaluate */
-void BKE_workspace_update_tagged(struct EvaluationContext *eval_ctx,
- Main *bmain,
+void BKE_workspace_update_tagged(Main *bmain,
WorkSpace *workspace,
Scene *scene)
{
@@ -519,5 +507,21 @@ void BKE_workspace_update_tagged(struct EvaluationContext *eval_ctx,
struct Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene,
view_layer,
true);
- BKE_scene_graph_update_tagged(eval_ctx, depsgraph, bmain, scene, view_layer);
+ BKE_scene_graph_update_tagged(depsgraph, bmain);
}
+
+
+bool BKE_workspace_owner_id_check(
+ const WorkSpace *workspace, const char *owner_id)
+{
+ if ((*owner_id == '\0') ||
+ ((workspace->flags & WORKSPACE_USE_FILTER_BY_ORIGIN) == 0))
+ {
+ return true;
+ }
+ else {
+ /* we could use hash lookup, for now this list is highly under < ~16 items. */
+ return BLI_findstring(&workspace->owner_ids, owner_id, offsetof(wmOwnerID, name)) != NULL;
+ }
+}
+
diff --git a/source/blender/blenkernel/intern/world.c b/source/blender/blenkernel/intern/world.c
index 5da8dc563e2..e87e84736c8 100644
--- a/source/blender/blenkernel/intern/world.c
+++ b/source/blender/blenkernel/intern/world.c
@@ -33,6 +33,7 @@
#include <string.h>
#include <stdlib.h>
#include <math.h>
+
#include "MEM_guardedalloc.h"
#include "DNA_world_types.h"
@@ -196,7 +197,7 @@ void BKE_world_make_local(Main *bmain, World *wrld, const bool lib_local)
void BKE_world_eval(const struct EvaluationContext *UNUSED(eval_ctx), World *world)
{
- if (G.debug & G_DEBUG_DEPSGRAPH) {
+ if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) {
printf("%s on %s (%p)\n", __func__, world->id.name, world);
}
if (!BLI_listbase_is_empty(&world->gpumaterial)) {
diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c
index f745a840cea..0a2527bafd2 100644
--- a/source/blender/blenkernel/intern/writeffmpeg.c
+++ b/source/blender/blenkernel/intern/writeffmpeg.c
@@ -53,6 +53,7 @@
#include "BKE_global.h"
#include "BKE_idprop.h"
+#include "BKE_image.h"
#include "BKE_main.h"
#include "BKE_report.h"
#include "BKE_sound.h"
@@ -62,6 +63,8 @@
#include "ffmpeg_compat.h"
+struct StampData;
+
typedef struct FFMpegContext {
int ffmpeg_type;
int ffmpeg_codec;
@@ -94,6 +97,8 @@ typedef struct FFMpegContext {
bool audio_deinterleave;
int audio_sample_size;
+ struct StampData *stamp_data;
+
#ifdef WITH_AUDASPACE
AUD_Device *audio_mixdown_device;
#endif
@@ -577,24 +582,33 @@ static AVStream *alloc_video_stream(FFMpegContext *context, RenderData *rd, int
}
if (context->ffmpeg_preset) {
- char const *preset_name;
+ /* 'preset' is used by h.264, 'deadline' is used by webm/vp9. I'm not
+ * setting those properties conditionally based on the video codec,
+ * as the FFmpeg encoder simply ignores unknown settings anyway. */
+ char const *preset_name = NULL; /* used by h.264 */
+ char const *deadline_name = NULL; /* used by webm/vp9 */
switch (context->ffmpeg_preset) {
- case FFM_PRESET_ULTRAFAST: preset_name = "ultrafast"; break;
- case FFM_PRESET_SUPERFAST: preset_name = "superfast"; break;
- case FFM_PRESET_VERYFAST: preset_name = "veryfast"; break;
- case FFM_PRESET_FASTER: preset_name = "faster"; break;
- case FFM_PRESET_FAST: preset_name = "fast"; break;
- case FFM_PRESET_MEDIUM: preset_name = "medium"; break;
- case FFM_PRESET_SLOW: preset_name = "slow"; break;
- case FFM_PRESET_SLOWER: preset_name = "slower"; break;
- case FFM_PRESET_VERYSLOW: preset_name = "veryslow"; break;
+ case FFM_PRESET_GOOD:
+ preset_name = "medium";
+ deadline_name = "good";
+ break;
+ case FFM_PRESET_BEST:
+ preset_name = "slower";
+ deadline_name = "best";
+ break;
+ case FFM_PRESET_REALTIME:
+ preset_name = "superfast";
+ deadline_name = "realtime";
+ break;
default:
printf("Unknown preset number %i, ignoring.\n", context->ffmpeg_preset);
- preset_name = NULL;
}
if (preset_name != NULL) {
av_dict_set(&opts, "preset", preset_name, 0);
}
+ if (deadline_name != NULL) {
+ av_dict_set(&opts, "deadline", deadline_name, 0);
+ }
}
#if 0
@@ -836,6 +850,12 @@ static void ffmpeg_dict_set_float(AVDictionary **dict, const char *key, float va
av_dict_set(dict, key, buffer, 0);
}
+static void ffmpeg_add_metadata_callback(void *data, const char *propname, char *propvalue, int len)
+{
+ AVDictionary **metadata = (AVDictionary **)data;
+ av_dict_set(metadata, propname, propvalue, 0);
+}
+
static int start_ffmpeg_impl(FFMpegContext *context, struct RenderData *rd, int rectx, int recty, const char *suffix, ReportList *reports)
{
/* Handle to the output file */
@@ -994,6 +1014,11 @@ static int start_ffmpeg_impl(FFMpegContext *context, struct RenderData *rd, int
goto fail;
}
}
+
+ if (context->stamp_data != NULL) {
+ BKE_stamp_info_callback(&of->metadata, context->stamp_data, ffmpeg_add_metadata_callback, false);
+ }
+
if (avformat_write_header(of, NULL) < 0) {
BKE_report(reports, RPT_ERROR, "Could not initialize streams, probably unsupported codec combination");
goto fail;
@@ -1168,6 +1193,7 @@ int BKE_ffmpeg_start(void *context_v, struct Scene *scene, RenderData *rd, int r
context->ffmpeg_autosplit_count = 0;
context->ffmpeg_preview = preview;
+ context->stamp_data = BKE_stamp_info_from_scene_static(scene);
success = start_ffmpeg_impl(context, rd, rectx, recty, suffix, reports);
#ifdef WITH_AUDASPACE
@@ -1659,7 +1685,7 @@ void BKE_ffmpeg_image_type_verify(RenderData *rd, ImageFormatData *imf)
{
BKE_ffmpeg_preset_set(rd, FFMPEG_PRESET_H264);
rd->ffcodecdata.constant_rate_factor = FFM_CRF_MEDIUM;
- rd->ffcodecdata.ffmpeg_preset = FFM_PRESET_MEDIUM;
+ rd->ffcodecdata.ffmpeg_preset = FFM_PRESET_GOOD;
rd->ffcodecdata.type = FFMPEG_MKV;
}
if (rd->ffcodecdata.type == FFMPEG_OGG) {
@@ -1734,6 +1760,7 @@ void *BKE_ffmpeg_context_create(void)
context->ffmpeg_autosplit = 0;
context->ffmpeg_autosplit_count = 0;
context->ffmpeg_preview = false;
+ context->stamp_data = NULL;
return context;
}
@@ -1741,9 +1768,13 @@ void *BKE_ffmpeg_context_create(void)
void BKE_ffmpeg_context_free(void *context_v)
{
FFMpegContext *context = context_v;
- if (context) {
- MEM_freeN(context);
+ if (context == NULL) {
+ return;
+ }
+ if (context->stamp_data) {
+ MEM_freeN(context->stamp_data);
}
+ MEM_freeN(context);
}
#endif /* WITH_FFMPEG */