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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_DerivedMesh.h67
-rw-r--r--source/blender/blenkernel/BKE_action.h1
-rw-r--r--source/blender/blenkernel/BKE_armature.h32
-rw-r--r--source/blender/blenkernel/BKE_attribute.h4
-rw-r--r--source/blender/blenkernel/BKE_attribute_math.hh26
-rw-r--r--source/blender/blenkernel/BKE_blender_version.h6
-rw-r--r--source/blender/blenkernel/BKE_collection.h4
-rw-r--r--source/blender/blenkernel/BKE_constraint.h12
-rw-r--r--source/blender/blenkernel/BKE_curves.h68
-rw-r--r--source/blender/blenkernel/BKE_gpencil.h34
-rw-r--r--source/blender/blenkernel/BKE_gpencil_update_cache.h152
-rw-r--r--source/blender/blenkernel/BKE_hair.h63
-rw-r--r--source/blender/blenkernel/BKE_idtype.h2
-rw-r--r--source/blender/blenkernel/BKE_image_partial_update.hh4
-rw-r--r--source/blender/blenkernel/BKE_lib_id.h4
-rw-r--r--source/blender/blenkernel/BKE_lib_override.h32
-rw-r--r--source/blender/blenkernel/BKE_lib_query.h3
-rw-r--r--source/blender/blenkernel/BKE_lib_remap.h9
-rw-r--r--source/blender/blenkernel/BKE_main.h6
-rw-r--r--source/blender/blenkernel/BKE_mesh_fair.h5
-rw-r--r--source/blender/blenkernel/BKE_modifier.h4
-rw-r--r--source/blender/blenkernel/BKE_node.h8
-rw-r--r--source/blender/blenkernel/BKE_object.h24
-rw-r--r--source/blender/blenkernel/BKE_particle.h7
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h2
-rw-r--r--source/blender/blenkernel/CMakeLists.txt11
-rw-r--r--source/blender/blenkernel/intern/DerivedMesh.cc166
-rw-r--r--source/blender/blenkernel/intern/action.c19
-rw-r--r--source/blender/blenkernel/intern/anim_data.c8
-rw-r--r--source/blender/blenkernel/intern/anim_sys.c4
-rw-r--r--source/blender/blenkernel/intern/armature.c221
-rw-r--r--source/blender/blenkernel/intern/armature_pose.cc2
-rw-r--r--source/blender/blenkernel/intern/armature_update.c60
-rw-r--r--source/blender/blenkernel/intern/attribute.c29
-rw-r--r--source/blender/blenkernel/intern/attribute_access.cc17
-rw-r--r--source/blender/blenkernel/intern/attribute_access_intern.hh3
-rw-r--r--source/blender/blenkernel/intern/blendfile.c30
-rw-r--r--source/blender/blenkernel/intern/blendfile_link_append.c83
-rw-r--r--source/blender/blenkernel/intern/cdderivedmesh.c48
-rw-r--r--source/blender/blenkernel/intern/constraint.c47
-rw-r--r--source/blender/blenkernel/intern/crazyspace.c13
-rw-r--r--source/blender/blenkernel/intern/curves.cc473
-rw-r--r--source/blender/blenkernel/intern/customdata.cc21
-rw-r--r--source/blender/blenkernel/intern/dynamicpaint.c3
-rw-r--r--source/blender/blenkernel/intern/fcurve_driver.c20
-rw-r--r--source/blender/blenkernel/intern/gpencil.c292
-rw-r--r--source/blender/blenkernel/intern/gpencil_update_cache.c274
-rw-r--r--source/blender/blenkernel/intern/hair.cc435
-rw-r--r--source/blender/blenkernel/intern/idtype.c13
-rw-r--r--source/blender/blenkernel/intern/image_partial_update.cc7
-rw-r--r--source/blender/blenkernel/intern/image_partial_update_test.cc2
-rw-r--r--source/blender/blenkernel/intern/lib_id.c65
-rw-r--r--source/blender/blenkernel/intern/lib_id_delete.c10
-rw-r--r--source/blender/blenkernel/intern/lib_override.c365
-rw-r--r--source/blender/blenkernel/intern/lib_override_proxy_conversion.c176
-rw-r--r--source/blender/blenkernel/intern/lib_query.c8
-rw-r--r--source/blender/blenkernel/intern/lib_remap.c61
-rw-r--r--source/blender/blenkernel/intern/main.c6
-rw-r--r--source/blender/blenkernel/intern/material.c26
-rw-r--r--source/blender/blenkernel/intern/mball.c9
-rw-r--r--source/blender/blenkernel/intern/mesh.cc11
-rw-r--r--source/blender/blenkernel/intern/mesh_fair.cc5
-rw-r--r--source/blender/blenkernel/intern/mesh_iterators.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_merge.c13
-rw-r--r--source/blender/blenkernel/intern/mesh_validate.c11
-rw-r--r--source/blender/blenkernel/intern/modifier.c9
-rw-r--r--source/blender/blenkernel/intern/node.cc19
-rw-r--r--source/blender/blenkernel/intern/object.cc304
-rw-r--r--source/blender/blenkernel/intern/object_update.c50
-rw-r--r--source/blender/blenkernel/intern/ocean.c6
-rw-r--r--source/blender/blenkernel/intern/particle.c2
-rw-r--r--source/blender/blenkernel/intern/particle_system.c7
-rw-r--r--source/blender/blenkernel/intern/pbvh.c29
-rw-r--r--source/blender/blenkernel/intern/pbvh_intern.h4
-rw-r--r--source/blender/blenkernel/intern/subsurf_ccg.c171
-rw-r--r--source/blender/blenkernel/intern/type_conversions.cc64
-rw-r--r--source/blender/blenkernel/intern/vfontdata_freetype.c8
-rw-r--r--source/blender/blenkernel/intern/writeavi.c4
78 files changed, 2183 insertions, 2142 deletions
diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h
index 04ea987579d..4526bc38a70 100644
--- a/source/blender/blenkernel/BKE_DerivedMesh.h
+++ b/source/blender/blenkernel/BKE_DerivedMesh.h
@@ -104,14 +104,6 @@ typedef enum DerivedMeshType {
DM_TYPE_CCGDM,
} DerivedMeshType;
-typedef enum DMDirtyFlag {
- /* dm has valid tessellated faces, but tessellated CDDATA need to be updated. */
- DM_DIRTY_TESS_CDLAYERS = 1 << 0,
-
- /* check this with modifier dependsOnNormals callback to see if normals need recalculation */
- DM_DIRTY_NORMALS = 1 << 1,
-} DMDirtyFlag;
-
typedef struct DerivedMesh DerivedMesh;
struct DerivedMesh {
/** Private DerivedMesh data, only for internal DerivedMesh use */
@@ -120,7 +112,6 @@ struct DerivedMesh {
int needsFree; /* checked on ->release, is set to 0 for cached results */
int deformedOnly; /* set by modifier stack if only deformed from original */
DerivedMeshType type;
- DMDirtyFlag dirty;
/**
* \warning Typical access is done via #getLoopTriArray, #getNumLoopTri.
@@ -139,9 +130,6 @@ struct DerivedMesh {
short tangent_mask; /* which tangent layers are calculated */
- /** Calculate vert and face normals */
- void (*calcNormals)(DerivedMesh *dm);
-
/** Loop tessellation cache (WARNING! Only call inside threading-protected code!) */
void (*recalcLoopTri)(DerivedMesh *dm);
/** accessor functions */
@@ -164,7 +152,6 @@ struct DerivedMesh {
*/
struct MVert *(*getVertArray)(DerivedMesh *dm);
struct MEdge *(*getEdgeArray)(DerivedMesh *dm);
- struct MFace *(*getTessFaceArray)(DerivedMesh *dm);
struct MLoop *(*getLoopArray)(DerivedMesh *dm);
struct MPoly *(*getPolyArray)(DerivedMesh *dm);
@@ -173,7 +160,6 @@ struct DerivedMesh {
*/
void (*copyVertArray)(DerivedMesh *dm, struct MVert *r_vert);
void (*copyEdgeArray)(DerivedMesh *dm, struct MEdge *r_edge);
- void (*copyTessFaceArray)(DerivedMesh *dm, struct MFace *r_face);
void (*copyLoopArray)(DerivedMesh *dm, struct MLoop *r_loop);
void (*copyPolyArray)(DerivedMesh *dm, struct MPoly *r_poly);
@@ -182,37 +168,18 @@ struct DerivedMesh {
*/
struct MVert *(*dupVertArray)(DerivedMesh *dm);
struct MEdge *(*dupEdgeArray)(DerivedMesh *dm);
- struct MFace *(*dupTessFaceArray)(DerivedMesh *dm);
struct MLoop *(*dupLoopArray)(DerivedMesh *dm);
struct MPoly *(*dupPolyArray)(DerivedMesh *dm);
- /** Return a pointer to a single element of vert/edge/face custom data
- * from the derived mesh (this gives a pointer to the actual data, not
- * a copy)
- */
- void *(*getVertData)(DerivedMesh *dm, int index, int type);
- void *(*getEdgeData)(DerivedMesh *dm, int index, int type);
- void *(*getTessFaceData)(DerivedMesh *dm, int index, int type);
- void *(*getPolyData)(DerivedMesh *dm, int index, int type);
-
/** Return a pointer to the entire array of vert/edge/face custom data
* from the derived mesh (this gives a pointer to the actual data, not
* a copy)
*/
void *(*getVertDataArray)(DerivedMesh *dm, int type);
void *(*getEdgeDataArray)(DerivedMesh *dm, int type);
- void *(*getTessFaceDataArray)(DerivedMesh *dm, int type);
void *(*getLoopDataArray)(DerivedMesh *dm, int type);
void *(*getPolyDataArray)(DerivedMesh *dm, int type);
- /** Retrieves the base CustomData structures for
- * verts/edges/tessfaces/loops/faces. */
- CustomData *(*getVertDataLayout)(DerivedMesh *dm);
- CustomData *(*getEdgeDataLayout)(DerivedMesh *dm);
- CustomData *(*getTessFaceDataLayout)(DerivedMesh *dm);
- CustomData *(*getLoopDataLayout)(DerivedMesh *dm);
- CustomData *(*getPolyDataLayout)(DerivedMesh *dm);
-
/** Optional grid access for subsurf */
int (*getNumGrids)(DerivedMesh *dm);
int (*getGridSize)(DerivedMesh *dm);
@@ -231,11 +198,6 @@ struct DerivedMesh {
/** Get smooth vertex normal, undefined if index is not valid */
void (*getVertNo)(DerivedMesh *dm, int index, float r_no[3]);
- void (*getPolyNo)(DerivedMesh *dm, int index, float r_no[3]);
-
- /** Get a map of vertices to faces
- */
- const struct MeshElemMap *(*getPolyMap)(struct Object *ob, DerivedMesh *dm);
/** Release reference to the DerivedMesh. This function decides internally
* if the DerivedMesh will be freed, or cached for later use. */
@@ -265,15 +227,6 @@ void DM_init(DerivedMesh *dm,
* Utility function to initialize a DerivedMesh for the desired number
* of vertices, edges and faces, with a layer setup copied from source
*/
-void DM_from_template_ex(DerivedMesh *dm,
- DerivedMesh *source,
- DerivedMeshType type,
- int numVerts,
- int numEdges,
- int numTessFaces,
- int numLoops,
- int numPolys,
- const struct CustomData_MeshMasks *mask);
void DM_from_template(DerivedMesh *dm,
DerivedMesh *source,
DerivedMeshType type,
@@ -303,26 +256,9 @@ void DM_set_only_copy(DerivedMesh *dm, const struct CustomData_MeshMasks *mask);
void DM_add_vert_layer(struct DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer);
void DM_add_edge_layer(struct DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer);
-void DM_add_tessface_layer(struct DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer);
-void DM_add_loop_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer);
void DM_add_poly_layer(struct DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer);
/* -------------------------------------------------------------------- */
-/** \name Custom Data Access Functions
- *
- * \return pointer to data from first layer which matches type
- * if they return NULL for valid indices, data doesn't exist.
- * \note these return pointers - any change modifies the internals of the mesh.
- * \{ */
-
-void *DM_get_vert_data(struct DerivedMesh *dm, int index, int type);
-void *DM_get_edge_data(struct DerivedMesh *dm, int index, int type);
-void *DM_get_tessface_data(struct DerivedMesh *dm, int index, int type);
-void *DM_get_poly_data(struct DerivedMesh *dm, int index, int type);
-
-/** \} */
-
-/* -------------------------------------------------------------------- */
/** \name Custom Data Layer Access Functions
*
* \return pointer to first data layer which matches type (a flat array)
@@ -332,7 +268,6 @@ void *DM_get_poly_data(struct DerivedMesh *dm, int index, int type);
void *DM_get_vert_data_layer(struct DerivedMesh *dm, int type);
void *DM_get_edge_data_layer(struct DerivedMesh *dm, int type);
-void *DM_get_tessface_data_layer(struct DerivedMesh *dm, int type);
void *DM_get_poly_data_layer(struct DerivedMesh *dm, int type);
void *DM_get_loop_data_layer(struct DerivedMesh *dm, int type);
@@ -354,8 +289,6 @@ void DM_copy_vert_data(struct DerivedMesh *source,
*/
void DM_DupPolys(DerivedMesh *source, DerivedMesh *target);
-void DM_ensure_normals(DerivedMesh *dm);
-
/**
* Ensure the array is large enough.
*
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index 0b09bfd8730..5d1b4baedfd 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -365,7 +365,6 @@ void what_does_obaction(struct Object *ob,
char groupname[],
const struct AnimationEvalContext *anim_eval_context);
-/* for proxy */
void BKE_pose_copy_pchan_result(struct bPoseChannel *pchanto,
const struct bPoseChannel *pchanfrom);
/**
diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h
index 8584ce6f508..ede300b19dd 100644
--- a/source/blender/blenkernel/BKE_armature.h
+++ b/source/blender/blenkernel/BKE_armature.h
@@ -163,6 +163,30 @@ void BKE_armature_transform(struct bArmature *arm, const float mat[4][4], bool d
/* Bounding box. */
struct BoundBox *BKE_armature_boundbox_get(struct Object *ob);
+/**
+ * Calculate the axis-aligned bounds of `pchan` in world-space,
+ * taking into account custom transform when set.
+ *
+ * `r_min` and `r_max` are expanded to fit `pchan` so the caller must initialize them
+ * (typically using #INIT_MINMAX).
+ *
+ * \note The bounds are calculated based on the head & tail of the bone
+ * or the custom object's bounds (if the bone uses a custom object).
+ * Visual elements such as the envelopes radius & bendy-bone spline segments are *not* included,
+ * making this not so useful for viewport culling.
+ */
+void BKE_pchan_minmax(const struct Object *ob,
+ const struct bPoseChannel *pchan,
+ float r_min[3],
+ float r_max[3]);
+/**
+ * Calculate the axis aligned bounds of the pose of `ob` in world-space.
+
+ * `r_min` and `r_max` are expanded to fit `ob->pose` so the caller must initialize them
+ * (typically using #INIT_MINMAX).
+ *
+ * \note This uses #BKE_pchan_minmax, see its documentation for details on bounds calculation.
+ */
bool BKE_pose_minmax(
struct Object *ob, float r_min[3], float r_max[3], bool use_hidden, bool use_select);
@@ -619,14 +643,6 @@ void BKE_pose_eval_cleanup(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *object);
-void BKE_pose_eval_proxy_init(struct Depsgraph *depsgraph, struct Object *object);
-void BKE_pose_eval_proxy_done(struct Depsgraph *depsgraph, struct Object *object);
-void BKE_pose_eval_proxy_cleanup(struct Depsgraph *depsgraph, struct Object *object);
-
-void BKE_pose_eval_proxy_copy_bone(struct Depsgraph *depsgraph,
- struct Object *object,
- int pchan_index);
-
/* -------------------------------------------------------------------- */
/** \name Deform 3D Coordinates by Armature (armature_deform.c)
* \{ */
diff --git a/source/blender/blenkernel/BKE_attribute.h b/source/blender/blenkernel/BKE_attribute.h
index 6020da08f51..ff207997e79 100644
--- a/source/blender/blenkernel/BKE_attribute.h
+++ b/source/blender/blenkernel/BKE_attribute.h
@@ -40,11 +40,11 @@ struct ReportList;
/* Attribute.domain */
typedef enum AttributeDomain {
ATTR_DOMAIN_AUTO = -1, /* Use for nodes to choose automatically based on other data. */
- ATTR_DOMAIN_POINT = 0, /* Mesh, Hair or PointCloud Point */
+ ATTR_DOMAIN_POINT = 0, /* Mesh, Curve or Point Cloud Point */
ATTR_DOMAIN_EDGE = 1, /* Mesh Edge */
ATTR_DOMAIN_FACE = 2, /* Mesh Face */
ATTR_DOMAIN_CORNER = 3, /* Mesh Corner */
- ATTR_DOMAIN_CURVE = 4, /* Hair Curve */
+ ATTR_DOMAIN_CURVE = 4, /* A single curve in a larger curve data-block */
ATTR_DOMAIN_INSTANCE = 5, /* Instance */
ATTR_DOMAIN_NUM
diff --git a/source/blender/blenkernel/BKE_attribute_math.hh b/source/blender/blenkernel/BKE_attribute_math.hh
index 90f349125c9..bf773cd6d75 100644
--- a/source/blender/blenkernel/BKE_attribute_math.hh
+++ b/source/blender/blenkernel/BKE_attribute_math.hh
@@ -50,6 +50,9 @@ inline void convert_to_static_type(const CustomDataType data_type, const Func &f
case CD_PROP_BOOL:
func(bool());
break;
+ case CD_PROP_INT8:
+ func(int8_t());
+ break;
case CD_PROP_COLOR:
func(ColorGeometry4f());
break;
@@ -77,6 +80,9 @@ inline void convert_to_static_type(const fn::CPPType &cpp_type, const Func &func
else if (cpp_type.is<bool>()) {
func(bool());
}
+ else if (cpp_type.is<int8_t>()) {
+ func(int8_t());
+ }
else if (cpp_type.is<ColorGeometry4f>()) {
func(ColorGeometry4f());
}
@@ -93,6 +99,12 @@ inline void convert_to_static_type(const fn::CPPType &cpp_type, const Func &func
template<typename T> T mix3(const float3 &weights, const T &v0, const T &v1, const T &v2);
+template<>
+inline int8_t mix3(const float3 &weights, const int8_t &v0, const int8_t &v1, const int8_t &v2)
+{
+ return static_cast<int8_t>(weights.x * v0 + weights.y * v1 + weights.z * v2);
+}
+
template<> inline bool mix3(const float3 &weights, const bool &v0, const bool &v1, const bool &v2)
{
return (weights.x * v0 + weights.y * v1 + weights.z * v2) >= 0.5f;
@@ -147,6 +159,11 @@ template<> inline bool mix2(const float factor, const bool &a, const bool &b)
return ((1.0f - factor) * a + factor * b) >= 0.5f;
}
+template<> inline int8_t mix2(const float factor, const int8_t &a, const int8_t &b)
+{
+ return static_cast<int8_t>((1.0f - factor) * a + factor * b);
+}
+
template<> inline int mix2(const float factor, const int &a, const int &b)
{
return static_cast<int>((1.0f - factor) * a + factor * b);
@@ -364,6 +381,15 @@ template<> struct DefaultMixerStruct<bool> {
using type = SimpleMixerWithAccumulationType<bool, float, float_to_bool>;
};
+template<> struct DefaultMixerStruct<int8_t> {
+ static int8_t float_to_int8_t(const float &value)
+ {
+ return static_cast<int8_t>(value);
+ }
+ /* Store interpolated 8 bit integers in a float temporarily to increase accuracy. */
+ using type = SimpleMixerWithAccumulationType<int8_t, float, float_to_int8_t>;
+};
+
template<typename T> struct DefaultPropatationMixerStruct {
/* Use void by default. This can be checked for in `if constexpr` statements. */
using type = typename DefaultMixerStruct<T>::type;
diff --git a/source/blender/blenkernel/BKE_blender_version.h b/source/blender/blenkernel/BKE_blender_version.h
index d1f31e0d2f5..1ba887903c8 100644
--- a/source/blender/blenkernel/BKE_blender_version.h
+++ b/source/blender/blenkernel/BKE_blender_version.h
@@ -31,15 +31,15 @@ extern "C" {
*/
/* Blender major and minor version. */
-#define BLENDER_VERSION 301
+#define BLENDER_VERSION 302
/* Blender patch version for bugfix releases. */
#define BLENDER_VERSION_PATCH 0
/** Blender release cycle stage: alpha/beta/rc/release. */
-#define BLENDER_VERSION_CYCLE beta
+#define BLENDER_VERSION_CYCLE alpha
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
-#define BLENDER_FILE_SUBVERSION 6
+#define BLENDER_FILE_SUBVERSION 3
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and show a warning if the file
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index bce15349880..467d74b17da 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -130,9 +130,9 @@ bool BKE_collection_object_add(struct Main *bmain,
struct Collection *collection,
struct Object *ob);
/**
- * Same as #BKE_collection_object_add, but uncondionnaly adds the object to the given collection.
+ * Same as #BKE_collection_object_add, but unconditionally adds the object to the given collection.
*
- * NOTE: required in certain cases, like do-versionning or complex ID management tasks.
+ * NOTE: required in certain cases, like do-versioning or complex ID management tasks.
*/
bool BKE_collection_object_add_notest(struct Main *bmain,
struct Collection *collection,
diff --git a/source/blender/blenkernel/BKE_constraint.h b/source/blender/blenkernel/BKE_constraint.h
index 55e5cd0a149..2da79e27576 100644
--- a/source/blender/blenkernel/BKE_constraint.h
+++ b/source/blender/blenkernel/BKE_constraint.h
@@ -278,18 +278,6 @@ bool BKE_constraint_apply_and_remove_for_pose(struct Depsgraph *depsgraph,
void BKE_constraint_panel_expand(struct bConstraint *con);
-/* Constraints + Proxies function prototypes */
-
-/**
- * Rescue all constraints tagged as being #CONSTRAINT_PROXY_LOCAL
- * (i.e. added to bone that's proxy-synced in this file).
- */
-void BKE_constraints_proxylocal_extract(struct ListBase *dst, struct ListBase *src);
-/**
- * Returns if the owner of the constraint is proxy-protected.
- */
-bool BKE_constraints_proxylocked_owner(struct Object *ob, struct bPoseChannel *pchan);
-
/* Constraint Evaluation function prototypes */
/**
diff --git a/source/blender/blenkernel/BKE_curves.h b/source/blender/blenkernel/BKE_curves.h
new file mode 100644
index 00000000000..99839b20121
--- /dev/null
+++ b/source/blender/blenkernel/BKE_curves.h
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+/** \file
+ * \ingroup bke
+ * \brief Low-level operations for curves.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct BoundBox;
+struct CustomDataLayer;
+struct Depsgraph;
+struct Curves;
+struct Main;
+struct Object;
+struct Scene;
+
+void *BKE_curves_add(struct Main *bmain, const char *name);
+
+struct BoundBox *BKE_curves_boundbox_get(struct Object *ob);
+
+void BKE_curves_update_customdata_pointers(struct Curves *curves);
+bool BKE_curves_customdata_required(struct Curves *curves, struct CustomDataLayer *layer);
+
+/* Depsgraph */
+
+struct Curves *BKE_curves_new_for_eval(const struct Curves *curves_src,
+ int totpoint,
+ int totcurve);
+struct Curves *BKE_curves_copy_for_eval(struct Curves *curves_src, bool reference);
+
+void BKE_curves_data_update(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *object);
+
+/* Draw Cache */
+
+enum {
+ BKE_CURVES_BATCH_DIRTY_ALL = 0,
+};
+
+void BKE_curves_batch_cache_dirty_tag(struct Curves *curves, int mode);
+void BKE_curves_batch_cache_free(struct Curves *curves);
+
+extern void (*BKE_curves_batch_cache_dirty_tag_cb)(struct Curves *curves, int mode);
+extern void (*BKE_curves_batch_cache_free_cb)(struct Curves *curves);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 885d0c2fd90..fd8996993c0 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -48,6 +48,7 @@ struct bGPDlayer;
struct bGPDlayer_Mask;
struct bGPDstroke;
struct bGPdata;
+struct GPencilUpdateCache;
#define GPENCIL_SIMPLIFY(scene) (scene->r.simplify_gpencil & SIMPLIFY_GPENCIL_ENABLE)
#define GPENCIL_SIMPLIFY_ONPLAY(playing) \
@@ -175,10 +176,28 @@ struct bGPDframe *BKE_gpencil_frame_duplicate(const struct bGPDframe *gpf_src, b
struct bGPDlayer *BKE_gpencil_layer_duplicate(const struct bGPDlayer *gpl_src,
bool dup_frames,
bool dup_strokes);
+
+/**
+ * Make a copy of a given gpencil data settings.
+ */
+void BKE_gpencil_data_copy_settings(const struct bGPdata *gpd_src, struct bGPdata *gpd_dst);
+
/**
* Make a copy of a given gpencil layer settings.
*/
void BKE_gpencil_layer_copy_settings(const struct bGPDlayer *gpl_src, struct bGPDlayer *gpl_dst);
+
+/**
+ * Make a copy of a given gpencil frame settings.
+ */
+void BKE_gpencil_frame_copy_settings(const struct bGPDframe *gpf_src, struct bGPDframe *gpf_dst);
+
+/**
+ * Make a copy of a given gpencil stroke settings.
+ */
+void BKE_gpencil_stroke_copy_settings(const struct bGPDstroke *gpf_src,
+ struct bGPDstroke *gpf_dst);
+
/**
* Make a copy of strokes between gpencil frames.
* \param gpf_src: Source grease pencil frame
@@ -675,6 +694,9 @@ extern void (*BKE_gpencil_batch_cache_free_cb)(struct bGPdata *gpd);
*/
void BKE_gpencil_frame_original_pointers_update(const struct bGPDframe *gpf_orig,
const struct bGPDframe *gpf_eval);
+
+void BKE_gpencil_layer_original_pointers_update(const struct bGPDlayer *gpl_orig,
+ const struct bGPDlayer *gpl_eval);
/**
* Update pointers of eval data to original data to keep references.
* \param ob_orig: Original grease pencil object
@@ -683,6 +705,14 @@ void BKE_gpencil_frame_original_pointers_update(const struct bGPDframe *gpf_orig
void BKE_gpencil_update_orig_pointers(const struct Object *ob_orig, const struct Object *ob_eval);
/**
+ * Update pointers of eval data to original data to keep references.
+ * \param gpd_orig: Original grease pencil data
+ * \param gpd_eval: Evaluated grease pencil data
+ */
+void BKE_gpencil_data_update_orig_pointers(const struct bGPdata *gpd_orig,
+ const struct bGPdata *gpd_eval);
+
+/**
* Get parent matrix, including layer parenting.
* \param depsgraph: Depsgraph
* \param obact: Grease pencil object
@@ -711,6 +741,10 @@ int BKE_gpencil_material_find_index_by_name_prefix(struct Object *ob, const char
void BKE_gpencil_blend_read_data(struct BlendDataReader *reader, struct bGPdata *gpd);
+bool BKE_gpencil_can_avoid_full_copy_on_write(const struct Depsgraph *depsgraph, struct bGPdata *gpd);
+
+void BKE_gpencil_update_on_write(struct bGPdata *gpd_orig, struct bGPdata *gpd_eval);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_gpencil_update_cache.h b/source/blender/blenkernel/BKE_gpencil_update_cache.h
new file mode 100644
index 00000000000..3ac78267922
--- /dev/null
+++ b/source/blender/blenkernel/BKE_gpencil_update_cache.h
@@ -0,0 +1,152 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2022, Blender Foundation
+ * This is a new part of Blender
+ */
+
+#pragma once
+
+/** \file
+ * \ingroup bke
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "BLI_sys_types.h" /* for bool */
+
+struct DLRBT_Tree;
+struct bGPdata;
+struct bGPDlayer;
+struct bGPDframe;
+struct bGPDstroke;
+struct GPencilUpdateCache;
+
+/* GPencilUpdateCache.flag */
+typedef enum eGPUpdateCacheNodeFlag {
+ /* Node is a placeholder (e.g. when only an index is needed). */
+ GP_UPDATE_NODE_NO_COPY = 0,
+ /* Copy only element, not the content. */
+ GP_UPDATE_NODE_LIGHT_COPY = 1,
+ /* Copy the element as well as all of its content. */
+ GP_UPDATE_NODE_FULL_COPY = 2,
+} eGPUpdateCacheNodeFlag;
+
+/**
+ * Cache for what needs to be updated after bGPdata was modified.
+ *
+ * Every node holds information about one element that was changed:
+ * - the index of where that element is in the linked-list
+ * - the pointer to the original element in bGPdata
+ * Additionally, nodes also hold other nodes that are one "level" below them.
+ * E.g. a node that represents a change on a bGPDframe could contain a set of
+ * nodes that represent a change on bGPDstrokes.
+ * These nodes are stored in a red-black tree so that they are sorted by their
+ * index to make sure they can be processed in the correct order.
+ */
+typedef struct GPencilUpdateCache {
+ /* Mapping from index to a GPencilUpdateCache struct. */
+ struct DLRBT_Tree *children;
+ /* eGPUpdateCacheNodeFlag */
+ int flag;
+ /* Index of the element in the linked-list. */
+ int index;
+ /* Pointer to one of bGPdata, bGPDLayer, bGPDFrame, bGPDStroke. */
+ void *data;
+} GPencilUpdateCache;
+
+/* Node structure in the DLRBT_Tree for GPencilUpdateCache mapping. */
+typedef struct GPencilUpdateCacheNode {
+ /* DLRB tree capabilities. */
+ struct GPencilUpdateCacheNode *next, *prev;
+ struct GPencilUpdateCacheNode *left, *right;
+ struct GPencilUpdateCacheNode *parent;
+ char tree_col;
+
+ char _pad[7];
+ /* Content of DLRB tree node. */
+ GPencilUpdateCache *cache;
+} GPencilUpdateCacheNode;
+
+/**
+ * Callback that is called in BKE_gpencil_traverse_update_cache at each level. If the callback
+ * returns true, then the children will not be iterated over and instead continue.
+ * \param cache: The cache at this level.
+ * \param user_data: Pointer to the user_data passed to BKE_gpencil_traverse_update_cache.
+ * \returns true, if iterating over the children of \a cache should be skipped, false if not.
+ */
+typedef bool (*GPencilUpdateCacheIter_Cb)(GPencilUpdateCache *cache, void *user_data);
+
+typedef struct GPencilUpdateCacheTraverseSettings {
+ /* Callbacks for the update cache traversal. Callback with index 0 is for layers, 1 for frames
+ * and 2 for strokes. */
+ GPencilUpdateCacheIter_Cb update_cache_cb[3];
+} GPencilUpdateCacheTraverseSettings;
+
+/**
+ * Allocates a new GPencilUpdateCache and populates it.
+ * \param data: A data pointer to populate the initial cache with.
+ * \param full_copy: If true, will mark this update cache as a full copy
+ * (GP_UPDATE_NODE_FULL_COPY). If false, it will be marked as a struct copy
+ * (GP_UPDATE_NODE_LIGHT_COPY).
+ */
+GPencilUpdateCache *BKE_gpencil_create_update_cache(void *data, bool full_copy);
+
+/**
+ * Traverses an update cache and executes callbacks at each level.
+ * \param cache: The update cache to traverse.
+ * \param ts: The traversal settings. This stores the callbacks that are called at each level.
+ * \param user_data: Custom data passed to each callback.
+ */
+void BKE_gpencil_traverse_update_cache(GPencilUpdateCache *cache,
+ GPencilUpdateCacheTraverseSettings *ts,
+ void *user_data);
+
+/**
+ * Tags an element (bGPdata, bGPDlayer, bGPDframe, or bGPDstroke) and all of its containing data to
+ * be updated in the next update-on-write operation.
+ *
+ * The function assumes that when a parameter is NULL all of the following parameters are NULL too.
+ * E.g. in order to tag a layer (gpl), the parameters would *have* to be (gpd, gpl, NULL, NULL).
+ */
+void BKE_gpencil_tag_full_update(struct bGPdata *gpd,
+ struct bGPDlayer *gpl,
+ struct bGPDframe *gpf,
+ struct bGPDstroke *gps);
+
+/**
+ * Tags an element (bGPdata, bGPDlayer, bGPDframe, or bGPDstroke) to be updated in the next
+ * update-on-write operation. This function will not update any of the containing data, only the
+ * struct itself.
+ *
+ * The function assumes that when a parameter is NULL all of the following parameters are NULL too.
+ * E.g. in order to tag a layer (gpl), the parameters would *have* to be (gpd, gpl, NULL, NULL).
+ */
+void BKE_gpencil_tag_light_update(struct bGPdata *gpd,
+ struct bGPDlayer *gpl,
+ struct bGPDframe *gpf,
+ struct bGPDstroke *gps);
+
+/**
+ * Frees the GPencilUpdateCache on the gpd->runtime. This will not free the data that the cache
+ * node might point to. It assumes that the cache does not own the data.
+ */
+void BKE_gpencil_free_update_cache(struct bGPdata *gpd);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/source/blender/blenkernel/BKE_hair.h b/source/blender/blenkernel/BKE_hair.h
deleted file mode 100644
index 403e461a9dc..00000000000
--- a/source/blender/blenkernel/BKE_hair.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-/** \file
- * \ingroup bke
- * \brief General operations for hairs.
- */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct BoundBox;
-struct CustomDataLayer;
-struct Depsgraph;
-struct Hair;
-struct Main;
-struct Object;
-struct Scene;
-
-void *BKE_hair_add(struct Main *bmain, const char *name);
-
-struct BoundBox *BKE_hair_boundbox_get(struct Object *ob);
-
-void BKE_hair_update_customdata_pointers(struct Hair *hair);
-bool BKE_hair_customdata_required(struct Hair *hair, struct CustomDataLayer *layer);
-
-/* Depsgraph */
-
-struct Hair *BKE_hair_new_for_eval(const struct Hair *hair_src, int totpoint, int totcurve);
-struct Hair *BKE_hair_copy_for_eval(struct Hair *hair_src, bool reference);
-
-void BKE_hair_data_update(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *object);
-
-/* Draw Cache */
-
-enum {
- BKE_HAIR_BATCH_DIRTY_ALL = 0,
-};
-
-void BKE_hair_batch_cache_dirty_tag(struct Hair *hair, int mode);
-void BKE_hair_batch_cache_free(struct Hair *hair);
-
-extern void (*BKE_hair_batch_cache_dirty_tag_cb)(struct Hair *hair, int mode);
-extern void (*BKE_hair_batch_cache_free_cb)(struct Hair *hair);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/source/blender/blenkernel/BKE_idtype.h b/source/blender/blenkernel/BKE_idtype.h
index df50f773a46..e9e5b183e4a 100644
--- a/source/blender/blenkernel/BKE_idtype.h
+++ b/source/blender/blenkernel/BKE_idtype.h
@@ -278,7 +278,7 @@ extern IDTypeInfo IDType_ID_PC;
extern IDTypeInfo IDType_ID_CF;
extern IDTypeInfo IDType_ID_WS;
extern IDTypeInfo IDType_ID_LP;
-extern IDTypeInfo IDType_ID_HA;
+extern IDTypeInfo IDType_ID_CV;
extern IDTypeInfo IDType_ID_PT;
extern IDTypeInfo IDType_ID_VO;
extern IDTypeInfo IDType_ID_SIM;
diff --git a/source/blender/blenkernel/BKE_image_partial_update.hh b/source/blender/blenkernel/BKE_image_partial_update.hh
index ca7c4f40593..0fc05809bbd 100644
--- a/source/blender/blenkernel/BKE_image_partial_update.hh
+++ b/source/blender/blenkernel/BKE_image_partial_update.hh
@@ -23,8 +23,8 @@
* image that are changed. These areas are organized in chunks. Changes that happen over time are
* organized in changesets.
*
- * A common usecase is to update GPUTexture for drawing where only that part is uploaded that only
- * changed.
+ * A common use case is to update #GPUTexture for drawing where only that part is uploaded that
+ * only changed.
*/
#pragma once
diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h
index ebd35cad965..daf13590ca2 100644
--- a/source/blender/blenkernel/BKE_lib_id.h
+++ b/source/blender/blenkernel/BKE_lib_id.h
@@ -376,10 +376,6 @@ enum {
/** Clear asset data (in case the ID can actually be made local, in copy case asset data is never
* copied over). */
LIB_ID_MAKELOCAL_ASSET_DATA_CLEAR = 1 << 3,
-
- /* Special type-specific options. */
- /** For Objects, do not clear the proxy pointers while making the data-block local. */
- LIB_ID_MAKELOCAL_OBJECT_NO_PROXY_CLEARING = 1 << 16,
};
/**
diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h
index 30e75259967..c81616110cc 100644
--- a/source/blender/blenkernel/BKE_lib_override.h
+++ b/source/blender/blenkernel/BKE_lib_override.h
@@ -100,8 +100,15 @@ struct ID *BKE_lib_override_library_create_from_id(struct Main *bmain,
* main. You can add more local IDs to be remapped to use new overriding ones by setting their
* LIB_TAG_DOIT tag.
*
- * \param reference_library: the library from which the linked data being overridden come from
- * (i.e. the library of the linked reference ID).
+ * \param owner_library: the library in which the overrides should be created. Besides versioning
+ * and resync code path, this should always be NULL (i.e. the local .blend file).
+ *
+ * \param id_root_reference: the linked ID that is considered as the root of the overridden
+ * hierarchy.
+ *
+ * \param id_hierarchy_root: the override ID that is the root of the hierarchy. May be NULL, in
+ * which case it is assumed that the given `id_root_reference` is tagged for override, and its
+ * newly created override will be used as hierarchy root.
*
* \param do_no_main: Create the new override data outside of Main database.
* Used for resyncing of linked overrides.
@@ -109,7 +116,9 @@ struct ID *BKE_lib_override_library_create_from_id(struct Main *bmain,
* \return \a true on success, \a false otherwise.
*/
bool BKE_lib_override_library_create_from_tag(struct Main *bmain,
- const struct Library *reference_library,
+ struct Library *owner_library,
+ const struct ID *id_root_reference,
+ struct ID *id_hierarchy_root,
bool do_no_main);
/**
* Advanced 'smart' function to create fully functional overrides.
@@ -122,16 +131,24 @@ bool BKE_lib_override_library_create_from_tag(struct Main *bmain,
*
* \param view_layer: the active view layer to search instantiated collections in, can be NULL (in
* which case \a scene's master collection children hierarchy is used instead).
+ *
+ * \param owner_library: the library in which the overrides should be created. Besides versioning
+ * and resync code path, this should always be NULL (i.e. the local .blend file).
+ *
* \param id_root: The root ID to create an override from.
+ *
* \param id_reference: Some reference ID used to do some post-processing after overrides have been
* created, may be NULL. Typically, the Empty object instantiating the linked collection we
* override, currently.
+ *
* \param r_id_root_override: if not NULL, the override generated for the given \a id_root.
+ *
* \return true if override was successfully created.
*/
bool BKE_lib_override_library_create(struct Main *bmain,
struct Scene *scene,
struct ViewLayer *view_layer,
+ struct Library *owner_library,
struct ID *id_root,
struct ID *id_reference,
struct ID **r_id_root_override);
@@ -160,6 +177,15 @@ bool BKE_lib_override_library_proxy_convert(struct Main *bmain,
*/
void BKE_lib_override_library_main_proxy_convert(struct Main *bmain,
struct BlendFileReadReport *reports);
+
+/**
+ * Find and set the 'hierarchy root' ID pointer of all library overrides in given `bmain`.
+ *
+ * NOTE: Cannot be called from `do_versions_after_linking` as this code needs a single complete
+ * Main database, not a split-by-libraries one.
+ */
+void BKE_lib_override_library_main_hierarchy_root_ensure(struct Main *bmain);
+
/**
* Advanced 'smart' function to resync, re-create fully functional overrides up-to-date with linked
* data, from an existing override hierarchy.
diff --git a/source/blender/blenkernel/BKE_lib_query.h b/source/blender/blenkernel/BKE_lib_query.h
index d853cb16b13..dd2e2a2f8e5 100644
--- a/source/blender/blenkernel/BKE_lib_query.h
+++ b/source/blender/blenkernel/BKE_lib_query.h
@@ -63,7 +63,7 @@ enum {
/**
* That ID is not really used by its owner, it's just an internal hint/helper.
- * This addresses Their Highest Ugliness the 'from' pointers: Object->from_proxy and Key->from.
+ * This marks the 'from' pointers issue, like Key->from.
* How to handle that kind of cases totally depends on what caller code is doing... */
IDWALK_CB_LOOPBACK = (1 << 4),
@@ -135,7 +135,6 @@ enum {
/** Do not process ID pointers inside embedded IDs. Needed by depsgraph processing e.g. */
IDWALK_IGNORE_EMBEDDED_ID = (1 << 3),
- IDWALK_NO_INDIRECT_PROXY_DATA_USAGE = (1 << 8), /* Ugly special case :(((( */
/** Also process internal ID pointers like `ID.newid` or `ID.orig_id`.
* WARNING: Dangerous, use with caution. */
IDWALK_DO_INTERNAL_RUNTIME_POINTERS = (1 << 9),
diff --git a/source/blender/blenkernel/BKE_lib_remap.h b/source/blender/blenkernel/BKE_lib_remap.h
index cc970342fbb..f14cd75c5c6 100644
--- a/source/blender/blenkernel/BKE_lib_remap.h
+++ b/source/blender/blenkernel/BKE_lib_remap.h
@@ -68,15 +68,6 @@ enum {
* and can cause crashes very easily!
*/
ID_REMAP_FORCE_NEVER_NULL_USAGE = 1 << 3,
- /**
- * Do not consider proxy/_group pointers of local objects as indirect usages...
- * Our oh-so-beloved proxies again...
- * Do not consider data used by local proxy object as indirect usage.
- * This is needed e.g. in reload scenario,
- * since we have to ensure remapping of Armature data of local proxy
- * is also performed. Usual nightmare...
- */
- ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE = 1 << 4,
/** Do not remap library override pointers. */
ID_REMAP_SKIP_OVERRIDE_LIBRARY = 1 << 5,
/** Don't touch the user count (use for low level actions such as swapping pointers). */
diff --git a/source/blender/blenkernel/BKE_main.h b/source/blender/blenkernel/BKE_main.h
index 4c6eb31db4b..e4f94110eb1 100644
--- a/source/blender/blenkernel/BKE_main.h
+++ b/source/blender/blenkernel/BKE_main.h
@@ -182,7 +182,11 @@ typedef struct Main {
ListBase linestyles;
ListBase cachefiles;
ListBase workspaces;
- ListBase hairs;
+ /**
+ * \note The name `hair_curves` is chosen to be different than `curves`,
+ * but they are generic curve data-blocks, not just for hair.
+ */
+ ListBase hair_curves;
ListBase pointclouds;
ListBase volumes;
ListBase simulations;
diff --git a/source/blender/blenkernel/BKE_mesh_fair.h b/source/blender/blenkernel/BKE_mesh_fair.h
index c4c1af054f0..2884de6d5c1 100644
--- a/source/blender/blenkernel/BKE_mesh_fair.h
+++ b/source/blender/blenkernel/BKE_mesh_fair.h
@@ -12,15 +12,14 @@
* 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.
- *
- * Mesh Fairing algorithm designed by Brett Fedack, used in the addon "Mesh Fairing":
- * https://github.com/fedackb/mesh-fairing.
*/
#pragma once
/** \file
* \ingroup bke
+ * Mesh Fairing algorithm designed by Brett Fedack, used in the addon "Mesh Fairing":
+ * https://github.com/fedackb/mesh-fairing.
*/
#include "BLI_utildefines.h"
diff --git a/source/blender/blenkernel/BKE_modifier.h b/source/blender/blenkernel/BKE_modifier.h
index 910b13b9b95..a05ed67063a 100644
--- a/source/blender/blenkernel/BKE_modifier.h
+++ b/source/blender/blenkernel/BKE_modifier.h
@@ -245,10 +245,6 @@ typedef struct ModifierTypeInfo {
const struct ModifierEvalContext *ctx,
struct Mesh *mesh);
- struct Hair *(*modifyHair)(struct ModifierData *md,
- const struct ModifierEvalContext *ctx,
- struct Hair *hair);
-
/**
* The modifier has to change the geometry set in-place. The geometry set can contain zero or
* more geometry components. This callback can be used by modifiers that don't work on any
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 16d8ba2e6dd..359a5662a13 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -274,6 +274,9 @@ typedef struct bNodeType {
char *label,
int maxlen);
+ /** Optional override for node class, used for drawing node header. */
+ int (*ui_class)(const struct bNode *node);
+
/** Called when the node is updated in the editor. */
void (*updatefunc)(struct bNodeTree *ntree, struct bNode *node);
/** Check and update if internal ID data has changed. */
@@ -1291,6 +1294,8 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
#define CMP_NODE_POSTERIZE 327
#define CMP_NODE_CONVERT_COLOR_SPACE 328
#define CMP_NODE_SCENE_TIME 329
+#define CMP_NODE_SEPARATE_XYZ 330
+#define CMP_NODE_COMBINE_XYZ 331
/* channel toggles */
#define CMP_CHAN_RGB 1
@@ -1298,12 +1303,13 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i
/* filter types */
#define CMP_FILT_SOFT 0
-#define CMP_FILT_SHARP 1
+#define CMP_FILT_SHARP_BOX 1
#define CMP_FILT_LAPLACE 2
#define CMP_FILT_SOBEL 3
#define CMP_FILT_PREWITT 4
#define CMP_FILT_KIRSCH 5
#define CMP_FILT_SHADOW 6
+#define CMP_FILT_SHARP_DIAMOND 7
/* scale node type, in custom1 */
#define CMP_SCALE_RELATIVE 0
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 99758f4ad78..e8ff0903b04 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -144,18 +144,6 @@ void BKE_object_link_modifiers(struct Object *ob_dst, const struct Object *ob_sr
void BKE_object_free_modifiers(struct Object *ob, int flag);
void BKE_object_free_shaderfx(struct Object *ob, int flag);
-/**
- * Proxy rule:
- * - `lib_object->proxy_from` == the one we borrow from, set temporally while object_update.
- * - `local_object->proxy` == pointer to library object, saved in files and read.
- * - `local_object->proxy_group` == pointer to collection dupli-object, saved in files and read.
- */
-void BKE_object_make_proxy(struct Main *bmain,
- struct Object *ob,
- struct Object *target,
- struct Object *cob);
-void BKE_object_copy_proxy_drivers(struct Object *ob, struct Object *target);
-
bool BKE_object_exists_check(struct Main *bmain, const struct Object *obtest);
/**
* Actual check for internal data, not context or flags.
@@ -444,8 +432,7 @@ void BKE_object_eval_constraints(struct Depsgraph *depsgraph,
struct Object *ob);
void BKE_object_eval_transform_final(struct Depsgraph *depsgraph, struct Object *ob);
-bool BKE_object_eval_proxy_copy(struct Depsgraph *depsgraph, struct Object *object);
-void BKE_object_eval_uber_transform(struct Depsgraph *depsgraph, struct Object *ob);
+void BKE_object_eval_uber_transform(struct Depsgraph *depsgraph, struct Object *object);
void BKE_object_eval_uber_data(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob);
@@ -486,12 +473,6 @@ void BKE_object_handle_data_update(struct Depsgraph *depsgraph,
*/
void BKE_object_handle_update(struct Depsgraph *depsgraph, struct Scene *scene, struct Object *ob);
/**
- * Proxy rule:
- * - lib_object->proxy_from == the one we borrow from, only set temporal and cleared here.
- * - local_object->proxy == pointer to library object, saved in files and read.
- *
- * Function below is polluted with proxy exceptions, cleanup will follow!
- *
* The main object update call, for object matrix, constraints, keys and #DispList (modifiers)
* requires flags to be set!
*
@@ -501,8 +482,7 @@ void BKE_object_handle_update(struct Depsgraph *depsgraph, struct Scene *scene,
void BKE_object_handle_update_ex(struct Depsgraph *depsgraph,
struct Scene *scene,
struct Object *ob,
- struct RigidBodyWorld *rbw,
- bool do_proxy_update);
+ struct RigidBodyWorld *rbw);
void BKE_object_sculpt_data_create(struct Object *ob);
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index 804331a3412..b5e60da540e 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -13,11 +13,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * The Original Code is Copyright (C) 2007 by Janne Karhu.
- * All rights reserved.
- * Adaptive time step
- * Classical SPH
- * Copyright 2011-2012 AutoCRC
+ * Copyright 2007 Janne Karhu. All rights reserved.
+ * 2011-2012 AutoCRC (adaptive time step, Classical SPH).
*/
#pragma once
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 1ef1c98ce83..42dfd7f14ff 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -299,6 +299,8 @@ bool BKE_pbvh_node_fully_masked_get(PBVHNode *node);
void BKE_pbvh_node_fully_unmasked_set(PBVHNode *node, int fully_masked);
bool BKE_pbvh_node_fully_unmasked_get(PBVHNode *node);
+void BKE_pbvh_vert_mark_update(PBVH *pbvh, int index);
+
void BKE_pbvh_node_get_grids(PBVH *pbvh,
PBVHNode *node,
int **grid_indices,
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index 220d4673075..1483466061f 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -119,6 +119,7 @@ set(SRC
intern/crazyspace.c
intern/cryptomatte.cc
intern/curve.cc
+ intern/curves.cc
intern/curve_bevel.c
intern/curve_convert.c
intern/curve_decimate.c
@@ -156,7 +157,7 @@ set(SRC
intern/gpencil_curve.c
intern/gpencil_geom.cc
intern/gpencil_modifier.c
- intern/hair.cc
+ intern/gpencil_update_cache.c
intern/icons.cc
intern/icons_rasterize.c
intern/idprop.c
@@ -182,6 +183,7 @@ set(SRC
intern/lib_id_eval.c
intern/lib_id_remapper.cc
intern/lib_override.c
+ intern/lib_override_proxy_conversion.c
intern/lib_query.c
intern/lib_remap.c
intern/library.c
@@ -355,6 +357,7 @@ set(SRC
BKE_cryptomatte.h
BKE_cryptomatte.hh
BKE_curve.h
+ BKE_curves.h
BKE_curve_to_mesh.hh
BKE_curveprofile.h
BKE_customdata.h
@@ -383,7 +386,7 @@ set(SRC
BKE_gpencil_curve.h
BKE_gpencil_geom.h
BKE_gpencil_modifier.h
- BKE_hair.h
+ BKE_gpencil_update_cache.h
BKE_icons.h
BKE_idprop.h
BKE_idprop.hh
@@ -719,10 +722,6 @@ if(WITH_FFTW3)
add_definitions(-DFFTW3=1)
endif()
-if(WITH_INTERNATIONAL)
- add_definitions(-DWITH_INTERNATIONAL)
-endif()
-
if(WITH_FREESTYLE)
add_definitions(-DWITH_FREESTYLE)
endif()
diff --git a/source/blender/blenkernel/intern/DerivedMesh.cc b/source/blender/blenkernel/intern/DerivedMesh.cc
index 6056b69b5c8..2e779d6fad7 100644
--- a/source/blender/blenkernel/intern/DerivedMesh.cc
+++ b/source/blender/blenkernel/intern/DerivedMesh.cc
@@ -127,30 +127,6 @@ static MEdge *dm_getEdgeArray(DerivedMesh *dm)
return medge;
}
-static MFace *dm_getTessFaceArray(DerivedMesh *dm)
-{
- MFace *mface = (MFace *)CustomData_get_layer(&dm->faceData, CD_MFACE);
-
- if (!mface) {
- int numTessFaces = dm->getNumTessFaces(dm);
-
- if (!numTessFaces) {
- /* Do not add layer if there's no elements in it, this leads to issues later when
- * this layer is needed with non-zero size, but currently CD stuff does not check
- * for requested layer size on creation and just returns layer which was previously
- * added (sergey) */
- return nullptr;
- }
-
- mface = (MFace *)CustomData_add_layer(
- &dm->faceData, CD_MFACE, CD_CALLOC, nullptr, numTessFaces);
- CustomData_set_layer_flag(&dm->faceData, CD_MFACE, CD_FLAG_TEMPORARY);
- dm->copyTessFaceArray(dm, mface);
- }
-
- return mface;
-}
-
static MLoop *dm_getLoopArray(DerivedMesh *dm)
{
MLoop *mloop = (MLoop *)CustomData_get_layer(&dm->loopData, CD_MLOOP);
@@ -203,18 +179,6 @@ static MEdge *dm_dupEdgeArray(DerivedMesh *dm)
return tmp;
}
-static MFace *dm_dupFaceArray(DerivedMesh *dm)
-{
- MFace *tmp = (MFace *)MEM_malloc_arrayN(
- dm->getNumTessFaces(dm), sizeof(*tmp), "dm_dupFaceArray tmp");
-
- if (tmp) {
- dm->copyTessFaceArray(dm, tmp);
- }
-
- return tmp;
-}
-
static MLoop *dm_dupLoopArray(DerivedMesh *dm)
{
MLoop *tmp = (MLoop *)MEM_malloc_arrayN(
@@ -270,42 +234,15 @@ static const MLoopTri *dm_getLoopTriArray(DerivedMesh *dm)
return looptri;
}
-static CustomData *dm_getVertCData(DerivedMesh *dm)
-{
- return &dm->vertData;
-}
-
-static CustomData *dm_getEdgeCData(DerivedMesh *dm)
-{
- return &dm->edgeData;
-}
-
-static CustomData *dm_getTessFaceCData(DerivedMesh *dm)
-{
- return &dm->faceData;
-}
-
-static CustomData *dm_getLoopCData(DerivedMesh *dm)
-{
- return &dm->loopData;
-}
-
-static CustomData *dm_getPolyCData(DerivedMesh *dm)
-{
- return &dm->polyData;
-}
-
void DM_init_funcs(DerivedMesh *dm)
{
/* default function implementations */
dm->getVertArray = dm_getVertArray;
dm->getEdgeArray = dm_getEdgeArray;
- dm->getTessFaceArray = dm_getTessFaceArray;
dm->getLoopArray = dm_getLoopArray;
dm->getPolyArray = dm_getPolyArray;
dm->dupVertArray = dm_dupVertArray;
dm->dupEdgeArray = dm_dupEdgeArray;
- dm->dupTessFaceArray = dm_dupFaceArray;
dm->dupLoopArray = dm_dupLoopArray;
dm->dupPolyArray = dm_dupPolyArray;
@@ -314,19 +251,8 @@ void DM_init_funcs(DerivedMesh *dm)
/* subtypes handle getting actual data */
dm->getNumLoopTri = dm_getNumLoopTri;
- dm->getVertDataLayout = dm_getVertCData;
- dm->getEdgeDataLayout = dm_getEdgeCData;
- dm->getTessFaceDataLayout = dm_getTessFaceCData;
- dm->getLoopDataLayout = dm_getLoopCData;
- dm->getPolyDataLayout = dm_getPolyCData;
-
- dm->getVertData = DM_get_vert_data;
- dm->getEdgeData = DM_get_edge_data;
- dm->getTessFaceData = DM_get_tessface_data;
- dm->getPolyData = DM_get_poly_data;
dm->getVertDataArray = DM_get_vert_data_layer;
dm->getEdgeDataArray = DM_get_edge_data_layer;
- dm->getTessFaceDataArray = DM_get_tessface_data_layer;
dm->getPolyDataArray = DM_get_poly_data_layer;
dm->getLoopDataArray = DM_get_loop_data_layer;
}
@@ -349,7 +275,6 @@ void DM_init(DerivedMesh *dm,
DM_init_funcs(dm);
dm->needsFree = 1;
- dm->dirty = (DMDirtyFlag)0;
/* Don't use #CustomData_reset because we don't want to touch custom-data. */
copy_vn_i(dm->vertData.typemap, CD_NUMTYPES, -1);
@@ -359,16 +284,16 @@ void DM_init(DerivedMesh *dm,
copy_vn_i(dm->polyData.typemap, CD_NUMTYPES, -1);
}
-void DM_from_template_ex(DerivedMesh *dm,
- DerivedMesh *source,
- DerivedMeshType type,
- int numVerts,
- int numEdges,
- int numTessFaces,
- int numLoops,
- int numPolys,
- const CustomData_MeshMasks *mask)
+void DM_from_template(DerivedMesh *dm,
+ DerivedMesh *source,
+ DerivedMeshType type,
+ int numVerts,
+ int numEdges,
+ int numTessFaces,
+ int numLoops,
+ int numPolys)
{
+ const CustomData_MeshMasks *mask = &CD_MASK_DERIVEDMESH;
CustomData_copy(&source->vertData, &dm->vertData, mask->vmask, CD_CALLOC, numVerts);
CustomData_copy(&source->edgeData, &dm->edgeData, mask->emask, CD_CALLOC, numEdges);
CustomData_copy(&source->faceData, &dm->faceData, mask->fmask, CD_CALLOC, numTessFaces);
@@ -387,26 +312,6 @@ void DM_from_template_ex(DerivedMesh *dm,
DM_init_funcs(dm);
dm->needsFree = 1;
- dm->dirty = (DMDirtyFlag)0;
-}
-void DM_from_template(DerivedMesh *dm,
- DerivedMesh *source,
- DerivedMeshType type,
- int numVerts,
- int numEdges,
- int numTessFaces,
- int numLoops,
- int numPolys)
-{
- DM_from_template_ex(dm,
- source,
- type,
- numVerts,
- numEdges,
- numTessFaces,
- numLoops,
- numPolys,
- &CD_MASK_DERIVEDMESH);
}
bool DM_release(DerivedMesh *dm)
@@ -464,14 +369,6 @@ void DM_DupPolys(DerivedMesh *source, DerivedMesh *target)
}
}
-void DM_ensure_normals(DerivedMesh *dm)
-{
- if (dm->dirty & DM_DIRTY_NORMALS) {
- dm->calcNormals(dm);
- }
- BLI_assert((dm->dirty & DM_DIRTY_NORMALS) == 0);
-}
-
void DM_ensure_looptri_data(DerivedMesh *dm)
{
const unsigned int totpoly = dm->numPolyData;
@@ -524,7 +421,7 @@ void DM_set_only_copy(DerivedMesh *dm, const CustomData_MeshMasks *mask)
* see replies to r50969, Campbell */
#if 0
CustomData_set_only_copy(&dm->loopData, mask->lmask);
- CustomData_set_only_copy(&dm->polyData, mask->pmask);
+ Custom(&dm->polyData, mask->pmask);
#endif
}
@@ -552,45 +449,11 @@ void DM_add_edge_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *
CustomData_add_layer(&dm->edgeData, type, alloctype, layer, dm->numEdgeData);
}
-void DM_add_tessface_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer)
-{
- CustomData_add_layer(&dm->faceData, type, alloctype, layer, dm->numTessFaceData);
-}
-
-void DM_add_loop_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer)
-{
- CustomData_add_layer(&dm->loopData, type, alloctype, layer, dm->numLoopData);
-}
-
void DM_add_poly_layer(DerivedMesh *dm, int type, eCDAllocType alloctype, void *layer)
{
CustomData_add_layer(&dm->polyData, type, alloctype, layer, dm->numPolyData);
}
-void *DM_get_vert_data(DerivedMesh *dm, int index, int type)
-{
- BLI_assert(index >= 0 && index < dm->getNumVerts(dm));
- return CustomData_get(&dm->vertData, index, type);
-}
-
-void *DM_get_edge_data(DerivedMesh *dm, int index, int type)
-{
- BLI_assert(index >= 0 && index < dm->getNumEdges(dm));
- return CustomData_get(&dm->edgeData, index, type);
-}
-
-void *DM_get_tessface_data(DerivedMesh *dm, int index, int type)
-{
- BLI_assert(index >= 0 && index < dm->getNumTessFaces(dm));
- return CustomData_get(&dm->faceData, index, type);
-}
-
-void *DM_get_poly_data(DerivedMesh *dm, int index, int type)
-{
- BLI_assert(index >= 0 && index < dm->getNumPolys(dm));
- return CustomData_get(&dm->polyData, index, type);
-}
-
void *DM_get_vert_data_layer(DerivedMesh *dm, int type)
{
if (type == CD_MVERT) {
@@ -609,15 +472,6 @@ void *DM_get_edge_data_layer(DerivedMesh *dm, int type)
return CustomData_get_layer(&dm->edgeData, type);
}
-void *DM_get_tessface_data_layer(DerivedMesh *dm, int type)
-{
- if (type == CD_MFACE) {
- return dm->getTessFaceArray(dm);
- }
-
- return CustomData_get_layer(&dm->faceData, type);
-}
-
void *DM_get_poly_data_layer(DerivedMesh *dm, int type)
{
return CustomData_get_layer(&dm->polyData, type);
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index fde42304185..8426f6f4676 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -1956,30 +1956,15 @@ void BKE_pose_blend_read_lib(BlendLibReader *reader, Object *ob, bPose *pose)
return;
}
- /* always rebuild to match proxy or lib changes, but on Undo */
+ /* Always rebuild to match library changes, except on Undo. */
bool rebuild = false;
if (!BLO_read_lib_is_undo(reader)) {
- if (ob->proxy || ob->id.lib != arm->id.lib) {
+ if (ob->id.lib != arm->id.lib) {
rebuild = true;
}
}
- if (ob->proxy) {
- /* sync proxy layer */
- if (pose->proxy_layer) {
- arm->layer = pose->proxy_layer;
- }
-
- /* sync proxy active bone */
- if (pose->proxy_act_bone[0]) {
- Bone *bone = BKE_armature_find_bone_name(arm, pose->proxy_act_bone);
- if (bone) {
- arm->act_bone = bone;
- }
- }
- }
-
LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) {
BKE_constraint_blend_read_lib(reader, (ID *)ob, &pchan->constraints);
diff --git a/source/blender/blenkernel/intern/anim_data.c b/source/blender/blenkernel/intern/anim_data.c
index 42b72a7cd66..1c0b465d202 100644
--- a/source/blender/blenkernel/intern/anim_data.c
+++ b/source/blender/blenkernel/intern/anim_data.c
@@ -1284,8 +1284,8 @@ void BKE_animdata_main_cb(Main *bmain, ID_AnimData_Edit_Callback func, void *use
/* cache files */
ANIMDATA_IDS_CB(bmain->cachefiles.first);
- /* hairs */
- ANIMDATA_IDS_CB(bmain->hairs.first);
+ /* Hair Curves. */
+ ANIMDATA_IDS_CB(bmain->hair_curves.first);
/* pointclouds */
ANIMDATA_IDS_CB(bmain->pointclouds.first);
@@ -1413,8 +1413,8 @@ void BKE_animdata_fix_paths_rename_all_ex(Main *bmain,
/* cache files */
RENAMEFIX_ANIM_IDS(bmain->cachefiles.first);
- /* hairs */
- RENAMEFIX_ANIM_IDS(bmain->hairs.first);
+ /* Hair Curves. */
+ RENAMEFIX_ANIM_IDS(bmain->hair_curves.first);
/* pointclouds */
RENAMEFIX_ANIM_IDS(bmain->pointclouds.first);
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index b5ea68aaadc..c45856adbda 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -3382,8 +3382,8 @@ void BKE_animsys_evaluate_all_animation(Main *main, Depsgraph *depsgraph, float
/* cache files */
EVAL_ANIM_IDS(main->cachefiles.first, ADT_RECALC_ANIM);
- /* hairs */
- EVAL_ANIM_IDS(main->hairs.first, ADT_RECALC_ANIM);
+ /* Hair Curves. */
+ EVAL_ANIM_IDS(main->hair_curves.first, ADT_RECALC_ANIM);
/* pointclouds */
EVAL_ANIM_IDS(main->pointclouds.first, ADT_RECALC_ANIM);
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 5704ef6e42f..1a9f0a9130d 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -69,8 +69,6 @@
#include "CLG_log.h"
-static CLG_LogRef LOG = {"bke.armature"};
-
/* -------------------------------------------------------------------- */
/** \name Prototypes
* \{ */
@@ -2296,161 +2294,6 @@ void BKE_armature_where_is(bArmature *arm)
/** \name Pose Rebuild
* \{ */
-/* if bone layer is protected, copy the data from from->pose
- * when used with linked libraries this copies from the linked pose into the local pose */
-static void pose_proxy_sync(Object *ob, Object *from, int layer_protected)
-{
- bPose *pose = ob->pose, *frompose = from->pose;
- bPoseChannel *pchan, *pchanp;
- bConstraint *con;
- int error = 0;
-
- if (frompose == NULL) {
- return;
- }
-
- /* in some cases when rigs change, we can't synchronize
- * to avoid crashing check for possible errors here */
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- if (pchan->bone->layer & layer_protected) {
- if (BKE_pose_channel_find_name(frompose, pchan->name) == NULL) {
- CLOG_ERROR(&LOG,
- "failed to sync proxy armature because '%s' is missing pose channel '%s'",
- from->id.name,
- pchan->name);
- error = 1;
- }
- }
- }
-
- if (error) {
- return;
- }
-
- /* clear all transformation values from library */
- BKE_pose_rest(frompose, false);
-
- /* copy over all of the proxy's bone groups */
- /* TODO: for later
- * - implement 'local' bone groups as for constraints
- * NOTE: this isn't trivial, as bones reference groups by index not by pointer,
- * so syncing things correctly needs careful attention */
- BLI_freelistN(&pose->agroups);
- BLI_duplicatelist(&pose->agroups, &frompose->agroups);
- pose->active_group = frompose->active_group;
-
- for (pchan = pose->chanbase.first; pchan; pchan = pchan->next) {
- pchanp = BKE_pose_channel_find_name(frompose, pchan->name);
-
- if (UNLIKELY(pchanp == NULL)) {
- /* happens for proxies that become invalid because of a missing link
- * for regular cases it shouldn't happen at all */
- }
- else if (pchan->bone->layer & layer_protected) {
- ListBase proxylocal_constraints = {NULL, NULL};
- bPoseChannel pchanw;
-
- /* copy posechannel to temp, but restore important pointers */
- pchanw = *pchanp;
- pchanw.bone = pchan->bone;
- pchanw.prev = pchan->prev;
- pchanw.next = pchan->next;
- pchanw.parent = pchan->parent;
- pchanw.child = pchan->child;
- pchanw.custom_tx = pchan->custom_tx;
- pchanw.bbone_prev = pchan->bbone_prev;
- pchanw.bbone_next = pchan->bbone_next;
-
- pchanw.mpath = pchan->mpath;
- pchan->mpath = NULL;
-
- /* Reset runtime data, we don't want to share that with the proxy. */
- BKE_pose_channel_runtime_reset_on_copy(&pchanw.runtime);
-
- /* this is freed so copy a copy, else undo crashes */
- if (pchanw.prop) {
- pchanw.prop = IDP_CopyProperty(pchanw.prop);
-
- /* use the values from the existing props */
- if (pchan->prop) {
- IDP_SyncGroupValues(pchanw.prop, pchan->prop);
- }
- }
-
- /* Constraints - proxy constraints are flushed... local ones are added after
- * 1: extract constraints not from proxy (CONSTRAINT_PROXY_LOCAL) from pchan's constraints.
- * 2: copy proxy-pchan's constraints on-to new.
- * 3: add extracted local constraints back on top.
- *
- * Note for BKE_constraints_copy:
- * When copying constraints, disable 'do_extern' otherwise
- * we get the libs direct linked in this blend.
- */
- BKE_constraints_proxylocal_extract(&proxylocal_constraints, &pchan->constraints);
- BKE_constraints_copy(&pchanw.constraints, &pchanp->constraints, false);
- BLI_movelisttolist(&pchanw.constraints, &proxylocal_constraints);
-
- /* constraints - set target ob pointer to own object */
- for (con = pchanw.constraints.first; con; con = con->next) {
- const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
- ListBase targets = {NULL, NULL};
- bConstraintTarget *ct;
-
- if (cti && cti->get_constraint_targets) {
- cti->get_constraint_targets(con, &targets);
-
- for (ct = targets.first; ct; ct = ct->next) {
- if (ct->tar == from) {
- ct->tar = ob;
- }
- }
-
- if (cti->flush_constraint_targets) {
- cti->flush_constraint_targets(con, &targets, 0);
- }
- }
- }
-
- /* free stuff from current channel */
- BKE_pose_channel_free(pchan);
-
- /* copy data in temp back over to the cleaned-out (but still allocated) original channel */
- *pchan = pchanw;
- if (pchan->custom) {
- id_us_plus(&pchan->custom->id);
- }
- }
- else {
- /* always copy custom shape */
- pchan->custom = pchanp->custom;
- if (pchan->custom) {
- id_us_plus(&pchan->custom->id);
- }
- if (pchanp->custom_tx) {
- pchan->custom_tx = BKE_pose_channel_find_name(pose, pchanp->custom_tx->name);
- }
-
- /* ID-Property Syncing */
- {
- IDProperty *prop_orig = pchan->prop;
- if (pchanp->prop) {
- pchan->prop = IDP_CopyProperty(pchanp->prop);
- if (prop_orig) {
- /* copy existing values across when types match */
- IDP_SyncGroupValues(pchan->prop, prop_orig);
- }
- }
- else {
- pchan->prop = NULL;
- }
- if (prop_orig) {
- IDP_FreeProperty(prop_orig);
- }
- }
- }
- }
-}
-
/**
* \param r_last_visited_bone_p: The last bone handled by the last call to this function.
*/
@@ -2579,16 +2422,6 @@ void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, const bool do_id_
// printf("rebuild pose %s, %d bones\n", ob->id.name, counter);
- /* synchronize protected layers with proxy */
- /* HACK! To preserve 2.7x behavior that you always can pose even locked bones,
- * do not do any restoration if this is a COW temp copy! */
- /* Switched back to just NO_MAIN tag, for some reasons (c)
- * using COW tag was working this morning, but not anymore... */
- if (ob->proxy != NULL && (ob->id.tag & LIB_TAG_NO_MAIN) == 0) {
- BKE_object_copy_proxy_drivers(ob, ob->proxy);
- pose_proxy_sync(ob, ob->proxy, arm->layer_protected);
- }
-
BKE_pose_update_constraint_flags(pose); /* for IK detection for example */
pose->flag &= ~POSE_RECALC;
@@ -2846,6 +2679,35 @@ BoundBox *BKE_armature_boundbox_get(Object *ob)
return ob->runtime.bb;
}
+void BKE_pchan_minmax(const Object *ob, const bPoseChannel *pchan, float r_min[3], float r_max[3])
+{
+ const bArmature *arm = ob->data;
+ const bPoseChannel *pchan_tx = (pchan->custom && pchan->custom_tx) ? pchan->custom_tx : pchan;
+ const BoundBox *bb_custom = ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) ?
+ BKE_object_boundbox_get(pchan->custom) :
+ NULL;
+ if (bb_custom) {
+ float mat[4][4], smat[4][4], rmat[4][4], tmp[4][4];
+ scale_m4_fl(smat, PCHAN_CUSTOM_BONE_LENGTH(pchan));
+ rescale_m4(smat, pchan->custom_scale_xyz);
+ eulO_to_mat4(rmat, pchan->custom_rotation_euler, ROT_MODE_XYZ);
+ copy_m4_m4(tmp, pchan_tx->pose_mat);
+ translate_m4(tmp,
+ pchan->custom_translation[0],
+ pchan->custom_translation[1],
+ pchan->custom_translation[2]);
+ mul_m4_series(mat, ob->obmat, tmp, rmat, smat);
+ BKE_boundbox_minmax(bb_custom, mat, r_min, r_max);
+ }
+ else {
+ float vec[3];
+ mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_head);
+ minmax_v3v3_v3(r_min, r_max, vec);
+ mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_tail);
+ minmax_v3v3_v3(r_min, r_max, vec);
+ }
+}
+
bool BKE_pose_minmax(Object *ob, float r_min[3], float r_max[3], bool use_hidden, bool use_select)
{
bool changed = false;
@@ -2859,31 +2721,8 @@ bool BKE_pose_minmax(Object *ob, float r_min[3], float r_max[3], bool use_hidden
* (editarmature.c:2592)... Skip in this case too! */
if (pchan->bone && (!((use_hidden == false) && (PBONE_VISIBLE(arm, pchan->bone) == false)) &&
!((use_select == true) && ((pchan->bone->flag & BONE_SELECTED) == 0)))) {
- bPoseChannel *pchan_tx = (pchan->custom && pchan->custom_tx) ? pchan->custom_tx : pchan;
- BoundBox *bb_custom = ((pchan->custom) && !(arm->flag & ARM_NO_CUSTOM)) ?
- BKE_object_boundbox_get(pchan->custom) :
- NULL;
- if (bb_custom) {
- float mat[4][4], smat[4][4], rmat[4][4], tmp[4][4];
- scale_m4_fl(smat, PCHAN_CUSTOM_BONE_LENGTH(pchan));
- rescale_m4(smat, pchan->custom_scale_xyz);
- eulO_to_mat4(rmat, pchan->custom_rotation_euler, ROT_MODE_XYZ);
- copy_m4_m4(tmp, pchan_tx->pose_mat);
- translate_m4(tmp,
- pchan->custom_translation[0],
- pchan->custom_translation[1],
- pchan->custom_translation[2]);
- mul_m4_series(mat, ob->obmat, tmp, rmat, smat);
- BKE_boundbox_minmax(bb_custom, mat, r_min, r_max);
- }
- else {
- float vec[3];
- mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_head);
- minmax_v3v3_v3(r_min, r_max, vec);
- mul_v3_m4v3(vec, ob->obmat, pchan_tx->pose_tail);
- minmax_v3v3_v3(r_min, r_max, vec);
- }
+ BKE_pchan_minmax(ob, pchan, r_min, r_max);
changed = true;
}
}
diff --git a/source/blender/blenkernel/intern/armature_pose.cc b/source/blender/blenkernel/intern/armature_pose.cc
index a62a32d9633..de26b997e76 100644
--- a/source/blender/blenkernel/intern/armature_pose.cc
+++ b/source/blender/blenkernel/intern/armature_pose.cc
@@ -15,8 +15,6 @@
*
* The Original Code is Copyright (C) 2015 Blender Foundation.
* All rights reserved.
- *
- * Defines and code for core node types
*/
/** \file
diff --git a/source/blender/blenkernel/intern/armature_update.c b/source/blender/blenkernel/intern/armature_update.c
index 05c318663e9..f19065f039b 100644
--- a/source/blender/blenkernel/intern/armature_update.c
+++ b/source/blender/blenkernel/intern/armature_update.c
@@ -15,8 +15,6 @@
*
* The Original Code is Copyright (C) 2015 Blender Foundation.
* All rights reserved.
- *
- * Defines and code for core node types
*/
/** \file
@@ -850,10 +848,6 @@ void BKE_pose_eval_init(struct Depsgraph *depsgraph, Scene *UNUSED(scene), Objec
}
BLI_assert(pose->chan_array != NULL || BLI_listbase_is_empty(&pose->chanbase));
-
- if (object->proxy != NULL) {
- object->proxy->proxy_from = object;
- }
}
void BKE_pose_eval_init_ik(struct Depsgraph *depsgraph, Scene *scene, Object *object)
@@ -1070,57 +1064,3 @@ void BKE_pose_eval_cleanup(struct Depsgraph *depsgraph, Scene *scene, Object *ob
BIK_release_tree(scene, object, ctime);
pose_eval_cleanup_common(object);
}
-
-void BKE_pose_eval_proxy_init(struct Depsgraph *depsgraph, Object *object)
-{
- BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL);
- DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
-
- BLI_assert(object->pose->chan_array != NULL || BLI_listbase_is_empty(&object->pose->chanbase));
-}
-
-void BKE_pose_eval_proxy_done(struct Depsgraph *depsgraph, Object *object)
-{
- BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL);
- DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
-}
-
-void BKE_pose_eval_proxy_cleanup(struct Depsgraph *depsgraph, Object *object)
-{
- BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL);
- DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
- pose_eval_cleanup_common(object);
-}
-
-void BKE_pose_eval_proxy_copy_bone(struct Depsgraph *depsgraph, Object *object, int pchan_index)
-{
- const bArmature *armature = (bArmature *)object->data;
- if (armature->edbo != NULL) {
- return;
- }
- BLI_assert(ID_IS_LINKED(object) && object->proxy_from != NULL);
- bPoseChannel *pchan = pose_pchan_get_indexed(object, pchan_index);
- BLI_assert(pchan != NULL);
- DEG_debug_print_eval_subdata(
- depsgraph, __func__, object->id.name, object, "pchan", pchan->name, pchan);
- /* TODO(sergey): Use indexed lookup, once it's guaranteed to be kept
- * around for the time while proxies are evaluating.
- */
-#if 0
- bPoseChannel *pchan_from = pose_pchan_get_indexed(object->proxy_from, pchan_index);
-#else
- bPoseChannel *pchan_from = BKE_pose_channel_find_name(object->proxy_from->pose, pchan->name);
-#endif
- if (pchan_from == NULL) {
- printf(
- "WARNING: Could not find bone %s in linked ID anymore... "
- "You should delete and re-generate your proxy.\n",
- pchan->name);
- return;
- }
- BKE_pose_copy_pchan_result(pchan, pchan_from);
- copy_dq_dq(&pchan->runtime.deform_dual_quat, &pchan_from->runtime.deform_dual_quat);
- BKE_pchan_bbone_segments_cache_copy(pchan, pchan_from);
-
- pose_channel_flush_to_orig_if_needed(depsgraph, object, pchan);
-}
diff --git a/source/blender/blenkernel/intern/attribute.c b/source/blender/blenkernel/intern/attribute.c
index ee8ef5e97f7..fdd84f3dfd4 100644
--- a/source/blender/blenkernel/intern/attribute.c
+++ b/source/blender/blenkernel/intern/attribute.c
@@ -15,13 +15,12 @@
*
* The Original Code is Copyright (C) 2006 Blender Foundation.
* All rights reserved.
- *
- * Implementation of generic geometry attributes management. This is built
- * on top of CustomData, which manages individual domains.
*/
/** \file
* \ingroup bke
+ * Implementation of generic geometry attributes management. This is built
+ * on top of CustomData, which manages individual domains.
*/
#include <string.h>
@@ -29,8 +28,8 @@
#include "MEM_guardedalloc.h"
#include "DNA_ID.h"
+#include "DNA_curves_types.h"
#include "DNA_customdata_types.h"
-#include "DNA_hair_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_pointcloud_types.h"
@@ -38,9 +37,9 @@
#include "BLI_string_utf8.h"
#include "BKE_attribute.h"
+#include "BKE_curves.h"
#include "BKE_customdata.h"
#include "BKE_editmesh.h"
-#include "BKE_hair.h"
#include "BKE_pointcloud.h"
#include "BKE_report.h"
@@ -88,12 +87,12 @@ static void get_domains(const ID *id, DomainInfo info[ATTR_DOMAIN_NUM])
}
break;
}
- case ID_HA: {
- Hair *hair = (Hair *)id;
- info[ATTR_DOMAIN_POINT].customdata = &hair->pdata;
- info[ATTR_DOMAIN_POINT].length = hair->totpoint;
- info[ATTR_DOMAIN_CURVE].customdata = &hair->cdata;
- info[ATTR_DOMAIN_CURVE].length = hair->totcurve;
+ case ID_CV: {
+ Curves *curves = (Curves *)id;
+ info[ATTR_DOMAIN_POINT].customdata = &curves->geometry.point_data;
+ info[ATTR_DOMAIN_POINT].length = curves->geometry.point_size;
+ info[ATTR_DOMAIN_CURVE].customdata = &curves->geometry.curve_data;
+ info[ATTR_DOMAIN_CURVE].length = curves->geometry.curve_size;
break;
}
default:
@@ -301,8 +300,8 @@ bool BKE_id_attribute_required(ID *id, CustomDataLayer *layer)
case ID_PT: {
return BKE_pointcloud_customdata_required((PointCloud *)id, layer);
}
- case ID_HA: {
- return BKE_hair_customdata_required((Hair *)id, layer);
+ case ID_CV: {
+ return BKE_curves_customdata_required((Curves *)id, layer);
}
default:
return false;
@@ -372,8 +371,8 @@ int *BKE_id_attributes_active_index_p(ID *id)
case ID_ME: {
return &((Mesh *)id)->attributes_active_index;
}
- case ID_HA: {
- return &((Hair *)id)->attributes_active_index;
+ case ID_CV: {
+ return &((Curves *)id)->attributes_active_index;
}
default:
return NULL;
diff --git a/source/blender/blenkernel/intern/attribute_access.cc b/source/blender/blenkernel/intern/attribute_access.cc
index cc43a3e26a8..68ab11a013b 100644
--- a/source/blender/blenkernel/intern/attribute_access.cc
+++ b/source/blender/blenkernel/intern/attribute_access.cc
@@ -83,6 +83,8 @@ const blender::fn::CPPType *custom_data_type_to_cpp_type(const CustomDataType ty
return &CPPType::get<ColorGeometry4f>();
case CD_PROP_BOOL:
return &CPPType::get<bool>();
+ case CD_PROP_INT8:
+ return &CPPType::get<int8_t>();
default:
return nullptr;
}
@@ -109,6 +111,9 @@ CustomDataType cpp_type_to_custom_data_type(const blender::fn::CPPType &type)
if (type.is<bool>()) {
return CD_PROP_BOOL;
}
+ if (type.is<int8_t>()) {
+ return CD_PROP_INT8;
+ }
return static_cast<CustomDataType>(-1);
}
@@ -117,16 +122,18 @@ static int attribute_data_type_complexity(const CustomDataType data_type)
switch (data_type) {
case CD_PROP_BOOL:
return 0;
- case CD_PROP_INT32:
+ case CD_PROP_INT8:
return 1;
- case CD_PROP_FLOAT:
+ case CD_PROP_INT32:
return 2;
- case CD_PROP_FLOAT2:
+ case CD_PROP_FLOAT:
return 3;
- case CD_PROP_FLOAT3:
+ case CD_PROP_FLOAT2:
return 4;
- case CD_PROP_COLOR:
+ case CD_PROP_FLOAT3:
return 5;
+ case CD_PROP_COLOR:
+ return 6;
#if 0 /* These attribute types are not supported yet. */
case CD_MLOOPCOL:
return 3;
diff --git a/source/blender/blenkernel/intern/attribute_access_intern.hh b/source/blender/blenkernel/intern/attribute_access_intern.hh
index 2cd128081eb..5341266e182 100644
--- a/source/blender/blenkernel/intern/attribute_access_intern.hh
+++ b/source/blender/blenkernel/intern/attribute_access_intern.hh
@@ -140,7 +140,8 @@ class CustomDataAttributeProvider final : public DynamicAttributesProvider {
private:
static constexpr uint64_t supported_types_mask = CD_MASK_PROP_FLOAT | CD_MASK_PROP_FLOAT2 |
CD_MASK_PROP_FLOAT3 | CD_MASK_PROP_INT32 |
- CD_MASK_PROP_COLOR | CD_MASK_PROP_BOOL;
+ CD_MASK_PROP_COLOR | CD_MASK_PROP_BOOL |
+ CD_MASK_PROP_INT8;
const AttributeDomain domain_;
const CustomDataAccessInfo custom_data_access_;
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index 53c9fe49fb7..07fd859765a 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -78,6 +78,23 @@
/** \name High Level `.blend` file read/write.
* \{ */
+static bool blendfile_or_libraries_versions_atleast(Main *bmain,
+ const short versionfile,
+ const short subversionfile)
+{
+ if (!MAIN_VERSION_ATLEAST(bmain, versionfile, subversionfile)) {
+ return false;
+ }
+
+ LISTBASE_FOREACH (Library *, library, &bmain->libraries) {
+ if (!MAIN_VERSION_ATLEAST(library, versionfile, subversionfile)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
static bool foreach_path_clean_cb(BPathForeachPathData *UNUSED(bpath_data),
char *path_dst,
const char *path_src)
@@ -349,13 +366,18 @@ static void setup_app_data(bContext *C,
do_versions_ipos_to_animato(bmain);
}
- /* FIXME: Same as above, readfile's `do_version` do not allow to create new IDs. */
- /* TODO: Once this is definitively validated for 3.0 and option to not do it is removed, add a
- * version bump and check here. */
- if (mode != LOAD_UNDO && !USER_EXPERIMENTAL_TEST(&U, no_proxy_to_override_conversion)) {
+ /* NOTE: readfile's `do_version` does not allow to create new IDs, and only operates on a single
+ * library at a time. This code needs to operate on the whole Main at once. */
+ /* NOTE: Check bmain version (i.e. current blend file version), AND the versions of all the
+ * linked libraries. */
+ if (mode != LOAD_UNDO && !blendfile_or_libraries_versions_atleast(bmain, 302, 1)) {
BKE_lib_override_library_main_proxy_convert(bmain, reports);
}
+ if (mode != LOAD_UNDO && !blendfile_or_libraries_versions_atleast(bmain, 302, 3)) {
+ BKE_lib_override_library_main_hierarchy_root_ensure(bmain);
+ }
+
bmain->recovered = 0;
/* startup.blend or recovered startup */
diff --git a/source/blender/blenkernel/intern/blendfile_link_append.c b/source/blender/blenkernel/intern/blendfile_link_append.c
index 9b3f4c2fae8..025d16007d8 100644
--- a/source/blender/blenkernel/intern/blendfile_link_append.c
+++ b/source/blender/blenkernel/intern/blendfile_link_append.c
@@ -993,6 +993,27 @@ static int foreach_libblock_link_append_callback(LibraryIDLinkCallbackData *cb_d
/** \name Library link/append code.
* \{ */
+static void blendfile_link_append_proxies_convert(Main *bmain, ReportList *reports)
+{
+ /* NOTE: Do not bother checking file versions here, if there are no proxies to convert this code
+ * is quite fast anyway. */
+
+ BlendFileReadReport bf_reports = {.reports = reports};
+ BKE_lib_override_library_main_proxy_convert(bmain, &bf_reports);
+
+ if (bf_reports.count.proxies_to_lib_overrides_success != 0 ||
+ bf_reports.count.proxies_to_lib_overrides_failures != 0) {
+ BKE_reportf(
+ bf_reports.reports,
+ RPT_WARNING,
+ "Proxies have been removed from Blender (%d proxies were automatically converted "
+ "to library overrides, %d proxies could not be converted and were cleared). "
+ "Please consider re-saving any library .blend file with the newest Blender version.",
+ bf_reports.count.proxies_to_lib_overrides_success,
+ bf_reports.count.proxies_to_lib_overrides_failures);
+ }
+}
+
void BKE_blendfile_append(BlendfileLinkAppendContext *lapp_context, ReportList *reports)
{
if (lapp_context->num_items == 0) {
@@ -1040,10 +1061,6 @@ void BKE_blendfile_append(BlendfileLinkAppendContext *lapp_context, ReportList *
if (item->action != LINK_APPEND_ACT_UNSET) {
/* Already set, pass. */
}
- if (GS(id->name) == ID_OB && ((Object *)id)->proxy_from != NULL) {
- CLOG_INFO(&LOG, 3, "Appended ID '%s' is proxified, keeping it linked...", id->name);
- item->action = LINK_APPEND_ACT_KEEP_LINKED;
- }
else if (do_reuse_local_id && existing_local_id != NULL) {
CLOG_INFO(&LOG, 3, "Appended ID '%s' as a matching local one, re-using it...", id->name);
item->action = LINK_APPEND_ACT_REUSE_LOCAL;
@@ -1098,10 +1115,7 @@ void BKE_blendfile_append(BlendfileLinkAppendContext *lapp_context, ReportList *
local_appended_new_id = id->newid;
break;
case LINK_APPEND_ACT_MAKE_LOCAL:
- BKE_lib_id_make_local(bmain,
- id,
- make_local_common_flags | LIB_ID_MAKELOCAL_FORCE_LOCAL |
- LIB_ID_MAKELOCAL_OBJECT_NO_PROXY_CLEARING);
+ BKE_lib_id_make_local(bmain, id, make_local_common_flags | LIB_ID_MAKELOCAL_FORCE_LOCAL);
BLI_assert(id->newid == NULL);
local_appended_new_id = id;
break;
@@ -1210,55 +1224,11 @@ void BKE_blendfile_append(BlendfileLinkAppendContext *lapp_context, ReportList *
continue;
}
BLI_assert(ID_IS_LINKED(id));
-
- /* Attempt to re-link copied proxy objects. This allows appending of an entire scene
- * from another blend file into this one, even when that blend file contains proxified
- * armatures that have local references. Since the proxified object needs to be linked
- * (not local), this will only work when the "Localize all" checkbox is disabled.
- * TL;DR: this is a dirty hack on top of an already weak feature (proxies). */
- if (GS(id->name) == ID_OB && ((Object *)id)->proxy != NULL) {
- Object *ob = (Object *)id;
- Object *ob_new = (Object *)id->newid;
- bool is_local = false, is_lib = false;
-
- /* Proxies only work when the proxified object is linked-in from a library. */
- if (!ID_IS_LINKED(ob->proxy)) {
- CLOG_WARN(&LOG,
- "Proxy object %s will lose its link to %s, because the "
- "proxified object is local",
- id->newid->name,
- ob->proxy->id.name);
- continue;
- }
-
- BKE_library_ID_test_usages(bmain, id, &is_local, &is_lib);
-
- /* We can only switch the proxy'ing to a made-local proxy if it is no longer
- * referred to from a library. Not checking for local use; if new local proxy
- * was not used locally would be a nasty bug! */
- if (is_local || is_lib) {
- CLOG_WARN(&LOG,
- "Made-local proxy object %s will lose its link to %s, "
- "because the linked-in proxy is referenced (is_local=%i, is_lib=%i)",
- id->newid->name,
- ob->proxy->id.name,
- is_local,
- is_lib);
- }
- else {
- /* we can switch the proxy'ing from the linked-in to the made-local proxy.
- * BKE_object_make_proxy() shouldn't be used here, as it allocates memory that
- * was already allocated by object_make_local() (which called BKE_object_copy). */
- ob_new->proxy = ob->proxy;
- ob_new->proxy_group = ob->proxy_group;
- ob_new->proxy_from = ob->proxy_from;
- ob_new->proxy->proxy_from = ob_new;
- ob->proxy = ob->proxy_from = ob->proxy_group = NULL;
- }
- }
}
BKE_main_id_newptr_and_tag_clear(bmain);
+
+ blendfile_link_append_proxies_convert(bmain, reports);
}
void BKE_blendfile_link(BlendfileLinkAppendContext *lapp_context, ReportList *reports)
@@ -1361,6 +1331,10 @@ void BKE_blendfile_link(BlendfileLinkAppendContext *lapp_context, ReportList *re
.active_collection = NULL};
loose_data_instantiate(&instantiate_context);
}
+
+ if ((lapp_context->params->flag & FILE_LINK) != 0) {
+ blendfile_link_append_proxies_convert(lapp_context->params->bmain, reports);
+ }
}
/** \} */
@@ -1541,7 +1515,6 @@ void BKE_blendfile_library_relocate(BlendfileLinkAppendContext *lapp_context,
/* Note that in reload case, we also want to replace indirect usages. */
const short remap_flags = ID_REMAP_SKIP_NEVER_NULL_USAGE |
- ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE |
(do_reload ? 0 : ID_REMAP_SKIP_INDIRECT_USAGE);
for (item_idx = 0, itemlink = lapp_context->items.list; itemlink;
item_idx++, itemlink = itemlink->next) {
diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c
index a4f3e84a2bf..d8ad4dd89e4 100644
--- a/source/blender/blenkernel/intern/cdderivedmesh.c
+++ b/source/blender/blenkernel/intern/cdderivedmesh.c
@@ -15,13 +15,12 @@
*
* The Original Code is Copyright (C) 2006 Blender Foundation.
* All rights reserved.
- * Implementation of CDDerivedMesh.
- *
- * BKE_cdderivedmesh.h contains the function prototypes for this file.
*/
/** \file
* \ingroup bke
+ * Implementation of #CDDerivedMesh.
+ * BKE_cdderivedmesh.h contains the function prototypes for this file.
*/
#include "atomic_ops.h"
@@ -116,12 +115,6 @@ static void cdDM_copyEdgeArray(DerivedMesh *dm, MEdge *r_edge)
memcpy(r_edge, cddm->medge, sizeof(*r_edge) * dm->numEdgeData);
}
-static void cdDM_copyTessFaceArray(DerivedMesh *dm, MFace *r_face)
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
- memcpy(r_face, cddm->mface, sizeof(*r_face) * dm->numTessFaceData);
-}
-
static void cdDM_copyLoopArray(DerivedMesh *dm, MLoop *r_loop)
{
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
@@ -147,20 +140,6 @@ static void cdDM_getVertNo(DerivedMesh *dm, int index, float r_no[3])
copy_v3_v3(r_no, cddm->vert_normals[index]);
}
-static const MeshElemMap *cdDM_getPolyMap(Object *ob, DerivedMesh *dm)
-{
- CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
-
- if (!cddm->pmap && ob->type == OB_MESH) {
- Mesh *me = ob->data;
-
- BKE_mesh_vert_poly_map_create(
- &cddm->pmap, &cddm->pmap_mem, me->mpoly, me->mloop, me->totvert, me->totpoly, me->totloop);
- }
-
- return cddm->pmap;
-}
-
static void cdDM_recalc_looptri(DerivedMesh *dm)
{
CDDerivedMesh *cddm = (CDDerivedMesh *)dm;
@@ -216,24 +195,17 @@ static CDDerivedMesh *cdDM_create(const char *desc)
dm->copyVertArray = cdDM_copyVertArray;
dm->copyEdgeArray = cdDM_copyEdgeArray;
- dm->copyTessFaceArray = cdDM_copyTessFaceArray;
dm->copyLoopArray = cdDM_copyLoopArray;
dm->copyPolyArray = cdDM_copyPolyArray;
- dm->getVertData = DM_get_vert_data;
- dm->getEdgeData = DM_get_edge_data;
- dm->getTessFaceData = DM_get_tessface_data;
dm->getVertDataArray = DM_get_vert_data_layer;
dm->getEdgeDataArray = DM_get_edge_data_layer;
- dm->getTessFaceDataArray = DM_get_tessface_data_layer;
dm->recalcLoopTri = cdDM_recalc_looptri;
dm->getVertCo = cdDM_getVertCo;
dm->getVertNo = cdDM_getVertNo;
- dm->getPolyMap = cdDM_getPolyMap;
-
dm->release = cdDM_release;
return cddm;
@@ -265,12 +237,6 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
dm->deformedOnly = 1;
dm->cd_flag = mesh->cd_flag;
- if (mesh->runtime.cd_dirty_vert & CD_MASK_NORMAL) {
- dm->dirty |= DM_DIRTY_NORMALS;
- }
- /* TODO: DM_DIRTY_TESS_CDLAYERS ? Maybe not though,
- * since we probably want to switch to looptris? */
-
CustomData_merge(&mesh->vdata, &dm->vertData, cddata_masks.vmask, alloctype, mesh->totvert);
CustomData_merge(&mesh->edata, &dm->edgeData, cddata_masks.emask, alloctype, mesh->totedge);
CustomData_merge(&mesh->fdata,
@@ -282,7 +248,9 @@ static DerivedMesh *cdDM_from_mesh_ex(Mesh *mesh,
CustomData_merge(&mesh->pdata, &dm->polyData, cddata_masks.pmask, alloctype, mesh->totpoly);
cddm->mvert = CustomData_get_layer(&dm->vertData, CD_MVERT);
- cddm->vert_normals = CustomData_get_layer(&dm->vertData, CD_NORMAL);
+ /* Though this may be an unnecessary calculation, simply retrieving the layer may return nothing
+ * or dirty normals. */
+ cddm->vert_normals = BKE_mesh_vertex_normals_ensure(mesh);
cddm->medge = CustomData_get_layer(&dm->edgeData, CD_MEDGE);
cddm->mloop = CustomData_get_layer(&dm->loopData, CD_MLOOP);
cddm->mpoly = CustomData_get_layer(&dm->polyData, CD_MPOLY);
@@ -327,12 +295,6 @@ DerivedMesh *CDDM_copy(DerivedMesh *source)
DM_from_template(dm, source, DM_TYPE_CDDM, numVerts, numEdges, numTessFaces, numLoops, numPolys);
dm->deformedOnly = source->deformedOnly;
dm->cd_flag = source->cd_flag;
- dm->dirty = source->dirty;
-
- /* Tessellation data is never copied, so tag it here.
- * Only tag dirty layers if we really ignored tessellation faces.
- */
- dm->dirty |= DM_DIRTY_TESS_CDLAYERS;
CustomData_copy_data(&source->vertData, &dm->vertData, 0, 0, numVerts);
CustomData_copy_data(&source->edgeData, &dm->edgeData, 0, 0, numEdges);
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index f013ef99dde..3b7f91b93c0 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -5850,14 +5850,6 @@ static void add_new_constraint_to_list(Object *ob, bPoseChannel *pchan, bConstra
BLI_addtail(list, con);
BKE_constraint_unique_name(con, list);
- /* if the target list is a list on some PoseChannel belonging to a proxy-protected
- * Armature layer, we must tag newly added constraints with a flag which allows them
- * to persist after proxy syncing has been done
- */
- if (BKE_constraints_proxylocked_owner(ob, pchan)) {
- con->flag |= CONSTRAINT_PROXY_LOCAL;
- }
-
/* make this constraint the active one */
BKE_constraints_active_set(list, con);
}
@@ -6213,45 +6205,6 @@ bool BKE_constraint_is_nonlocal_in_liboverride(const Object *ob, const bConstrai
(con == NULL || (con->flag & CONSTRAINT_OVERRIDE_LIBRARY_LOCAL) == 0));
}
-/* -------- Constraints and Proxies ------- */
-
-void BKE_constraints_proxylocal_extract(ListBase *dst, ListBase *src)
-{
- bConstraint *con, *next;
-
- /* for each tagged constraint, remove from src and move to dst */
- for (con = src->first; con; con = next) {
- next = con->next;
-
- /* check if tagged */
- if (con->flag & CONSTRAINT_PROXY_LOCAL) {
- BLI_remlink(src, con);
- BLI_addtail(dst, con);
- }
- }
-}
-
-bool BKE_constraints_proxylocked_owner(Object *ob, bPoseChannel *pchan)
-{
- /* Currently, constraints can only be on object or bone level */
- if (ob && ob->proxy) {
- if (ob->pose && pchan) {
- bArmature *arm = ob->data;
-
- /* On bone-level, check if bone is on proxy-protected layer */
- if ((pchan->bone) && (pchan->bone->layer & arm->layer_protected)) {
- return true;
- }
- }
- else {
- /* FIXME: constraints on object-level are not handled well yet */
- return true;
- }
- }
-
- return false;
-}
-
/* -------- Target-Matrix Stuff ------- */
void BKE_constraint_target_matrix_get(struct Depsgraph *depsgraph,
diff --git a/source/blender/blenkernel/intern/crazyspace.c b/source/blender/blenkernel/intern/crazyspace.c
index 573595b6f90..0bf83ed5036 100644
--- a/source/blender/blenkernel/intern/crazyspace.c
+++ b/source/blender/blenkernel/intern/crazyspace.c
@@ -194,13 +194,10 @@ void BKE_crazyspace_set_quats_mesh(Mesh *me,
float (*mappedcos)[3],
float (*quats)[4])
{
- MVert *mvert = me->mvert;
- for (int i = 0; i < me->totvert; i++, mvert++) {
- mvert->flag &= ~ME_VERT_TMP_TAG;
- }
+ BLI_bitmap *vert_tag = BLI_BITMAP_NEW(me->totvert, __func__);
/* first store two sets of tangent vectors in vertices, we derive it just from the face-edges */
- mvert = me->mvert;
+ MVert *mvert = me->mvert;
MPoly *mp = me->mpoly;
MLoop *mloop = me->mloop;
@@ -210,7 +207,7 @@ void BKE_crazyspace_set_quats_mesh(Mesh *me,
MLoop *ml_prev = &ml_next[mp->totloop - 2];
for (int j = 0; j < mp->totloop; j++) {
- if ((mvert[ml_curr->v].flag & ME_VERT_TMP_TAG) == 0) {
+ if (!BLI_BITMAP_TEST(vert_tag, ml_curr->v)) {
const float *co_prev, *co_curr, *co_next; /* orig */
const float *vd_prev, *vd_curr, *vd_next; /* deform */
@@ -233,7 +230,7 @@ void BKE_crazyspace_set_quats_mesh(Mesh *me,
set_crazy_vertex_quat(
quats[ml_curr->v], co_curr, co_next, co_prev, vd_curr, vd_next, vd_prev);
- mvert[ml_curr->v].flag |= ME_VERT_TMP_TAG;
+ BLI_BITMAP_ENABLE(vert_tag, ml_curr->v);
}
ml_prev = ml_curr;
@@ -241,6 +238,8 @@ void BKE_crazyspace_set_quats_mesh(Mesh *me,
ml_next++;
}
}
+
+ MEM_freeN(vert_tag);
}
int BKE_crazyspace_get_first_deform_matrices_editbmesh(struct Depsgraph *depsgraph,
diff --git a/source/blender/blenkernel/intern/curves.cc b/source/blender/blenkernel/intern/curves.cc
new file mode 100644
index 00000000000..819f1551427
--- /dev/null
+++ b/source/blender/blenkernel/intern/curves.cc
@@ -0,0 +1,473 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include <cmath>
+#include <cstring>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_curves_types.h"
+#include "DNA_defaults.h"
+#include "DNA_material_types.h"
+#include "DNA_object_types.h"
+
+#include "BLI_index_range.hh"
+#include "BLI_listbase.h"
+#include "BLI_math_base.h"
+#include "BLI_math_vec_types.hh"
+#include "BLI_rand.hh"
+#include "BLI_string.h"
+#include "BLI_utildefines.h"
+
+#include "BKE_anim_data.h"
+#include "BKE_curves.h"
+#include "BKE_customdata.h"
+#include "BKE_global.h"
+#include "BKE_idtype.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_query.h"
+#include "BKE_lib_remap.h"
+#include "BKE_main.h"
+#include "BKE_modifier.h"
+#include "BKE_object.h"
+
+#include "BLT_translation.h"
+
+#include "DEG_depsgraph_query.h"
+
+#include "BLO_read_write.h"
+
+using blender::float3;
+using blender::IndexRange;
+using blender::MutableSpan;
+using blender::RandomNumberGenerator;
+
+static const char *ATTR_POSITION = "position";
+static const char *ATTR_RADIUS = "radius";
+
+static void curves_random(Curves *curves);
+
+static void curves_init_data(ID *id)
+{
+ Curves *curves = (Curves *)id;
+ BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(curves, id));
+
+ MEMCPY_STRUCT_AFTER(curves, DNA_struct_default_get(Curves), id);
+
+ CustomData_reset(&curves->geometry.point_data);
+ CustomData_reset(&curves->geometry.curve_data);
+
+ CustomData_add_layer_named(&curves->geometry.point_data,
+ CD_PROP_FLOAT3,
+ CD_CALLOC,
+ nullptr,
+ curves->geometry.point_size,
+ ATTR_POSITION);
+ CustomData_add_layer_named(&curves->geometry.point_data,
+ CD_PROP_FLOAT,
+ CD_CALLOC,
+ nullptr,
+ curves->geometry.point_size,
+ ATTR_RADIUS);
+
+ BKE_curves_update_customdata_pointers(curves);
+
+ curves_random(curves);
+}
+
+static void curves_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag)
+{
+ Curves *curves_dst = (Curves *)id_dst;
+ const Curves *curves_src = (const Curves *)id_src;
+ curves_dst->mat = static_cast<Material **>(MEM_dupallocN(curves_src->mat));
+
+ curves_dst->geometry.point_size = curves_src->geometry.point_size;
+ curves_dst->geometry.curve_size = curves_src->geometry.curve_size;
+
+ const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
+ CustomData_copy(&curves_src->geometry.point_data,
+ &curves_dst->geometry.point_data,
+ CD_MASK_ALL,
+ alloc_type,
+ curves_dst->geometry.point_size);
+ CustomData_copy(&curves_src->geometry.curve_data,
+ &curves_dst->geometry.curve_data,
+ CD_MASK_ALL,
+ alloc_type,
+ curves_dst->geometry.curve_size);
+ BKE_curves_update_customdata_pointers(curves_dst);
+
+ curves_dst->geometry.offsets = static_cast<int *>(MEM_dupallocN(curves_src->geometry.offsets));
+
+ curves_dst->batch_cache = nullptr;
+}
+
+static void curves_free_data(ID *id)
+{
+ Curves *curves = (Curves *)id;
+ BKE_animdata_free(&curves->id, false);
+
+ BKE_curves_batch_cache_free(curves);
+
+ CustomData_free(&curves->geometry.point_data, curves->geometry.point_size);
+ CustomData_free(&curves->geometry.curve_data, curves->geometry.curve_size);
+
+ MEM_SAFE_FREE(curves->geometry.offsets);
+
+ MEM_SAFE_FREE(curves->mat);
+}
+
+static void curves_foreach_id(ID *id, LibraryForeachIDData *data)
+{
+ Curves *curves = (Curves *)id;
+ for (int i = 0; i < curves->totcol; i++) {
+ BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, curves->mat[i], IDWALK_CB_USER);
+ }
+}
+
+static void curves_blend_write(BlendWriter *writer, ID *id, const void *id_address)
+{
+ Curves *curves = (Curves *)id;
+
+ CustomDataLayer *players = nullptr, players_buff[CD_TEMP_CHUNK_SIZE];
+ CustomDataLayer *clayers = nullptr, clayers_buff[CD_TEMP_CHUNK_SIZE];
+ CustomData_blend_write_prepare(
+ &curves->geometry.point_data, &players, players_buff, ARRAY_SIZE(players_buff));
+ CustomData_blend_write_prepare(
+ &curves->geometry.curve_data, &clayers, clayers_buff, ARRAY_SIZE(clayers_buff));
+
+ /* Write LibData */
+ BLO_write_id_struct(writer, Curves, id_address, &curves->id);
+ BKE_id_blend_write(writer, &curves->id);
+
+ /* Direct data */
+ CustomData_blend_write(writer,
+ &curves->geometry.point_data,
+ players,
+ curves->geometry.point_size,
+ CD_MASK_ALL,
+ &curves->id);
+ CustomData_blend_write(writer,
+ &curves->geometry.curve_data,
+ clayers,
+ curves->geometry.curve_size,
+ CD_MASK_ALL,
+ &curves->id);
+
+ BLO_write_int32_array(writer, curves->geometry.curve_size + 1, curves->geometry.offsets);
+
+ BLO_write_pointer_array(writer, curves->totcol, curves->mat);
+ if (curves->adt) {
+ BKE_animdata_blend_write(writer, curves->adt);
+ }
+
+ /* Remove temporary data. */
+ if (players && players != players_buff) {
+ MEM_freeN(players);
+ }
+ if (clayers && clayers != clayers_buff) {
+ MEM_freeN(clayers);
+ }
+}
+
+static void curves_blend_read_data(BlendDataReader *reader, ID *id)
+{
+ Curves *curves = (Curves *)id;
+ BLO_read_data_address(reader, &curves->adt);
+ BKE_animdata_blend_read_data(reader, curves->adt);
+
+ /* Geometry */
+ CustomData_blend_read(reader, &curves->geometry.point_data, curves->geometry.point_size);
+ CustomData_blend_read(reader, &curves->geometry.curve_data, curves->geometry.curve_size);
+ BKE_curves_update_customdata_pointers(curves);
+
+ BLO_read_int32_array(reader, curves->geometry.curve_size + 1, &curves->geometry.offsets);
+
+ /* Materials */
+ BLO_read_pointer_array(reader, (void **)&curves->mat);
+}
+
+static void curves_blend_read_lib(BlendLibReader *reader, ID *id)
+{
+ Curves *curves = (Curves *)id;
+ for (int a = 0; a < curves->totcol; a++) {
+ BLO_read_id_address(reader, curves->id.lib, &curves->mat[a]);
+ }
+}
+
+static void curves_blend_read_expand(BlendExpander *expander, ID *id)
+{
+ Curves *curves = (Curves *)id;
+ for (int a = 0; a < curves->totcol; a++) {
+ BLO_expand(expander, curves->mat[a]);
+ }
+}
+
+IDTypeInfo IDType_ID_CV = {
+ /*id_code */ ID_CV,
+ /*id_filter */ FILTER_ID_CV,
+ /*main_listbase_index */ INDEX_ID_CV,
+ /*struct_size */ sizeof(Curves),
+ /*name */ "Hair Curves",
+ /*name_plural */ "Hair Curves",
+ /*translation_context */ BLT_I18NCONTEXT_ID_CURVES,
+ /*flags */ IDTYPE_FLAGS_APPEND_IS_REUSABLE,
+ /*asset_type_info */ nullptr,
+
+ /*init_data */ curves_init_data,
+ /*copy_data */ curves_copy_data,
+ /*free_data */ curves_free_data,
+ /*make_local */ nullptr,
+ /*foreach_id */ curves_foreach_id,
+ /*foreach_cache */ nullptr,
+ /*foreach_path */ nullptr,
+ /*owner_get */ nullptr,
+
+ /*blend_write */ curves_blend_write,
+ /*blend_read_data */ curves_blend_read_data,
+ /*blend_read_lib */ curves_blend_read_lib,
+ /*blend_read_expand */ curves_blend_read_expand,
+
+ /*blend_read_undo_preserve */ nullptr,
+
+ /*lib_override_apply_post */ nullptr,
+};
+
+static void curves_random(Curves *curves)
+{
+ CurvesGeometry &geometry = curves->geometry;
+ const int numpoints = 8;
+
+ geometry.curve_size = 500;
+
+ geometry.curve_size = 500;
+ geometry.point_size = geometry.curve_size * numpoints;
+
+ curves->geometry.offsets = (int *)MEM_calloc_arrayN(
+ curves->geometry.curve_size + 1, sizeof(int), __func__);
+ CustomData_realloc(&geometry.point_data, geometry.point_size);
+ CustomData_realloc(&geometry.curve_data, geometry.curve_size);
+ BKE_curves_update_customdata_pointers(curves);
+
+ MutableSpan<int> offsets{geometry.offsets, geometry.curve_size + 1};
+ MutableSpan<float3> positions{(float3 *)geometry.position, geometry.point_size};
+ MutableSpan<float> radii{geometry.radius, geometry.point_size};
+
+ for (const int i : offsets.index_range()) {
+ geometry.offsets[i] = numpoints * i;
+ }
+
+ RandomNumberGenerator rng;
+
+ for (int i = 0; i < geometry.curve_size; i++) {
+ const IndexRange curve_range(offsets[i], offsets[i + 1] - offsets[i]);
+ MutableSpan<float3> curve_positions = positions.slice(curve_range);
+ MutableSpan<float> curve_radii = radii.slice(curve_range);
+
+ const float theta = 2.0f * M_PI * rng.get_float();
+ const float phi = saacosf(2.0f * rng.get_float() - 1.0f);
+
+ float3 no = {std::sin(theta) * std::sin(phi), std::cos(theta) * std::sin(phi), std::cos(phi)};
+ no = blender::math::normalize(no);
+
+ float3 co = no;
+ for (int key = 0; key < numpoints; key++) {
+ float t = key / (float)(numpoints - 1);
+ curve_positions[key] = co;
+ curve_radii[key] = 0.02f * (1.0f - t);
+
+ float3 offset = float3(rng.get_float(), rng.get_float(), rng.get_float()) * 2.0f - 1.0f;
+ co += (offset + no) / numpoints;
+ }
+ }
+}
+
+void *BKE_curves_add(Main *bmain, const char *name)
+{
+ Curves *curves = static_cast<Curves *>(BKE_id_new(bmain, ID_CV, name));
+
+ return curves;
+}
+
+BoundBox *BKE_curves_boundbox_get(Object *ob)
+{
+ BLI_assert(ob->type == OB_CURVES);
+ Curves *curves = static_cast<Curves *>(ob->data);
+
+ if (ob->runtime.bb != nullptr && (ob->runtime.bb->flag & BOUNDBOX_DIRTY) == 0) {
+ return ob->runtime.bb;
+ }
+
+ if (ob->runtime.bb == nullptr) {
+ ob->runtime.bb = MEM_cnew<BoundBox>(__func__);
+
+ float min[3], max[3];
+ INIT_MINMAX(min, max);
+
+ float(*curves_co)[3] = curves->geometry.position;
+ float *curves_radius = curves->geometry.radius;
+ for (int a = 0; a < curves->geometry.point_size; a++) {
+ float *co = curves_co[a];
+ float radius = (curves_radius) ? curves_radius[a] : 0.0f;
+ const float co_min[3] = {co[0] - radius, co[1] - radius, co[2] - radius};
+ const float co_max[3] = {co[0] + radius, co[1] + radius, co[2] + radius};
+ DO_MIN(co_min, min);
+ DO_MAX(co_max, max);
+ }
+
+ BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
+ }
+
+ return ob->runtime.bb;
+}
+
+void BKE_curves_update_customdata_pointers(Curves *curves)
+{
+ curves->geometry.position = (float(*)[3])CustomData_get_layer_named(
+ &curves->geometry.point_data, CD_PROP_FLOAT3, ATTR_POSITION);
+ curves->geometry.radius = (float *)CustomData_get_layer_named(
+ &curves->geometry.point_data, CD_PROP_FLOAT, ATTR_RADIUS);
+}
+
+bool BKE_curves_customdata_required(Curves *UNUSED(curves), CustomDataLayer *layer)
+{
+ return layer->type == CD_PROP_FLOAT3 && STREQ(layer->name, ATTR_POSITION);
+}
+
+/* Dependency Graph */
+
+Curves *BKE_curves_new_for_eval(const Curves *curves_src, int totpoint, int totcurve)
+{
+ Curves *curves_dst = static_cast<Curves *>(BKE_id_new_nomain(ID_CV, nullptr));
+
+ STRNCPY(curves_dst->id.name, curves_src->id.name);
+ curves_dst->mat = static_cast<Material **>(MEM_dupallocN(curves_src->mat));
+ curves_dst->totcol = curves_src->totcol;
+
+ curves_dst->geometry.point_size = totpoint;
+ curves_dst->geometry.curve_size = totcurve;
+ CustomData_copy(&curves_src->geometry.point_data,
+ &curves_dst->geometry.point_data,
+ CD_MASK_ALL,
+ CD_CALLOC,
+ totpoint);
+ CustomData_copy(&curves_src->geometry.curve_data,
+ &curves_dst->geometry.curve_data,
+ CD_MASK_ALL,
+ CD_CALLOC,
+ totcurve);
+ BKE_curves_update_customdata_pointers(curves_dst);
+
+ return curves_dst;
+}
+
+Curves *BKE_curves_copy_for_eval(Curves *curves_src, bool reference)
+{
+ int flags = LIB_ID_COPY_LOCALIZE;
+
+ if (reference) {
+ flags |= LIB_ID_COPY_CD_REFERENCE;
+ }
+
+ Curves *result = (Curves *)BKE_id_copy_ex(nullptr, &curves_src->id, nullptr, flags);
+ return result;
+}
+
+static Curves *curves_evaluate_modifiers(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ Object *object,
+ Curves *curves_input)
+{
+ Curves *curves = curves_input;
+
+ /* Modifier evaluation modes. */
+ const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
+ const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime;
+ ModifierApplyFlag apply_flag = use_render ? MOD_APPLY_RENDER : MOD_APPLY_USECACHE;
+ const ModifierEvalContext mectx = {depsgraph, object, apply_flag};
+
+ /* Get effective list of modifiers to execute. Some effects like shape keys
+ * are added as virtual modifiers before the user created modifiers. */
+ VirtualModifierData virtualModifierData;
+ ModifierData *md = BKE_modifiers_get_virtual_modifierlist(object, &virtualModifierData);
+
+ /* Evaluate modifiers. */
+ for (; md; md = md->next) {
+ const ModifierTypeInfo *mti = BKE_modifier_get_info(static_cast<ModifierType>(md->type));
+
+ if (!BKE_modifier_is_enabled(scene, md, required_mode)) {
+ continue;
+ }
+
+ if ((mti->type == eModifierTypeType_OnlyDeform) &&
+ (mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly)) {
+ /* Ensure we are not modifying the input. */
+ if (curves == curves_input) {
+ curves = BKE_curves_copy_for_eval(curves, true);
+ }
+
+ /* Ensure we are not overwriting referenced data. */
+ CustomData_duplicate_referenced_layer_named(&curves->geometry.point_data,
+ CD_PROP_FLOAT3,
+ ATTR_POSITION,
+ curves->geometry.point_size);
+ BKE_curves_update_customdata_pointers(curves);
+
+ /* Created deformed coordinates array on demand. */
+ mti->deformVerts(
+ md, &mectx, nullptr, curves->geometry.position, curves->geometry.point_size);
+ }
+ }
+
+ return curves;
+}
+
+void BKE_curves_data_update(struct Depsgraph *depsgraph, struct Scene *scene, Object *object)
+{
+ /* Free any evaluated data and restore original data. */
+ BKE_object_free_derived_caches(object);
+
+ /* Evaluate modifiers. */
+ Curves *curves = static_cast<Curves *>(object->data);
+ Curves *curves_eval = curves_evaluate_modifiers(depsgraph, scene, object, curves);
+
+ /* Assign evaluated object. */
+ const bool is_owned = (curves != curves_eval);
+ BKE_object_eval_assign_data(object, &curves_eval->id, is_owned);
+}
+
+/* Draw Cache */
+
+void (*BKE_curves_batch_cache_dirty_tag_cb)(Curves *curves, int mode) = nullptr;
+void (*BKE_curves_batch_cache_free_cb)(Curves *curves) = nullptr;
+
+void BKE_curves_batch_cache_dirty_tag(Curves *curves, int mode)
+{
+ if (curves->batch_cache) {
+ BKE_curves_batch_cache_dirty_tag_cb(curves, mode);
+ }
+}
+
+void BKE_curves_batch_cache_free(Curves *curves)
+{
+ if (curves->batch_cache) {
+ BKE_curves_batch_cache_free_cb(curves);
+ }
+}
diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc
index e4c18325d76..6db5ae7567f 100644
--- a/source/blender/blenkernel/intern/customdata.cc
+++ b/source/blender/blenkernel/intern/customdata.cc
@@ -15,13 +15,13 @@
*
* The Original Code is Copyright (C) 2006 Blender Foundation.
* All rights reserved.
- * Implementation of CustomData.
- *
- * BKE_customdata.h contains the function prototypes for this file.
*/
/** \file
* \ingroup bke
+ * Implementation of CustomData.
+ *
+ * BKE_customdata.h contains the function prototypes for this file.
*/
#include "MEM_guardedalloc.h"
@@ -31,7 +31,6 @@
#include "DNA_ID.h"
#include "DNA_customdata_types.h"
-#include "DNA_hair_types.h"
#include "DNA_meshdata_types.h"
#include "BLI_bitmap.h"
@@ -1793,10 +1792,10 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = {
{sizeof(float[3]), "vec3f", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 44: CD_RADIUS */
{sizeof(float), "MFloatProperty", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
- /* 45: CD_HAIRCURVE */
- {sizeof(HairCurve), "HairCurve", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
- /* 46: CD_HAIRMAPPING */
- {sizeof(HairMapping), "HairMapping", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
+ /* 45: CD_PROP_INT8 */
+ {sizeof(int8_t), "MInt8Property", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
+ /* 46: CD_HAIRMAPPING */ /* UNUSED */
+ {-1, "", 1, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr},
/* 47: CD_PROP_COLOR */
{sizeof(MPropCol),
"MPropCol",
@@ -1914,7 +1913,7 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = {
"CDCustomLoopNormal",
"CDSculptFaceGroups",
/* 43-46 */ "CDHairPoint",
- "CDHairCurve",
+ "CDPropInt8",
"CDHairMapping",
"CDPoint",
"CDPropCol",
@@ -2431,7 +2430,7 @@ const char *CustomData_get_active_layer_name(const struct CustomData *data, cons
{
/* Get the layer index of the active layer of this type. */
const int layer_index = CustomData_get_active_layer_index(data, type);
- return layer_index < 0 ? NULL : data->layers[layer_index].name;
+ return layer_index < 0 ? nullptr : data->layers[layer_index].name;
}
void CustomData_set_layer_active(CustomData *data, int type, int n)
@@ -2786,7 +2785,7 @@ void CustomData_free_layers_anonymous(struct CustomData *data, int totelem)
bool found_anonymous_layer = false;
for (int i = 0; i < data->totlayer; i++) {
const CustomDataLayer *layer = &data->layers[i];
- if (layer->anonymous_id != NULL) {
+ if (layer->anonymous_id != nullptr) {
CustomData_free_layer(data, layer->type, totelem, i);
found_anonymous_layer = true;
break;
diff --git a/source/blender/blenkernel/intern/dynamicpaint.c b/source/blender/blenkernel/intern/dynamicpaint.c
index ef789d3e39b..bc5a0ed1538 100644
--- a/source/blender/blenkernel/intern/dynamicpaint.c
+++ b/source/blender/blenkernel/intern/dynamicpaint.c
@@ -1985,9 +1985,6 @@ static Mesh *dynamicPaint_Modifier_apply(DynamicPaintModifierData *pmd, Object *
}
MEM_freeN(fcolor);
-
- /* Mark tessellated CD layers as dirty. */
- // result->dirty |= DM_DIRTY_TESS_CDLAYERS;
}
/* vertex group paint */
else if (surface->type == MOD_DPAINT_SURFACE_T_WEIGHT) {
diff --git a/source/blender/blenkernel/intern/fcurve_driver.c b/source/blender/blenkernel/intern/fcurve_driver.c
index ce30f80ba65..e71217fea9e 100644
--- a/source/blender/blenkernel/intern/fcurve_driver.c
+++ b/source/blender/blenkernel/intern/fcurve_driver.c
@@ -88,14 +88,6 @@ typedef struct DriverVarTypeInfo {
/** \name Driver Target Utilities
* \{ */
-static ID *dtar_id_ensure_proxy_from(ID *id)
-{
- if (id && GS(id->name) == ID_OB && ((Object *)id)->proxy_from) {
- return (ID *)(((Object *)id)->proxy_from);
- }
- return id;
-}
-
/**
* Helper function to obtain a value using RNA from the specified source
* (for evaluating drivers).
@@ -113,7 +105,7 @@ static float dtar_get_prop_val(ChannelDriver *driver, DriverTarget *dtar)
return 0.0f;
}
- id = dtar_id_ensure_proxy_from(dtar->id);
+ id = dtar->id;
/* Error check for missing pointer. */
if (id == NULL) {
@@ -217,7 +209,7 @@ bool driver_get_variable_property(ChannelDriver *driver,
return false;
}
- id = dtar_id_ensure_proxy_from(dtar->id);
+ id = dtar->id;
/* Error check for missing pointer. */
if (id == NULL) {
@@ -273,7 +265,7 @@ static short driver_check_valid_targets(ChannelDriver *driver, DriverVar *dvar)
short valid_targets = 0;
DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) {
- Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id);
+ Object *ob = (Object *)dtar->id;
/* Check if this target has valid data. */
if ((ob == NULL) || (GS(ob->id.name) != ID_OB)) {
@@ -328,7 +320,7 @@ static float dvar_eval_rotDiff(ChannelDriver *driver, DriverVar *dvar)
for (int i = 0; i < 2; i++) {
/* Get pointer to loc values to store in. */
DriverTarget *dtar = &dvar->targets[i];
- Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id);
+ Object *ob = (Object *)dtar->id;
bPoseChannel *pchan;
/* After the checks above, the targets should be valid here. */
@@ -389,7 +381,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
/* NOTE: for now, these are all just world-space */
DRIVER_TARGETS_USED_LOOPER_BEGIN (dvar) {
/* Get pointer to loc values to store in. */
- Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id);
+ Object *ob = (Object *)dtar->id;
bPoseChannel *pchan;
float tmp_loc[3];
@@ -472,7 +464,7 @@ static float dvar_eval_locDiff(ChannelDriver *driver, DriverVar *dvar)
static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
{
DriverTarget *dtar = &dvar->targets[0];
- Object *ob = (Object *)dtar_id_ensure_proxy_from(dtar->id);
+ Object *ob = (Object *)dtar->id;
bPoseChannel *pchan;
float mat[4][4];
float oldEul[3] = {0.0f, 0.0f, 0.0f};
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 13338f33bd6..6e39125b252 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -55,6 +55,7 @@
#include "BKE_deform.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_geom.h"
+#include "BKE_gpencil_update_cache.h"
#include "BKE_icons.h"
#include "BKE_idtype.h"
#include "BKE_image.h"
@@ -158,6 +159,7 @@ static void greasepencil_blend_write(BlendWriter *writer, ID *id, const void *id
gpd->runtime.sbuffer_used = 0;
gpd->runtime.sbuffer_size = 0;
gpd->runtime.tot_cp_points = 0;
+ gpd->runtime.update_cache = NULL;
/* write gpd data block to file */
BLO_write_id_struct(writer, bGPdata, id_address, &gpd->id);
@@ -221,6 +223,7 @@ void BKE_gpencil_blend_read_data(BlendDataReader *reader, bGPdata *gpd)
gpd->runtime.sbuffer_used = 0;
gpd->runtime.sbuffer_size = 0;
gpd->runtime.tot_cp_points = 0;
+ gpd->runtime.update_cache = NULL;
/* Relink palettes (old palettes deprecated, only to convert old files). */
BLO_read_list(reader, &gpd->palettes);
@@ -501,6 +504,8 @@ void BKE_gpencil_free_data(bGPdata *gpd, bool free_all)
BLI_freelistN(&gpd->vertex_group_names);
+ BKE_gpencil_free_update_cache(gpd);
+
/* free all data */
if (free_all) {
/* clear cache */
@@ -985,6 +990,43 @@ bGPDlayer *BKE_gpencil_layer_duplicate(const bGPDlayer *gpl_src,
return gpl_dst;
}
+void BKE_gpencil_data_copy_settings(const bGPdata *gpd_src, bGPdata *gpd_dst)
+{
+ gpd_dst->flag = gpd_src->flag;
+ gpd_dst->curve_edit_resolution = gpd_src->curve_edit_resolution;
+ gpd_dst->curve_edit_threshold = gpd_src->curve_edit_threshold;
+ gpd_dst->curve_edit_corner_angle = gpd_src->curve_edit_corner_angle;
+ gpd_dst->pixfactor = gpd_src->pixfactor;
+ copy_v4_v4(gpd_dst->line_color, gpd_src->line_color);
+
+ gpd_dst->onion_factor = gpd_src->onion_factor;
+ gpd_dst->onion_mode = gpd_src->onion_mode;
+ gpd_dst->onion_flag = gpd_src->onion_flag;
+ gpd_dst->gstep = gpd_src->gstep;
+ gpd_dst->gstep_next = gpd_src->gstep_next;
+
+ copy_v3_v3(gpd_dst->gcolor_prev, gpd_src->gcolor_prev);
+ copy_v3_v3(gpd_dst->gcolor_next, gpd_src->gcolor_next);
+
+ gpd_dst->zdepth_offset = gpd_src->zdepth_offset;
+
+ gpd_dst->totlayer = gpd_src->totlayer;
+ gpd_dst->totframe = gpd_src->totframe;
+ gpd_dst->totstroke = gpd_src->totstroke;
+ gpd_dst->totpoint = gpd_src->totpoint;
+
+ gpd_dst->draw_mode = gpd_src->draw_mode;
+ gpd_dst->onion_keytype = gpd_src->onion_keytype;
+
+ gpd_dst->select_last_index = gpd_src->select_last_index;
+ gpd_dst->vertex_group_active_index = gpd_src->vertex_group_active_index;
+
+ copy_v3_v3(gpd_dst->grid.color, gpd_src->grid.color);
+ copy_v2_v2(gpd_dst->grid.scale, gpd_src->grid.scale);
+ copy_v2_v2(gpd_dst->grid.offset, gpd_src->grid.offset);
+ gpd_dst->grid.lines = gpd_src->grid.lines;
+}
+
void BKE_gpencil_layer_copy_settings(const bGPDlayer *gpl_src, bGPDlayer *gpl_dst)
{
gpl_dst->line_change = gpl_src->line_change;
@@ -1004,6 +1046,33 @@ void BKE_gpencil_layer_copy_settings(const bGPDlayer *gpl_src, bGPDlayer *gpl_ds
copy_m4_m4(gpl_dst->layer_invmat, gpl_src->layer_invmat);
gpl_dst->blend_mode = gpl_src->blend_mode;
gpl_dst->flag = gpl_src->flag;
+ gpl_dst->onion_flag = gpl_src->onion_flag;
+}
+
+void BKE_gpencil_frame_copy_settings(const bGPDframe *gpf_src, bGPDframe *gpf_dst)
+{
+ gpf_dst->flag = gpf_src->flag;
+ gpf_dst->key_type = gpf_src->key_type;
+ gpf_dst->framenum = gpf_src->framenum;
+}
+
+void BKE_gpencil_stroke_copy_settings(const bGPDstroke *gps_src, bGPDstroke *gps_dst)
+{
+ gps_dst->thickness = gps_src->thickness;
+ gps_dst->flag = gps_src->flag;
+ gps_dst->inittime = gps_src->inittime;
+ gps_dst->mat_nr = gps_src->mat_nr;
+ copy_v2_v2_short(gps_dst->caps, gps_src->caps);
+ gps_dst->hardeness = gps_src->hardeness;
+ copy_v2_v2(gps_dst->aspect_ratio, gps_src->aspect_ratio);
+ gps_dst->fill_opacity_fac = gps_dst->fill_opacity_fac;
+ copy_v3_v3(gps_dst->boundbox_min, gps_src->boundbox_min);
+ copy_v3_v3(gps_dst->boundbox_max, gps_src->boundbox_max);
+ gps_dst->uv_rotation = gps_src->uv_rotation;
+ copy_v2_v2(gps_dst->uv_translation, gps_src->uv_translation);
+ gps_dst->uv_scale = gps_src->uv_scale;
+ gps_dst->select_index = gps_src->select_index;
+ copy_v4_v4(gps_dst->vert_color_fill, gps_src->vert_color_fill);
}
bGPdata *BKE_gpencil_data_duplicate(Main *bmain, const bGPdata *gpd_src, bool internal_copy)
@@ -2579,36 +2648,53 @@ void BKE_gpencil_frame_original_pointers_update(const struct bGPDframe *gpf_orig
}
}
-void BKE_gpencil_update_orig_pointers(const Object *ob_orig, const Object *ob_eval)
+/**
+ * Update original pointers in evaluated layer.
+ * \param gpl_orig: Original grease-pencil layer.
+ * \param gpl_eval: Evaluated grease pencil layer.
+ */
+void BKE_gpencil_layer_original_pointers_update(const struct bGPDlayer *gpl_orig,
+ const struct bGPDlayer *gpl_eval)
{
- bGPdata *gpd_eval = (bGPdata *)ob_eval->data;
- bGPdata *gpd_orig = (bGPdata *)ob_orig->data;
+ bGPDframe *gpf_eval = gpl_eval->frames.first;
+ LISTBASE_FOREACH (bGPDframe *, gpf_orig, &gpl_orig->frames) {
+ if (gpf_eval != NULL) {
+ /* Update frame reference pointers. */
+ gpf_eval->runtime.gpf_orig = (bGPDframe *)gpf_orig;
+ BKE_gpencil_frame_original_pointers_update(gpf_orig, gpf_eval);
+ gpf_eval = gpf_eval->next;
+ }
+ }
+}
+void BKE_gpencil_data_update_orig_pointers(const bGPdata *gpd_orig, const bGPdata *gpd_eval)
+{
/* Assign pointers to the original stroke and points to the evaluated data. This must
* be done before applying any modifier because at this moment the structure is equals,
* so we can assume the layer index is the same in both data-blocks.
* This data will be used by operators. */
bGPDlayer *gpl_eval = gpd_eval->layers.first;
- LISTBASE_FOREACH (bGPDlayer *, gpl, &gpd_orig->layers) {
+ LISTBASE_FOREACH (bGPDlayer *, gpl_orig, &gpd_orig->layers) {
if (gpl_eval != NULL) {
/* Update layer reference pointers. */
- gpl_eval->runtime.gpl_orig = (bGPDlayer *)gpl;
-
- bGPDframe *gpf_eval = gpl_eval->frames.first;
- LISTBASE_FOREACH (bGPDframe *, gpf_orig, &gpl->frames) {
- if (gpf_eval != NULL) {
- /* Update frame reference pointers. */
- gpf_eval->runtime.gpf_orig = (bGPDframe *)gpf_orig;
- BKE_gpencil_frame_original_pointers_update(gpf_orig, gpf_eval);
- gpf_eval = gpf_eval->next;
- }
- }
+ gpl_eval->runtime.gpl_orig = gpl_orig;
+ BKE_gpencil_layer_original_pointers_update(gpl_orig, gpl_eval);
gpl_eval = gpl_eval->next;
}
}
}
+/**
+ * Update pointers of eval data to original data to keep references.
+ * \param ob_orig: Original grease pencil object
+ * \param ob_eval: Evaluated grease pencil object
+ */
+void BKE_gpencil_update_orig_pointers(const Object *ob_orig, const Object *ob_eval)
+{
+ BKE_gpencil_data_update_orig_pointers((bGPdata *)ob_orig->data, (bGPdata *)ob_eval->data);
+}
+
void BKE_gpencil_layer_transform_matrix_get(const Depsgraph *depsgraph,
Object *obact,
bGPDlayer *gpl,
@@ -2751,4 +2837,180 @@ void BKE_gpencil_frame_selected_hash(bGPdata *gpd, struct GHash *r_list)
}
}
+bool BKE_gpencil_can_avoid_full_copy_on_write(const Depsgraph *depsgraph, bGPdata *gpd)
+{
+ /* For now, we only use the update cache in the active depsgraph. Othwerwise we might access the
+ * cache while another depsgraph frees it. */
+ if (!DEG_is_active(depsgraph)) {
+ return false;
+ }
+
+ GPencilUpdateCache *update_cache = gpd->runtime.update_cache;
+ return update_cache != NULL && update_cache->flag != GP_UPDATE_NODE_FULL_COPY;
+}
+
+typedef struct tGPencilUpdateOnWriteTraverseData {
+ bGPdata *gpd_eval;
+ bGPDlayer *gpl_eval;
+ bGPDframe *gpf_eval;
+ bGPDstroke *gps_eval;
+ int gpl_index;
+ int gpf_index;
+ int gps_index;
+} tGPencilUpdateOnWriteTraverseData;
+
+static bool gpencil_update_on_write_layer_cb(GPencilUpdateCache *gpl_cache, void *user_data)
+{
+ tGPencilUpdateOnWriteTraverseData *td = (tGPencilUpdateOnWriteTraverseData *)user_data;
+ td->gpl_eval = BLI_findlinkfrom((Link *)td->gpl_eval, gpl_cache->index - td->gpl_index);
+ td->gpl_index = gpl_cache->index;
+ bGPDlayer *gpl = (bGPDlayer *)gpl_cache->data;
+
+ if (gpl_cache->flag == GP_UPDATE_NODE_FULL_COPY) {
+ bGPDlayer *gpl_eval_next = td->gpl_eval->next;
+ BLI_assert(gpl != NULL);
+
+ BKE_gpencil_layer_delete(td->gpd_eval, td->gpl_eval);
+
+ td->gpl_eval = BKE_gpencil_layer_duplicate(gpl, true, true);
+ BLI_insertlinkbefore(&td->gpd_eval->layers, gpl_eval_next, td->gpl_eval);
+
+ BKE_gpencil_layer_original_pointers_update(gpl, td->gpl_eval);
+ td->gpl_eval->runtime.gpl_orig = gpl;
+ return true;
+ }
+ else if (gpl_cache->flag == GP_UPDATE_NODE_LIGHT_COPY) {
+ BLI_assert(gpl != NULL);
+ BKE_gpencil_layer_copy_settings(gpl, td->gpl_eval);
+ td->gpl_eval->runtime.gpl_orig = gpl;
+ }
+
+ td->gpf_eval = td->gpl_eval->frames.first;
+ td->gpf_index = 0;
+ return false;
+}
+
+static bool gpencil_update_on_write_frame_cb(GPencilUpdateCache *gpf_cache, void *user_data)
+{
+ tGPencilUpdateOnWriteTraverseData *td = (tGPencilUpdateOnWriteTraverseData *)user_data;
+ td->gpf_eval = BLI_findlinkfrom((Link *)td->gpf_eval, gpf_cache->index - td->gpf_index);
+ td->gpf_index = gpf_cache->index;
+
+ bGPDframe *gpf = (bGPDframe *)gpf_cache->data;
+
+ if (gpf_cache->flag == GP_UPDATE_NODE_FULL_COPY) {
+ /* Do a full copy of the frame. */
+ bGPDframe *gpf_eval_next = td->gpf_eval->next;
+ BLI_assert(gpf != NULL);
+
+ bool update_actframe = (td->gpl_eval->actframe == td->gpf_eval) ? true : false;
+ BKE_gpencil_free_strokes(td->gpf_eval);
+ BLI_freelinkN(&td->gpl_eval->frames, td->gpf_eval);
+
+ td->gpf_eval = BKE_gpencil_frame_duplicate(gpf, true);
+ BLI_insertlinkbefore(&td->gpl_eval->frames, gpf_eval_next, td->gpf_eval);
+
+ BKE_gpencil_frame_original_pointers_update(gpf, td->gpf_eval);
+ td->gpf_eval->runtime.gpf_orig = gpf;
+
+ if (update_actframe) {
+ td->gpl_eval->actframe = td->gpf_eval;
+ }
+
+ return true;
+ }
+ else if (gpf_cache->flag == GP_UPDATE_NODE_LIGHT_COPY) {
+ BLI_assert(gpf != NULL);
+ BKE_gpencil_frame_copy_settings(gpf, td->gpf_eval);
+ td->gpf_eval->runtime.gpf_orig = gpf;
+ }
+
+ td->gps_eval = td->gpf_eval->strokes.first;
+ td->gps_index = 0;
+ return false;
+}
+
+static bool gpencil_update_on_write_stroke_cb(GPencilUpdateCache *gps_cache, void *user_data)
+{
+ tGPencilUpdateOnWriteTraverseData *td = (tGPencilUpdateOnWriteTraverseData *)user_data;
+ td->gps_eval = BLI_findlinkfrom((Link *)td->gps_eval, gps_cache->index - td->gps_index);
+ td->gps_index = gps_cache->index;
+
+ bGPDstroke *gps = (bGPDstroke *)gps_cache->data;
+
+ if (gps_cache->flag == GP_UPDATE_NODE_FULL_COPY) {
+ /* Do a full copy of the stroke. */
+ bGPDstroke *gps_eval_next = td->gps_eval->next;
+ BLI_assert(gps != NULL);
+
+ BLI_remlink(&td->gpf_eval->strokes, td->gps_eval);
+ BKE_gpencil_free_stroke(td->gps_eval);
+
+ td->gps_eval = BKE_gpencil_stroke_duplicate(gps, true, true);
+ BLI_insertlinkbefore(&td->gpf_eval->strokes, gps_eval_next, td->gps_eval);
+
+ td->gps_eval->runtime.gps_orig = gps;
+
+ /* Assign original pt pointers. */
+ for (int i = 0; i < gps->totpoints; i++) {
+ bGPDspoint *pt_orig = &gps->points[i];
+ bGPDspoint *pt_eval = &td->gps_eval->points[i];
+ pt_orig->runtime.pt_orig = NULL;
+ pt_orig->runtime.idx_orig = i;
+ pt_eval->runtime.pt_orig = pt_orig;
+ pt_eval->runtime.idx_orig = i;
+ }
+ }
+ else if (gps_cache->flag == GP_UPDATE_NODE_LIGHT_COPY) {
+ BLI_assert(gps != NULL);
+ BKE_gpencil_stroke_copy_settings(gps, td->gps_eval);
+ td->gps_eval->runtime.gps_orig = gps;
+ }
+
+ return false;
+}
+
+/**
+ * Update the geometry of the evaluated bGPdata.
+ * This function will:
+ * 1) Copy the original data over to the evaluated object.
+ * 2) Update the original pointers in the runtime structs.
+ */
+void BKE_gpencil_update_on_write(bGPdata *gpd_orig, bGPdata *gpd_eval)
+{
+ GPencilUpdateCache *update_cache = gpd_orig->runtime.update_cache;
+
+ /* We assume that a full copy is not needed and the update cache is populated. */
+ if (update_cache == NULL || update_cache->flag == GP_UPDATE_NODE_FULL_COPY) {
+ return;
+ }
+
+ if (update_cache->flag == GP_UPDATE_NODE_LIGHT_COPY) {
+ BKE_gpencil_data_copy_settings(gpd_orig, gpd_eval);
+ }
+
+ GPencilUpdateCacheTraverseSettings ts = {{
+ gpencil_update_on_write_layer_cb,
+ gpencil_update_on_write_frame_cb,
+ gpencil_update_on_write_stroke_cb,
+ }};
+
+ tGPencilUpdateOnWriteTraverseData data = {
+ .gpd_eval = gpd_eval,
+ .gpl_eval = gpd_eval->layers.first,
+ .gpf_eval = NULL,
+ .gps_eval = NULL,
+ .gpl_index = 0,
+ .gpf_index = 0,
+ .gps_index = 0,
+ };
+
+ BKE_gpencil_traverse_update_cache(update_cache, &ts, &data);
+
+ gpd_eval->flag |= GP_DATA_CACHE_IS_DIRTY;
+
+ /* TODO: This might cause issues when we have multiple depsgraphs? */
+ BKE_gpencil_free_update_cache(gpd_orig);
+}
+
/** \} */
diff --git a/source/blender/blenkernel/intern/gpencil_update_cache.c b/source/blender/blenkernel/intern/gpencil_update_cache.c
new file mode 100644
index 00000000000..323c3a9f2a2
--- /dev/null
+++ b/source/blender/blenkernel/intern/gpencil_update_cache.c
@@ -0,0 +1,274 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2022, Blender Foundation
+ * This is a new part of Blender
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include <stdio.h>
+
+#include "BKE_gpencil_update_cache.h"
+
+#include "BLI_dlrbTree.h"
+#include "BLI_listbase.h"
+
+#include "BKE_gpencil.h"
+
+#include "DNA_gpencil_types.h"
+#include "DNA_userdef_types.h"
+
+#include "MEM_guardedalloc.h"
+
+static GPencilUpdateCache *update_cache_alloc(int index, int flag, void *data)
+{
+ GPencilUpdateCache *new_cache = MEM_callocN(sizeof(GPencilUpdateCache), __func__);
+ new_cache->children = BLI_dlrbTree_new();
+ new_cache->flag = flag;
+ new_cache->index = index;
+ new_cache->data = data;
+
+ return new_cache;
+}
+
+static short cache_node_compare(void *node, void *data)
+{
+ int index_a = ((GPencilUpdateCacheNode *)node)->cache->index;
+ int index_b = ((GPencilUpdateCache *)data)->index;
+ if (index_a == index_b) {
+ return 0;
+ }
+ return index_a < index_b ? 1 : -1;
+}
+
+static DLRBT_Node *cache_node_alloc(void *data)
+{
+ GPencilUpdateCacheNode *new_node = MEM_callocN(sizeof(GPencilUpdateCacheNode), __func__);
+ new_node->cache = ((GPencilUpdateCache *)data);
+ return (DLRBT_Node *)new_node;
+}
+
+static void cache_node_free(void *node);
+
+static void update_cache_free(GPencilUpdateCache *cache)
+{
+ if (cache->children != NULL) {
+ BLI_dlrbTree_free(cache->children, cache_node_free);
+ MEM_freeN(cache->children);
+ }
+ MEM_freeN(cache);
+}
+
+static void cache_node_free(void *node)
+{
+ GPencilUpdateCache *cache = ((GPencilUpdateCacheNode *)node)->cache;
+ if (cache != NULL) {
+ update_cache_free(cache);
+ }
+ MEM_freeN(node);
+}
+
+static void cache_node_update(void *node, void *data)
+{
+ GPencilUpdateCache *update_cache = ((GPencilUpdateCacheNode *)node)->cache;
+ GPencilUpdateCache *new_update_cache = (GPencilUpdateCache *)data;
+
+ /* If the new cache is already "covered" by the current cache, just free it and return. */
+ if (new_update_cache->flag <= update_cache->flag) {
+ update_cache_free(new_update_cache);
+ return;
+ }
+
+ update_cache->data = new_update_cache->data;
+ update_cache->flag = new_update_cache->flag;
+
+ /* In case the new cache does a full update, remove its children since they will be all
+ * updated by this cache. */
+ if (new_update_cache->flag == GP_UPDATE_NODE_FULL_COPY && update_cache->children != NULL) {
+ BLI_dlrbTree_free(update_cache->children, cache_node_free);
+ MEM_freeN(update_cache->children);
+ }
+
+ update_cache_free(new_update_cache);
+}
+
+static void update_cache_node_create_ex(GPencilUpdateCache *root_cache,
+ void *data,
+ int gpl_index,
+ int gpf_index,
+ int gps_index,
+ bool full_copy)
+{
+ if (root_cache->flag == GP_UPDATE_NODE_FULL_COPY) {
+ /* Entire data-block has to be recaculated, e.g. nothing else needs to be added to the cache.
+ */
+ return;
+ }
+
+ const int node_flag = full_copy ? GP_UPDATE_NODE_FULL_COPY : GP_UPDATE_NODE_LIGHT_COPY;
+
+ if (gpl_index == -1) {
+ root_cache->data = (bGPdata *)data;
+ root_cache->flag = node_flag;
+ if (full_copy) {
+ /* Entire data-block has to be recaculated, remove all caches of "lower" elements. */
+ BLI_dlrbTree_free(root_cache->children, cache_node_free);
+ }
+ return;
+ }
+
+ const bool is_layer_update_node = (gpf_index == -1);
+ /* If the data pointer in GPencilUpdateCache is NULL, this element is not actually cached
+ * and does not need to be updated, but we do need the index to find elements that are in
+ * levels below. E.g. if a stroke needs to be updated, the frame it is in would not hold a
+ * pointer to it's data. */
+ GPencilUpdateCache *gpl_cache = update_cache_alloc(
+ gpl_index,
+ is_layer_update_node ? node_flag : GP_UPDATE_NODE_NO_COPY,
+ is_layer_update_node ? (bGPDlayer *)data : NULL);
+ GPencilUpdateCacheNode *gpl_node = (GPencilUpdateCacheNode *)BLI_dlrbTree_add(
+ root_cache->children, cache_node_compare, cache_node_alloc, cache_node_update, gpl_cache);
+
+ BLI_dlrbTree_linkedlist_sync(root_cache->children);
+ if (gpl_node->cache->flag == GP_UPDATE_NODE_FULL_COPY || is_layer_update_node) {
+ return;
+ }
+
+ const bool is_frame_update_node = (gps_index == -1);
+ GPencilUpdateCache *gpf_cache = update_cache_alloc(
+ gpf_index,
+ is_frame_update_node ? node_flag : GP_UPDATE_NODE_NO_COPY,
+ is_frame_update_node ? (bGPDframe *)data : NULL);
+ GPencilUpdateCacheNode *gpf_node = (GPencilUpdateCacheNode *)BLI_dlrbTree_add(
+ gpl_node->cache->children,
+ cache_node_compare,
+ cache_node_alloc,
+ cache_node_update,
+ gpf_cache);
+
+ BLI_dlrbTree_linkedlist_sync(gpl_node->cache->children);
+ if (gpf_node->cache->flag == GP_UPDATE_NODE_FULL_COPY || is_frame_update_node) {
+ return;
+ }
+
+ GPencilUpdateCache *gps_cache = update_cache_alloc(gps_index, node_flag, (bGPDstroke *)data);
+ BLI_dlrbTree_add(
+ gpf_node->cache->children, cache_node_compare, cache_node_alloc, cache_node_update, gps_cache);
+
+ BLI_dlrbTree_linkedlist_sync(gpf_node->cache->children);
+}
+
+static void update_cache_node_create(
+ bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps, bool full_copy)
+{
+ if (gpd == NULL) {
+ return;
+ }
+
+ GPencilUpdateCache *root_cache = gpd->runtime.update_cache;
+ if (root_cache == NULL) {
+ gpd->runtime.update_cache = update_cache_alloc(0, GP_UPDATE_NODE_NO_COPY, NULL);
+ root_cache = gpd->runtime.update_cache;
+ }
+
+ if (root_cache->flag == GP_UPDATE_NODE_FULL_COPY) {
+ /* Entire data-block has to be recaculated, e.g. nothing else needs to be added to the cache.
+ */
+ return;
+ }
+
+ const int gpl_index = (gpl != NULL) ? BLI_findindex(&gpd->layers, gpl) : -1;
+ const int gpf_index = (gpl != NULL && gpf != NULL) ? BLI_findindex(&gpl->frames, gpf) : -1;
+ const int gps_index = (gpf != NULL && gps != NULL) ? BLI_findindex(&gpf->strokes, gps) : -1;
+
+ void *data = gps;
+ if (!data) {
+ data = gpf;
+ }
+ if (!data) {
+ data = gpl;
+ }
+ if (!data) {
+ data = gpd;
+ }
+
+ update_cache_node_create_ex(root_cache, data, gpl_index, gpf_index, gps_index, full_copy);
+}
+
+static void gpencil_traverse_update_cache_ex(GPencilUpdateCache *parent_cache,
+ GPencilUpdateCacheTraverseSettings *ts,
+ int depth,
+ void *user_data)
+{
+ if (BLI_listbase_is_empty((ListBase *)parent_cache->children)) {
+ return;
+ }
+
+ LISTBASE_FOREACH (GPencilUpdateCacheNode *, cache_node, parent_cache->children) {
+ GPencilUpdateCache *cache = cache_node->cache;
+
+ GPencilUpdateCacheIter_Cb cb = ts->update_cache_cb[depth];
+ if (cb != NULL) {
+ bool skip = cb(cache, user_data);
+ if (skip) {
+ continue;
+ }
+ }
+
+ gpencil_traverse_update_cache_ex(cache, ts, depth + 1, user_data);
+ }
+}
+
+/* -------------------------------------------------------------------- */
+/** \name Update Cache API
+ *
+ * \{ */
+
+GPencilUpdateCache *BKE_gpencil_create_update_cache(void *data, bool full_copy)
+{
+ return update_cache_alloc(
+ 0, full_copy ? GP_UPDATE_NODE_FULL_COPY : GP_UPDATE_NODE_LIGHT_COPY, data);
+}
+
+void BKE_gpencil_traverse_update_cache(GPencilUpdateCache *cache,
+ GPencilUpdateCacheTraverseSettings *ts,
+ void *user_data)
+{
+ gpencil_traverse_update_cache_ex(cache, ts, 0, user_data);
+}
+
+void BKE_gpencil_tag_full_update(bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps)
+{
+ update_cache_node_create(gpd, gpl, gpf, gps, true);
+}
+
+void BKE_gpencil_tag_light_update(bGPdata *gpd, bGPDlayer *gpl, bGPDframe *gpf, bGPDstroke *gps)
+{
+ update_cache_node_create(gpd, gpl, gpf, gps, false);
+}
+
+void BKE_gpencil_free_update_cache(bGPdata *gpd)
+{
+ GPencilUpdateCache *gpd_cache = gpd->runtime.update_cache;
+ if (gpd_cache) {
+ update_cache_free(gpd_cache);
+ gpd->runtime.update_cache = NULL;
+ }
+}
+
+/** \} */
diff --git a/source/blender/blenkernel/intern/hair.cc b/source/blender/blenkernel/intern/hair.cc
deleted file mode 100644
index b7ba159f631..00000000000
--- a/source/blender/blenkernel/intern/hair.cc
+++ /dev/null
@@ -1,435 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-/** \file
- * \ingroup bke
- */
-
-#include <cmath>
-#include <cstring>
-
-#include "MEM_guardedalloc.h"
-
-#include "DNA_defaults.h"
-#include "DNA_hair_types.h"
-#include "DNA_material_types.h"
-#include "DNA_object_types.h"
-
-#include "BLI_listbase.h"
-#include "BLI_math_base.h"
-#include "BLI_math_vec_types.hh"
-#include "BLI_rand.h"
-#include "BLI_string.h"
-#include "BLI_utildefines.h"
-
-#include "BKE_anim_data.h"
-#include "BKE_customdata.h"
-#include "BKE_global.h"
-#include "BKE_hair.h"
-#include "BKE_idtype.h"
-#include "BKE_lib_id.h"
-#include "BKE_lib_query.h"
-#include "BKE_lib_remap.h"
-#include "BKE_main.h"
-#include "BKE_modifier.h"
-#include "BKE_object.h"
-
-#include "BLT_translation.h"
-
-#include "DEG_depsgraph_query.h"
-
-#include "BLO_read_write.h"
-
-using blender::float3;
-
-static const char *HAIR_ATTR_POSITION = "position";
-static const char *HAIR_ATTR_RADIUS = "radius";
-
-/* Hair datablock */
-
-static void hair_random(Hair *hair);
-
-static void hair_init_data(ID *id)
-{
- Hair *hair = (Hair *)id;
- BLI_assert(MEMCMP_STRUCT_AFTER_IS_ZERO(hair, id));
-
- MEMCPY_STRUCT_AFTER(hair, DNA_struct_default_get(Hair), id);
-
- CustomData_reset(&hair->pdata);
- CustomData_reset(&hair->cdata);
-
- CustomData_add_layer_named(
- &hair->pdata, CD_PROP_FLOAT3, CD_CALLOC, nullptr, hair->totpoint, HAIR_ATTR_POSITION);
- CustomData_add_layer_named(
- &hair->pdata, CD_PROP_FLOAT, CD_CALLOC, nullptr, hair->totpoint, HAIR_ATTR_RADIUS);
- CustomData_add_layer(&hair->cdata, CD_HAIRCURVE, CD_CALLOC, nullptr, hair->totcurve);
- BKE_hair_update_customdata_pointers(hair);
-
- hair_random(hair);
-}
-
-static void hair_copy_data(Main *UNUSED(bmain), ID *id_dst, const ID *id_src, const int flag)
-{
- Hair *hair_dst = (Hair *)id_dst;
- const Hair *hair_src = (const Hair *)id_src;
- hair_dst->mat = static_cast<Material **>(MEM_dupallocN(hair_src->mat));
-
- const eCDAllocType alloc_type = (flag & LIB_ID_COPY_CD_REFERENCE) ? CD_REFERENCE : CD_DUPLICATE;
- CustomData_copy(&hair_src->pdata, &hair_dst->pdata, CD_MASK_ALL, alloc_type, hair_dst->totpoint);
- CustomData_copy(&hair_src->cdata, &hair_dst->cdata, CD_MASK_ALL, alloc_type, hair_dst->totcurve);
- BKE_hair_update_customdata_pointers(hair_dst);
-
- hair_dst->batch_cache = nullptr;
-}
-
-static void hair_free_data(ID *id)
-{
- Hair *hair = (Hair *)id;
- BKE_animdata_free(&hair->id, false);
-
- BKE_hair_batch_cache_free(hair);
-
- CustomData_free(&hair->pdata, hair->totpoint);
- CustomData_free(&hair->cdata, hair->totcurve);
-
- MEM_SAFE_FREE(hair->mat);
-}
-
-static void hair_foreach_id(ID *id, LibraryForeachIDData *data)
-{
- Hair *hair = (Hair *)id;
- for (int i = 0; i < hair->totcol; i++) {
- BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, hair->mat[i], IDWALK_CB_USER);
- }
-}
-
-static void hair_blend_write(BlendWriter *writer, ID *id, const void *id_address)
-{
- Hair *hair = (Hair *)id;
-
- CustomDataLayer *players = nullptr, players_buff[CD_TEMP_CHUNK_SIZE];
- CustomDataLayer *clayers = nullptr, clayers_buff[CD_TEMP_CHUNK_SIZE];
- CustomData_blend_write_prepare(&hair->pdata, &players, players_buff, ARRAY_SIZE(players_buff));
- CustomData_blend_write_prepare(&hair->cdata, &clayers, clayers_buff, ARRAY_SIZE(clayers_buff));
-
- /* Write LibData */
- BLO_write_id_struct(writer, Hair, id_address, &hair->id);
- BKE_id_blend_write(writer, &hair->id);
-
- /* Direct data */
- CustomData_blend_write(writer, &hair->pdata, players, hair->totpoint, CD_MASK_ALL, &hair->id);
- CustomData_blend_write(writer, &hair->cdata, clayers, hair->totcurve, CD_MASK_ALL, &hair->id);
-
- BLO_write_pointer_array(writer, hair->totcol, hair->mat);
- if (hair->adt) {
- BKE_animdata_blend_write(writer, hair->adt);
- }
-
- /* Remove temporary data. */
- if (players && players != players_buff) {
- MEM_freeN(players);
- }
- if (clayers && clayers != clayers_buff) {
- MEM_freeN(clayers);
- }
-}
-
-static void hair_blend_read_data(BlendDataReader *reader, ID *id)
-{
- Hair *hair = (Hair *)id;
- BLO_read_data_address(reader, &hair->adt);
- BKE_animdata_blend_read_data(reader, hair->adt);
-
- /* Geometry */
- CustomData_blend_read(reader, &hair->pdata, hair->totpoint);
- CustomData_blend_read(reader, &hair->cdata, hair->totcurve);
- BKE_hair_update_customdata_pointers(hair);
-
- /* Materials */
- BLO_read_pointer_array(reader, (void **)&hair->mat);
-}
-
-static void hair_blend_read_lib(BlendLibReader *reader, ID *id)
-{
- Hair *hair = (Hair *)id;
- for (int a = 0; a < hair->totcol; a++) {
- BLO_read_id_address(reader, hair->id.lib, &hair->mat[a]);
- }
-}
-
-static void hair_blend_read_expand(BlendExpander *expander, ID *id)
-{
- Hair *hair = (Hair *)id;
- for (int a = 0; a < hair->totcol; a++) {
- BLO_expand(expander, hair->mat[a]);
- }
-}
-
-IDTypeInfo IDType_ID_HA = {
- /*id_code */ ID_HA,
- /*id_filter */ FILTER_ID_HA,
- /*main_listbase_index */ INDEX_ID_HA,
- /*struct_size */ sizeof(Hair),
- /*name */ "Hair",
- /*name_plural */ "hairs",
- /*translation_context */ BLT_I18NCONTEXT_ID_HAIR,
- /*flags */ IDTYPE_FLAGS_APPEND_IS_REUSABLE,
- /*asset_type_info */ nullptr,
-
- /*init_data */ hair_init_data,
- /*copy_data */ hair_copy_data,
- /*free_data */ hair_free_data,
- /*make_local */ nullptr,
- /*foreach_id */ hair_foreach_id,
- /*foreach_cache */ nullptr,
- /*foreach_path */ nullptr,
- /*owner_get */ nullptr,
-
- /*blend_write */ hair_blend_write,
- /*blend_read_data */ hair_blend_read_data,
- /*blend_read_lib */ hair_blend_read_lib,
- /*blend_read_expand */ hair_blend_read_expand,
-
- /*blend_read_undo_preserve */ nullptr,
-
- /*lib_override_apply_post */ nullptr,
-};
-
-static void hair_random(Hair *hair)
-{
- const int numpoints = 8;
-
- hair->totcurve = 500;
- hair->totpoint = hair->totcurve * numpoints;
-
- CustomData_realloc(&hair->pdata, hair->totpoint);
- CustomData_realloc(&hair->cdata, hair->totcurve);
- BKE_hair_update_customdata_pointers(hair);
-
- RNG *rng = BLI_rng_new(0);
-
- for (int i = 0; i < hair->totcurve; i++) {
- HairCurve *curve = &hair->curves[i];
- curve->firstpoint = i * numpoints;
- curve->numpoints = numpoints;
-
- float theta = 2.0f * M_PI * BLI_rng_get_float(rng);
- float phi = saacosf(2.0f * BLI_rng_get_float(rng) - 1.0f);
-
- float no[3] = {sinf(theta) * sinf(phi), cosf(theta) * sinf(phi), cosf(phi)};
- normalize_v3(no);
-
- float co[3];
- copy_v3_v3(co, no);
-
- float(*curve_co)[3] = hair->co + curve->firstpoint;
- float *curve_radius = hair->radius + curve->firstpoint;
- for (int key = 0; key < numpoints; key++) {
- float t = key / (float)(numpoints - 1);
- copy_v3_v3(curve_co[key], co);
- curve_radius[key] = 0.02f * (1.0f - t);
-
- float offset[3] = {2.0f * BLI_rng_get_float(rng) - 1.0f,
- 2.0f * BLI_rng_get_float(rng) - 1.0f,
- 2.0f * BLI_rng_get_float(rng) - 1.0f};
- add_v3_v3(offset, no);
- madd_v3_v3fl(co, offset, 1.0f / numpoints);
- }
- }
-
- BLI_rng_free(rng);
-}
-
-void *BKE_hair_add(Main *bmain, const char *name)
-{
- Hair *hair = static_cast<Hair *>(BKE_id_new(bmain, ID_HA, name));
-
- return hair;
-}
-
-BoundBox *BKE_hair_boundbox_get(Object *ob)
-{
- BLI_assert(ob->type == OB_HAIR);
- Hair *hair = static_cast<Hair *>(ob->data);
-
- if (ob->runtime.bb != nullptr && (ob->runtime.bb->flag & BOUNDBOX_DIRTY) == 0) {
- return ob->runtime.bb;
- }
-
- if (ob->runtime.bb == nullptr) {
- ob->runtime.bb = MEM_cnew<BoundBox>(__func__);
-
- float min[3], max[3];
- INIT_MINMAX(min, max);
-
- float(*hair_co)[3] = hair->co;
- float *hair_radius = hair->radius;
- for (int a = 0; a < hair->totpoint; a++) {
- float *co = hair_co[a];
- float radius = (hair_radius) ? hair_radius[a] : 0.0f;
- const float co_min[3] = {co[0] - radius, co[1] - radius, co[2] - radius};
- const float co_max[3] = {co[0] + radius, co[1] + radius, co[2] + radius};
- DO_MIN(co_min, min);
- DO_MAX(co_max, max);
- }
-
- BKE_boundbox_init_from_minmax(ob->runtime.bb, min, max);
- }
-
- return ob->runtime.bb;
-}
-
-void BKE_hair_update_customdata_pointers(Hair *hair)
-{
- hair->co = (float(*)[3])CustomData_get_layer_named(
- &hair->pdata, CD_PROP_FLOAT3, HAIR_ATTR_POSITION);
- hair->radius = (float *)CustomData_get_layer_named(
- &hair->pdata, CD_PROP_FLOAT, HAIR_ATTR_RADIUS);
- hair->curves = (HairCurve *)CustomData_get_layer(&hair->cdata, CD_HAIRCURVE);
- hair->mapping = (HairMaping *)CustomData_get_layer(&hair->cdata, CD_HAIRMAPPING);
-}
-
-bool BKE_hair_customdata_required(Hair *UNUSED(hair), CustomDataLayer *layer)
-{
- return layer->type == CD_PROP_FLOAT3 && STREQ(layer->name, HAIR_ATTR_POSITION);
-}
-
-/* Dependency Graph */
-
-Hair *BKE_hair_new_for_eval(const Hair *hair_src, int totpoint, int totcurve)
-{
- Hair *hair_dst = static_cast<Hair *>(BKE_id_new_nomain(ID_HA, nullptr));
-
- STRNCPY(hair_dst->id.name, hair_src->id.name);
- hair_dst->mat = static_cast<Material **>(MEM_dupallocN(hair_src->mat));
- hair_dst->totcol = hair_src->totcol;
-
- hair_dst->totpoint = totpoint;
- hair_dst->totcurve = totcurve;
- CustomData_copy(&hair_src->pdata, &hair_dst->pdata, CD_MASK_ALL, CD_CALLOC, totpoint);
- CustomData_copy(&hair_src->cdata, &hair_dst->cdata, CD_MASK_ALL, CD_CALLOC, totcurve);
- BKE_hair_update_customdata_pointers(hair_dst);
-
- return hair_dst;
-}
-
-Hair *BKE_hair_copy_for_eval(Hair *hair_src, bool reference)
-{
- int flags = LIB_ID_COPY_LOCALIZE;
-
- if (reference) {
- flags |= LIB_ID_COPY_CD_REFERENCE;
- }
-
- Hair *result = (Hair *)BKE_id_copy_ex(nullptr, &hair_src->id, nullptr, flags);
- return result;
-}
-
-static Hair *hair_evaluate_modifiers(struct Depsgraph *depsgraph,
- struct Scene *scene,
- Object *object,
- Hair *hair_input)
-{
- Hair *hair = hair_input;
-
- /* Modifier evaluation modes. */
- const bool use_render = (DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
- const int required_mode = use_render ? eModifierMode_Render : eModifierMode_Realtime;
- ModifierApplyFlag apply_flag = use_render ? MOD_APPLY_RENDER : MOD_APPLY_USECACHE;
- const ModifierEvalContext mectx = {depsgraph, object, apply_flag};
-
- /* Get effective list of modifiers to execute. Some effects like shape keys
- * are added as virtual modifiers before the user created modifiers. */
- VirtualModifierData virtualModifierData;
- ModifierData *md = BKE_modifiers_get_virtual_modifierlist(object, &virtualModifierData);
-
- /* Evaluate modifiers. */
- for (; md; md = md->next) {
- const ModifierTypeInfo *mti = BKE_modifier_get_info(static_cast<ModifierType>(md->type));
-
- if (!BKE_modifier_is_enabled(scene, md, required_mode)) {
- continue;
- }
-
- if ((mti->type == eModifierTypeType_OnlyDeform) &&
- (mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly)) {
- /* Ensure we are not modifying the input. */
- if (hair == hair_input) {
- hair = BKE_hair_copy_for_eval(hair, true);
- }
-
- /* Ensure we are not overwriting referenced data. */
- CustomData_duplicate_referenced_layer_named(
- &hair->pdata, CD_PROP_FLOAT3, HAIR_ATTR_POSITION, hair->totpoint);
- BKE_hair_update_customdata_pointers(hair);
-
- /* Created deformed coordinates array on demand. */
- mti->deformVerts(md, &mectx, nullptr, hair->co, hair->totpoint);
- }
- else if (mti->modifyHair) {
- /* Ensure we are not modifying the input. */
- if (hair == hair_input) {
- hair = BKE_hair_copy_for_eval(hair, true);
- }
-
- Hair *hair_next = mti->modifyHair(md, &mectx, hair);
-
- if (hair_next && hair_next != hair) {
- /* If the modifier returned a new hair, release the old one. */
- if (hair != hair_input) {
- BKE_id_free(nullptr, hair);
- }
- hair = hair_next;
- }
- }
- }
-
- return hair;
-}
-
-void BKE_hair_data_update(struct Depsgraph *depsgraph, struct Scene *scene, Object *object)
-{
- /* Free any evaluated data and restore original data. */
- BKE_object_free_derived_caches(object);
-
- /* Evaluate modifiers. */
- Hair *hair = static_cast<Hair *>(object->data);
- Hair *hair_eval = hair_evaluate_modifiers(depsgraph, scene, object, hair);
-
- /* Assign evaluated object. */
- const bool is_owned = (hair != hair_eval);
- BKE_object_eval_assign_data(object, &hair_eval->id, is_owned);
-}
-
-/* Draw Cache */
-
-void (*BKE_hair_batch_cache_dirty_tag_cb)(Hair *hair, int mode) = nullptr;
-void (*BKE_hair_batch_cache_free_cb)(Hair *hair) = nullptr;
-
-void BKE_hair_batch_cache_dirty_tag(Hair *hair, int mode)
-{
- if (hair->batch_cache) {
- BKE_hair_batch_cache_dirty_tag_cb(hair, mode);
- }
-}
-
-void BKE_hair_batch_cache_free(Hair *hair)
-{
- if (hair->batch_cache) {
- BKE_hair_batch_cache_free_cb(hair);
- }
-}
diff --git a/source/blender/blenkernel/intern/idtype.c b/source/blender/blenkernel/intern/idtype.c
index e6fd6c14d42..98bbd920615 100644
--- a/source/blender/blenkernel/intern/idtype.c
+++ b/source/blender/blenkernel/intern/idtype.c
@@ -15,9 +15,6 @@
*
* The Original Code is Copyright (C) 2005 by the Blender Foundation.
* All rights reserved.
- * Modifier stack implementation.
- *
- * BKE_modifier.h contains the function prototypes for this file.
*/
/** \file
@@ -110,7 +107,7 @@ static void id_type_init(void)
INIT_TYPE(ID_CF);
INIT_TYPE(ID_WS);
INIT_TYPE(ID_LP);
- INIT_TYPE(ID_HA);
+ INIT_TYPE(ID_CV);
INIT_TYPE(ID_PT);
INIT_TYPE(ID_VO);
INIT_TYPE(ID_SIM);
@@ -237,7 +234,7 @@ uint64_t BKE_idtype_idcode_to_idfilter(const short idcode)
CASE_IDFILTER(CU);
CASE_IDFILTER(GD);
CASE_IDFILTER(GR);
- CASE_IDFILTER(HA);
+ CASE_IDFILTER(CV);
CASE_IDFILTER(IM);
CASE_IDFILTER(LA);
CASE_IDFILTER(LS);
@@ -286,7 +283,7 @@ short BKE_idtype_idcode_from_idfilter(const uint64_t idfilter)
CASE_IDFILTER(CU);
CASE_IDFILTER(GD);
CASE_IDFILTER(GR);
- CASE_IDFILTER(HA);
+ CASE_IDFILTER(CV);
CASE_IDFILTER(IM);
CASE_IDFILTER(LA);
CASE_IDFILTER(LS);
@@ -334,7 +331,7 @@ int BKE_idtype_idcode_to_index(const short idcode)
CASE_IDINDEX(CU);
CASE_IDINDEX(GD);
CASE_IDINDEX(GR);
- CASE_IDINDEX(HA);
+ CASE_IDINDEX(CV);
CASE_IDINDEX(IM);
CASE_IDINDEX(IP);
CASE_IDINDEX(KE);
@@ -393,7 +390,7 @@ short BKE_idtype_idcode_from_index(const int index)
CASE_IDCODE(CU);
CASE_IDCODE(GD);
CASE_IDCODE(GR);
- CASE_IDCODE(HA);
+ CASE_IDCODE(CV);
CASE_IDCODE(IM);
CASE_IDCODE(IP);
CASE_IDCODE(KE);
diff --git a/source/blender/blenkernel/intern/image_partial_update.cc b/source/blender/blenkernel/intern/image_partial_update.cc
index 7e187c2014e..876e5276e5a 100644
--- a/source/blender/blenkernel/intern/image_partial_update.cc
+++ b/source/blender/blenkernel/intern/image_partial_update.cc
@@ -23,8 +23,8 @@
* image that are changed. These areas are organized in chunks. Changes that happen over time are
* organized in changesets.
*
- * A common usecase is to update GPUTexture for drawing where only that part is uploaded that only
- * changed.
+ * A common use case is to update #GPUTexture for drawing where only that part is uploaded that
+ * only changed.
*
* Usage:
*
@@ -273,7 +273,8 @@ struct TileChangeset {
const int previous_chunk_len = chunk_dirty_flags_.size();
chunk_dirty_flags_.resize(chunk_len);
- /* Fast exit. When the changeset was already empty no need to re-init the chunk_validity. */
+ /* Fast exit. When the changeset was already empty no need to
+ * re-initialize the chunk_validity. */
if (!has_dirty_chunks()) {
return;
}
diff --git a/source/blender/blenkernel/intern/image_partial_update_test.cc b/source/blender/blenkernel/intern/image_partial_update_test.cc
index 70aa51f7c98..bf12c27241e 100644
--- a/source/blender/blenkernel/intern/image_partial_update_test.cc
+++ b/source/blender/blenkernel/intern/image_partial_update_test.cc
@@ -70,7 +70,7 @@ class ImagePartialUpdateTest : public testing::Test {
IMB_init();
bmain = BKE_main_new();
- /* Creating an image generates a mem-leak during tests. */
+ /* Creating an image generates a memory-leak during tests. */
image = create_test_image(1024, 1024);
image_tile = BKE_image_get_tile(image, 0);
image_buffer = BKE_image_acquire_ibuf(image, nullptr, nullptr);
diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c
index 49a518607f1..6c19c7a328b 100644
--- a/source/blender/blenkernel/intern/lib_id.c
+++ b/source/blender/blenkernel/intern/lib_id.c
@@ -1918,7 +1918,6 @@ void BKE_library_make_local(Main *bmain,
* but complicates slightly the pre-processing of relations between IDs at step 2... */
else if (!do_skip && id->tag & (LIB_TAG_EXTERN | LIB_TAG_INDIRECT | LIB_TAG_NEW) &&
ELEM(lib, NULL, id->lib) &&
- !(GS(id->name) == ID_OB && ((Object *)id)->proxy_from != NULL) &&
((untagged_only == false) || !(id->tag & LIB_TAG_PRE_EXISTING))) {
BLI_linklist_prepend_arena(&todo_ids, id, linklist_mem);
id->tag |= LIB_TAG_DOIT;
@@ -1982,12 +1981,8 @@ void BKE_library_make_local(Main *bmain,
}
}
else {
- /* In this specific case, we do want to make ID local even if it has no local usage yet...
- * Note that for objects, we don't want proxy pointers to be cleared yet. This will happen
- * down the road in this function.
- */
- BKE_lib_id_make_local(
- bmain, id, LIB_ID_MAKELOCAL_FULL_LIBRARY | LIB_ID_MAKELOCAL_OBJECT_NO_PROXY_CLEARING);
+ /* In this specific case, we do want to make ID local even if it has no local usage yet... */
+ BKE_lib_id_make_local(bmain, id, LIB_ID_MAKELOCAL_FULL_LIBRARY);
if (id->newid) {
if (GS(id->newid->name) == ID_OB) {
@@ -2049,62 +2044,6 @@ void BKE_library_make_local(Main *bmain,
TIMEIT_VALUE_PRINT(make_local);
#endif
- /* Step 5: proxy 'remapping' hack. */
- for (LinkNode *it = copied_ids; it; it = it->next) {
- ID *id = it->link;
-
- /* Attempt to re-link copied proxy objects. This allows appending of an entire scene
- * from another blend file into this one, even when that blend file contains proxified
- * armatures that have local references. Since the proxified object needs to be linked
- * (not local), this will only work when the "Localize all" checkbox is disabled.
- * TL;DR: this is a dirty hack on top of an already weak feature (proxies). */
- if (GS(id->name) == ID_OB && ((Object *)id)->proxy != NULL) {
- Object *ob = (Object *)id;
- Object *ob_new = (Object *)id->newid;
- bool is_local = false, is_lib = false;
-
- /* Proxies only work when the proxified object is linked-in from a library. */
- if (!ID_IS_LINKED(ob->proxy)) {
- CLOG_WARN(&LOG,
- "proxy object %s will lose its link to %s, because the "
- "proxified object is local.",
- id->newid->name,
- ob->proxy->id.name);
- continue;
- }
-
- BKE_library_ID_test_usages(bmain, id, &is_local, &is_lib);
-
- /* We can only switch the proxy'ing to a made-local proxy if it is no longer
- * referred to from a library. Not checking for local use; if new local proxy
- * was not used locally would be a nasty bug! */
- if (is_local || is_lib) {
- CLOG_WARN(&LOG,
- "made-local proxy object %s will lose its link to %s, "
- "because the linked-in proxy is referenced (is_local=%i, is_lib=%i).",
- id->newid->name,
- ob->proxy->id.name,
- is_local,
- is_lib);
- }
- else {
- /* we can switch the proxy'ing from the linked-in to the made-local proxy.
- * BKE_object_make_proxy() shouldn't be used here, as it allocates memory that
- * was already allocated by object_make_local() (which called BKE_object_copy). */
- ob_new->proxy = ob->proxy;
- ob_new->proxy_group = ob->proxy_group;
- ob_new->proxy_from = ob->proxy_from;
- ob_new->proxy->proxy_from = ob_new;
- ob->proxy = ob->proxy_from = ob->proxy_group = NULL;
- }
- }
- }
-
-#ifdef DEBUG_TIME
- printf("Step 5: Proxy 'remapping' hack: Done.\n");
- TIMEIT_VALUE_PRINT(make_local);
-#endif
-
/* This is probably more of a hack than something we should do here, but...
* Issue is, the whole copying + remapping done in complex cases above may leave pose-channels
* of armatures in complete invalid state (more precisely, the bone pointers of the
diff --git a/source/blender/blenkernel/intern/lib_id_delete.c b/source/blender/blenkernel/intern/lib_id_delete.c
index f4dd67cac28..5db70d85e71 100644
--- a/source/blender/blenkernel/intern/lib_id_delete.c
+++ b/source/blender/blenkernel/intern/lib_id_delete.c
@@ -265,8 +265,8 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
}
for (id = last_remapped_id->next; id; id = id->next) {
/* Will tag 'never NULL' users of this ID too.
- * Note that we cannot use BKE_libblock_unlink() here,
- * since it would ignore indirect (and proxy!)
+ *
+ * NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect
* links, this can lead to nasty crashing here in second, actual deleting loop.
* Also, this will also flag users of deleted data that cannot be unlinked
* (object using deleted obdata, etc.), so that they also get deleted. */
@@ -315,9 +315,9 @@ static size_t id_delete(Main *bmain, const bool do_tagged_deletion)
}
/* Will tag 'never NULL' users of this ID too.
- * Note that we cannot use BKE_libblock_unlink() here, since it would ignore indirect
- * (and proxy!) links, this can lead to nasty crashing here in second,
- * actual deleting loop.
+ *
+ * NOTE: #BKE_libblock_unlink() cannot be used here, since it would ignore indirect
+ * links, this can lead to nasty crashing here in second, actual deleting loop.
* Also, this will also flag users of deleted data that cannot be unlinked
* (object using deleted obdata, etc.), so that they also get deleted. */
BKE_libblock_remap_multiple_locked(bmain,
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index 649e7dab5d1..59cb6b2036e 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -161,6 +161,8 @@ void BKE_lib_override_library_copy(ID *dst_id, const ID *src_id, const bool do_f
(ID *)src_id;
id_us_plus(dst_id->override_library->reference);
+ dst_id->override_library->hierarchy_root = src_id->override_library->hierarchy_root;
+
if (do_full_copy) {
BLI_duplicatelist(&dst_id->override_library->properties,
&src_id->override_library->properties);
@@ -211,6 +213,7 @@ void BKE_lib_override_library_free(struct IDOverrideLibrary **override, const bo
}
static ID *lib_override_library_create_from(Main *bmain,
+ Library *owner_library,
ID *reference_id,
const int lib_id_copy_flags)
{
@@ -227,6 +230,12 @@ static ID *lib_override_library_create_from(Main *bmain,
}
id_us_min(local_id);
+ /* TODO: Handle this properly in LIB_NO_MAIN case as well (i.e. resync case). Or offload to
+ * generic ID copy code? */
+ if ((lib_id_copy_flags & LIB_ID_CREATE_NO_MAIN) == 0) {
+ local_id->lib = owner_library;
+ }
+
BKE_lib_override_library_init(local_id, reference_id);
/* NOTE: From liboverride perspective (and RNA one), shape keys are considered as local embedded
@@ -281,11 +290,12 @@ ID *BKE_lib_override_library_create_from_id(Main *bmain,
BLI_assert(reference_id != NULL);
BLI_assert(ID_IS_LINKED(reference_id));
- ID *local_id = lib_override_library_create_from(bmain, reference_id, 0);
+ ID *local_id = lib_override_library_create_from(bmain, NULL, reference_id, 0);
/* We cannot allow automatic hierarchy resync on this ID, it is highly likely to generate a giant
* mess in case there are a lot of hidden, non-instantiated, non-properly organized dependencies.
* Ref T94650. */
local_id->override_library->flag |= IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY;
+ local_id->override_library->hierarchy_root = local_id;
if (do_tagged_remap) {
Key *reference_key, *local_key = NULL;
@@ -320,9 +330,19 @@ ID *BKE_lib_override_library_create_from_id(Main *bmain,
}
bool BKE_lib_override_library_create_from_tag(Main *bmain,
- const Library *reference_library,
+ Library *owner_library,
+ const ID *id_root_reference,
+ ID *id_hierarchy_root,
const bool do_no_main)
{
+ BLI_assert(id_root_reference != NULL);
+ BLI_assert(id_hierarchy_root != NULL || (id_root_reference->tag & LIB_TAG_DOIT) != 0);
+ BLI_assert(id_hierarchy_root == NULL ||
+ (ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root) &&
+ id_hierarchy_root->override_library->reference == id_root_reference));
+
+ const Library *reference_library = id_root_reference->lib;
+
ID *reference_id;
bool success = true;
@@ -351,7 +371,7 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain,
* This requires extra care further down the resync process,
* see: #BKE_lib_override_library_resync. */
reference_id->newid = lib_override_library_create_from(
- bmain, reference_id, do_no_main ? LIB_ID_CREATE_NO_MAIN : 0);
+ bmain, owner_library, reference_id, do_no_main ? LIB_ID_CREATE_NO_MAIN : 0);
if (reference_id->newid == NULL) {
success = false;
break;
@@ -375,6 +395,11 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain,
/* Only remap new local ID's pointers, we don't want to force our new overrides onto our whole
* existing linked IDs usages. */
if (success) {
+ if (id_root_reference->newid != NULL) {
+ id_hierarchy_root = id_root_reference->newid;
+ }
+ BLI_assert(id_hierarchy_root != NULL);
+
for (todo_id_iter = todo_ids.first; todo_id_iter != NULL; todo_id_iter = todo_id_iter->next) {
reference_id = todo_id_iter->data;
ID *local_id = reference_id->newid;
@@ -383,6 +408,8 @@ bool BKE_lib_override_library_create_from_tag(Main *bmain,
continue;
}
+ local_id->override_library->hierarchy_root = id_hierarchy_root;
+
Key *reference_key, *local_key = NULL;
if ((reference_key = BKE_key_from_id(reference_id)) != NULL) {
local_key = BKE_key_from_id(reference_id->newid);
@@ -451,6 +478,7 @@ typedef struct LibOverrideGroupTagData {
Main *bmain;
Scene *scene;
ID *id_root;
+ ID *hierarchy_root_id;
uint tag;
uint missing_tag;
/* Whether we are looping on override data, or their references (linked) one. */
@@ -761,6 +789,8 @@ static void lib_override_overrides_group_tag_recursive(LibOverrideGroupTagData *
BLI_assert(ID_IS_OVERRIDE_LIBRARY(id_owner));
BLI_assert(data->is_override);
+ ID *id_hierarchy_root = data->hierarchy_root_id;
+
if (ID_IS_OVERRIDE_LIBRARY_REAL(id_owner) &&
(id_owner->override_library->flag & IDOVERRIDE_LIBRARY_FLAG_NO_HIERARCHY) != 0) {
return;
@@ -792,9 +822,15 @@ static void lib_override_overrides_group_tag_recursive(LibOverrideGroupTagData *
if (ELEM(to_id, NULL, id_owner)) {
continue;
}
+ /* Different libraries or different hierarchy roots are break points in override hierarchies.
+ */
if (!ID_IS_OVERRIDE_LIBRARY(to_id) || (to_id->lib != id_owner->lib)) {
continue;
}
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(to_id) &&
+ to_id->override_library->hierarchy_root != id_hierarchy_root) {
+ continue;
+ }
Library *reference_lib = lib_override_get(bmain, id_owner)->reference->lib;
ID *to_id_reference = lib_override_get(bmain, to_id)->reference;
@@ -824,6 +860,11 @@ static void lib_override_overrides_group_tag(LibOverrideGroupTagData *data)
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_root));
BLI_assert(data->is_override);
+ ID *id_hierarchy_root = data->hierarchy_root_id;
+ BLI_assert(id_hierarchy_root != NULL);
+ BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id_hierarchy_root));
+ UNUSED_VARS_NDEBUG(id_hierarchy_root);
+
if (id_root->override_library->reference->tag & LIB_TAG_MISSING) {
id_root->tag |= data->missing_tag;
}
@@ -835,7 +876,10 @@ static void lib_override_overrides_group_tag(LibOverrideGroupTagData *data)
lib_override_overrides_group_tag_recursive(data);
}
-static bool lib_override_library_create_do(Main *bmain, Scene *scene, ID *id_root)
+static bool lib_override_library_create_do(Main *bmain,
+ Scene *scene,
+ Library *owner_library,
+ ID *id_root)
{
BKE_main_relations_create(bmain, 0);
LibOverrideGroupTagData data = {.bmain = bmain,
@@ -854,12 +898,16 @@ static bool lib_override_library_create_do(Main *bmain, Scene *scene, ID *id_roo
BKE_main_relations_free(bmain);
lib_override_group_tag_data_clear(&data);
- return BKE_lib_override_library_create_from_tag(bmain, id_root->lib, false);
+ const bool success = BKE_lib_override_library_create_from_tag(
+ bmain, owner_library, id_root, NULL, false);
+
+ return success;
}
static void lib_override_library_create_post_process(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
+ const Library *owner_library,
ID *id_root,
ID *id_reference,
Collection *residual_storage,
@@ -881,7 +929,8 @@ static void lib_override_library_create_post_process(Main *bmain,
/* Instantiating the root collection or object should never be needed in resync case, since the
* old override would be remapped to the new one. */
- if (!is_resync && id_root != NULL && id_root->newid != NULL && !ID_IS_LINKED(id_root->newid)) {
+ if (!is_resync && id_root != NULL && id_root->newid != NULL &&
+ (!ID_IS_LINKED(id_root->newid) || id_root->newid->lib == owner_library)) {
switch (GS(id_root->name)) {
case ID_GR: {
Object *ob_reference = id_reference != NULL && GS(id_reference->name) == ID_OB ?
@@ -926,7 +975,7 @@ static void lib_override_library_create_post_process(Main *bmain,
Collection *default_instantiating_collection = residual_storage;
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
Object *ob_new = (Object *)ob->id.newid;
- if (ob_new == NULL || ID_IS_LINKED(ob_new)) {
+ if (ob_new == NULL || (ID_IS_LINKED(ob_new) && ob_new->id.lib != owner_library)) {
continue;
}
@@ -989,6 +1038,7 @@ static void lib_override_library_create_post_process(Main *bmain,
bool BKE_lib_override_library_create(Main *bmain,
Scene *scene,
ViewLayer *view_layer,
+ Library *owner_library,
ID *id_root,
ID *id_reference,
ID **r_id_root_override)
@@ -997,7 +1047,7 @@ bool BKE_lib_override_library_create(Main *bmain,
*r_id_root_override = NULL;
}
- const bool success = lib_override_library_create_do(bmain, scene, id_root);
+ const bool success = lib_override_library_create_do(bmain, scene, owner_library, id_root);
if (!success) {
return success;
@@ -1008,7 +1058,7 @@ bool BKE_lib_override_library_create(Main *bmain,
}
lib_override_library_create_post_process(
- bmain, scene, view_layer, id_root, id_reference, NULL, false);
+ bmain, scene, view_layer, owner_library, id_root, id_reference, NULL, false);
/* Cleanup. */
BKE_main_id_newptr_and_tag_clear(bmain);
@@ -1033,120 +1083,187 @@ bool BKE_lib_override_library_template_create(struct ID *id)
return true;
}
-bool BKE_lib_override_library_proxy_convert(Main *bmain,
- Scene *scene,
- ViewLayer *view_layer,
- Object *ob_proxy)
+static ID *lib_override_root_find(Main *bmain, ID *id, const int curr_level, int *r_best_level)
{
- /* `proxy_group`, if defined, is the empty instantiating the collection from which the proxy is
- * coming. */
- Object *ob_proxy_group = ob_proxy->proxy_group;
- const bool is_override_instancing_object = ob_proxy_group != NULL;
- ID *id_root = is_override_instancing_object ? &ob_proxy_group->instance_collection->id :
- &ob_proxy->proxy->id;
- ID *id_reference = is_override_instancing_object ? &ob_proxy_group->id : &ob_proxy->id;
+ if (curr_level > 1000) {
+ CLOG_ERROR(&LOG,
+ "Levels of dependency relationships between library overrides IDs is way too high, "
+ "skipping further processing loops (involves at least '%s')",
+ id->name);
+ BLI_assert(0);
+ return NULL;
+ }
- /* In some cases the instance collection of a proxy object may be local (see e.g. T83875). Not
- * sure this is a valid state, but for now just abort the overriding process. */
- if (!ID_IS_OVERRIDABLE_LIBRARY(id_root)) {
- return false;
+ if (!ID_IS_OVERRIDE_LIBRARY(id)) {
+ BLI_assert(0);
+ return NULL;
}
- /* We manually convert the proxy object into a library override, further override handling will
- * then be handled by `BKE_lib_override_library_create()` just as for a regular override
- * creation.
- */
- ob_proxy->proxy->id.tag |= LIB_TAG_DOIT;
- ob_proxy->proxy->id.newid = &ob_proxy->id;
- BKE_lib_override_library_init(&ob_proxy->id, &ob_proxy->proxy->id);
+ MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, id);
+ BLI_assert(entry != NULL);
- ob_proxy->proxy->proxy_from = NULL;
- ob_proxy->proxy = ob_proxy->proxy_group = NULL;
+ int best_level_candidate = curr_level;
+ ID *best_root_id_candidate = id;
- DEG_id_tag_update(&ob_proxy->id, ID_RECALC_COPY_ON_WRITE);
+ for (MainIDRelationsEntryItem *from_id_entry = entry->from_ids; from_id_entry != NULL;
+ from_id_entry = from_id_entry->next) {
+ if ((from_id_entry->usage_flag & IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE) != 0) {
+ /* Never consider non-overridable relationships as actual dependencies. */
+ continue;
+ }
+
+ ID *from_id = from_id_entry->id_pointer.from;
+ if (ELEM(from_id, NULL, id)) {
+ continue;
+ }
+ if (!ID_IS_OVERRIDE_LIBRARY(from_id) || (from_id->lib != id->lib)) {
+ continue;
+ }
- /* In case of proxy conversion, remap all local ID usages to linked IDs to their newly created
- * overrides.
- * While this might not be 100% the desired behavior, it is likely to be the case most of the
- * time. Ref: T91711. */
- ID *id_iter;
- FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
- if (!ID_IS_LINKED(id_iter)) {
- id_iter->tag |= LIB_TAG_DOIT;
+ int level_candidate = curr_level + 1;
+ /* Recursively process the parent. */
+ ID *root_id_candidate = lib_override_root_find(
+ bmain, from_id, curr_level + 1, &level_candidate);
+ if (level_candidate > best_level_candidate && root_id_candidate != NULL) {
+ best_root_id_candidate = root_id_candidate;
+ best_level_candidate = level_candidate;
}
}
- FOREACH_MAIN_ID_END;
- return BKE_lib_override_library_create(bmain, scene, view_layer, id_root, id_reference, NULL);
+ *r_best_level = best_level_candidate;
+ return best_root_id_candidate;
}
-static void lib_override_library_proxy_convert_do(Main *bmain,
- Scene *scene,
- Object *ob_proxy,
- BlendFileReadReport *reports)
+static void lib_override_root_hierarchy_set(Main *bmain, ID *id_root, ID *id, ID *id_from)
{
- Object *ob_proxy_group = ob_proxy->proxy_group;
- const bool is_override_instancing_object = ob_proxy_group != NULL;
+ if (ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ if (id->override_library->hierarchy_root == id_root) {
+ /* Already set, nothing else to do here, sub-hierarchy is also assumed to be properly set
+ * then. */
+ return;
+ }
- const bool success = BKE_lib_override_library_proxy_convert(bmain, scene, NULL, ob_proxy);
+ /* Hierarchy root already set, and not matching currently proposed one, try to find which is
+ * best. */
+ if (id->override_library->hierarchy_root != NULL) {
+ /* Check if given `id_from` matches with the hierarchy of the linked reference ID, in which
+ * case we assume that the given hierarchy root is the 'real' one.
+ *
+ * NOTE: This can fail if user mixed dependencies between several overrides of a same
+ * reference linked hierarchy. Not much to be done in that case, it's virtually impossible to
+ * fix this automatically in a reliable way. */
+ if (id_from == NULL || !ID_IS_OVERRIDE_LIBRARY_REAL(id_from)) {
+ /* Too complicated to deal with for now. */
+ CLOG_WARN(&LOG,
+ "Inconsistency in library override hierarchy of ID '%s'.\n"
+ "\tNot enough data to verify validity of current proposed root '%s', assuming "
+ "already set one '%s' is valid.",
+ id->name,
+ id_root->name,
+ id->override_library->hierarchy_root->name);
+ return;
+ }
- if (success) {
- CLOG_INFO(&LOG,
- 4,
- "Proxy object '%s' successfully converted to library overrides",
- ob_proxy->id.name);
- /* Remove the instance empty from this scene, the items now have an overridden collection
- * instead. */
- if (is_override_instancing_object) {
- BKE_scene_collections_object_remove(bmain, scene, ob_proxy_group, true);
- }
- reports->count.proxies_to_lib_overrides_success++;
- }
-}
+ ID *id_from_ref = id_from->override_library->reference;
+ MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers,
+ id->override_library->reference);
+ BLI_assert(entry != NULL);
-void BKE_lib_override_library_main_proxy_convert(Main *bmain, BlendFileReadReport *reports)
-{
- LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
- LinkNodePair proxy_objects = {NULL};
+ bool do_replace_root = false;
+ for (MainIDRelationsEntryItem *from_id_entry = entry->from_ids; from_id_entry != NULL;
+ from_id_entry = from_id_entry->next) {
+ if ((from_id_entry->usage_flag & IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE) != 0) {
+ /* Never consider non-overridable relationships as actual dependencies. */
+ continue;
+ }
- FOREACH_SCENE_OBJECT_BEGIN (scene, object) {
- if (object->proxy_group != NULL) {
- BLI_linklist_append(&proxy_objects, object);
+ if (id_from_ref == from_id_entry->id_pointer.from) {
+ /* A matching parent was found in reference linked data, assume given hierarchy root is
+ * the valid one. */
+ do_replace_root = true;
+ CLOG_WARN(
+ &LOG,
+ "Inconsistency in library override hierarchy of ID '%s'.\n"
+ "\tCurrent proposed root '%s' detected as valid, will replace already set one '%s'.",
+ id->name,
+ id_root->name,
+ id->override_library->hierarchy_root->name);
+ break;
+ }
}
- }
- FOREACH_SCENE_OBJECT_END;
- FOREACH_SCENE_OBJECT_BEGIN (scene, object) {
- if (object->proxy != NULL && object->proxy_group == NULL) {
- BLI_linklist_append(&proxy_objects, object);
+ if (!do_replace_root) {
+ CLOG_WARN(
+ &LOG,
+ "Inconsistency in library override hierarchy of ID '%s'.\n"
+ "\tCurrent proposed root '%s' not detected as valid, keeping already set one '%s'.",
+ id->name,
+ id_root->name,
+ id->override_library->hierarchy_root->name);
+ return;
}
}
- FOREACH_SCENE_OBJECT_END;
- for (LinkNode *proxy_object_iter = proxy_objects.list; proxy_object_iter != NULL;
- proxy_object_iter = proxy_object_iter->next) {
- Object *proxy_object = proxy_object_iter->link;
- lib_override_library_proxy_convert_do(bmain, scene, proxy_object, reports);
+ id->override_library->hierarchy_root = id_root;
+ }
+
+ MainIDRelationsEntry *entry = BLI_ghash_lookup(bmain->relations->relations_from_pointers, id);
+ BLI_assert(entry != NULL);
+
+ for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != NULL;
+ to_id_entry = to_id_entry->next) {
+ if ((to_id_entry->usage_flag & IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE) != 0) {
+ /* Never consider non-overridable relationships as actual dependencies. */
+ continue;
}
- BLI_linklist_free(proxy_objects.list, NULL);
+ ID *to_id = *to_id_entry->id_pointer.to;
+ if (ELEM(to_id, NULL, id)) {
+ continue;
+ }
+ if (!ID_IS_OVERRIDE_LIBRARY(to_id) || (to_id->lib != id->lib)) {
+ continue;
+ }
+
+ /* Recursively process the sub-hierarchy. */
+ lib_override_root_hierarchy_set(bmain, id_root, to_id, id);
}
+}
- LISTBASE_FOREACH (Object *, object, &bmain->objects) {
- if (ID_IS_LINKED(object)) {
- if (object->proxy != NULL) {
- CLOG_WARN(&LOG, "Did not try to convert linked proxy object '%s'", object->id.name);
- reports->count.linked_proxies++;
- }
+void BKE_lib_override_library_main_hierarchy_root_ensure(Main *bmain)
+{
+ ID *id;
+
+ BKE_main_relations_create(bmain, 0);
+
+ FOREACH_MAIN_ID_BEGIN (bmain, id) {
+ if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
continue;
}
+ if (id->override_library->hierarchy_root != NULL) {
+ continue;
+ }
+
+ int best_level = 0;
+ ID *id_root = lib_override_root_find(bmain, id, best_level, &best_level);
- if (object->proxy_group != NULL || object->proxy != NULL) {
- CLOG_WARN(
- &LOG, "Proxy object '%s' failed to be converted to library override", object->id.name);
- reports->count.proxies_to_lib_overrides_failures++;
+ if (!ELEM(id_root->override_library->hierarchy_root, id_root, NULL)) {
+ CLOG_WARN(&LOG,
+ "Potential inconsistency in library override hierarchy of ID '%s', detected as "
+ "part of the hierarchy of '%s', which has a different root '%s'",
+ id->name,
+ id_root->name,
+ id_root->override_library->hierarchy_root->name);
+ continue;
}
+
+ lib_override_root_hierarchy_set(bmain, id_root, id_root, NULL);
+
+ BLI_assert(id->override_library->hierarchy_root != NULL);
}
+ FOREACH_MAIN_ID_END;
+
+ BKE_main_relations_free(bmain);
}
static void lib_override_library_remap(Main *bmain,
@@ -1214,6 +1331,7 @@ static bool lib_override_library_resync(Main *bmain,
LibOverrideGroupTagData data = {.bmain = bmain,
.scene = scene,
.id_root = id_root,
+ .hierarchy_root_id = id_root->override_library->hierarchy_root,
.tag = LIB_TAG_DOIT,
.missing_tag = LIB_TAG_MISSING,
.is_override = true,
@@ -1316,7 +1434,7 @@ static bool lib_override_library_resync(Main *bmain,
* override IDs (including within the old overrides themselves, since those are tagged too
* above). */
const bool success = BKE_lib_override_library_create_from_tag(
- bmain, id_root_reference->lib, true);
+ bmain, NULL, id_root_reference, id_root->override_library->hierarchy_root, true);
if (!success) {
return success;
@@ -1530,6 +1648,7 @@ static bool lib_override_library_resync(Main *bmain,
lib_override_library_create_post_process(bmain,
scene,
view_layer,
+ NULL,
id_root_reference,
id_root,
override_resync_residual_storage,
@@ -1634,46 +1753,20 @@ static void lib_override_resync_tagging_finalize_recurse(Main *bmain,
*
* NOTE: Related to `lib_override_resync_tagging_finalize` above.
*/
-static ID *lib_override_library_main_resync_find_root_recurse(ID *id, int *level)
-{
- (*level)++;
- ID *return_id = id;
-
- switch (GS(id->name)) {
- case ID_GR: {
- /* Find the highest valid collection in the parenting hierarchy.
- * Note that in practice, in any decent common case there is only one well defined root
- * collection anyway. */
- int max_level = *level;
- Collection *collection = (Collection *)id;
- LISTBASE_FOREACH (CollectionParent *, collection_parent_iter, &collection->parents) {
- Collection *collection_parent = collection_parent_iter->collection;
- if (ID_IS_OVERRIDE_LIBRARY_REAL(collection_parent) &&
- collection_parent->id.lib == id->lib) {
- int tmp_level = *level;
- ID *tmp_id = lib_override_library_main_resync_find_root_recurse(&collection_parent->id,
- &tmp_level);
- if (tmp_level > max_level) {
- max_level = tmp_level;
- return_id = tmp_id;
- }
- }
- }
- break;
- }
- case ID_OB: {
- Object *object = (Object *)id;
- if (object->parent != NULL && ID_IS_OVERRIDE_LIBRARY_REAL(object->parent) &&
- object->parent->id.lib == id->lib) {
- return_id = lib_override_library_main_resync_find_root_recurse(&object->parent->id, level);
- }
- break;
+static ID *lib_override_library_main_resync_root_get(Main *bmain, ID *id)
+{
+ if (!ID_IS_OVERRIDE_LIBRARY_REAL(id)) {
+ const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
+ if (id_type->owner_get != NULL) {
+ id = id_type->owner_get(bmain, id);
}
- default:
- break;
+ BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id));
}
- return return_id;
+ ID *hierarchy_root_id = id->override_library->hierarchy_root;
+ BLI_assert(hierarchy_root_id != NULL);
+ BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(hierarchy_root_id));
+ return hierarchy_root_id;
}
/* Ensure resync of all overrides at one level of indirect usage.
@@ -1815,14 +1908,13 @@ static void lib_override_library_main_resync_on_library_indirect_level(
Library *library = id->lib;
- int level = 0;
/* In complex non-supported cases, with several different override hierarchies sharing
* relations between each-other, we may end up not actually updating/replacing the given
* root id (see e.g. pro/shots/110_rextoria/110_0150_A/110_0150_A.anim.blend of sprites
* project repository, r2687).
* This can lead to infinite loop here, at least avoid this. */
id->tag &= ~LIB_TAG_LIB_OVERRIDE_NEED_RESYNC;
- id = lib_override_library_main_resync_find_root_recurse(id, &level);
+ id = lib_override_library_main_resync_root_get(bmain, id);
id->tag &= ~LIB_TAG_LIB_OVERRIDE_NEED_RESYNC;
BLI_assert(ID_IS_OVERRIDE_LIBRARY_REAL(id));
BLI_assert(id->lib == library);
@@ -1863,7 +1955,8 @@ static int lib_override_sort_libraries_func(LibraryIDLinkCallbackData *cb_data)
ID *id_owner = cb_data->id_owner;
ID *id = *cb_data->id_pointer;
if (id != NULL && ID_IS_LINKED(id) && id->lib != id_owner->lib) {
- const int owner_library_indirect_level = id_owner->lib != NULL ? id_owner->lib->temp_index : 0;
+ const int owner_library_indirect_level = ID_IS_LINKED(id_owner) ? id_owner->lib->temp_index :
+ 0;
if (owner_library_indirect_level > 10000) {
CLOG_ERROR(
&LOG,
@@ -1954,7 +2047,7 @@ void BKE_lib_override_library_main_resync(Main *bmain,
/* Essentially ensures that potentially new overrides of new objects will be instantiated. */
lib_override_library_create_post_process(
- bmain, scene, view_layer, NULL, NULL, override_resync_residual_storage, true);
+ bmain, scene, view_layer, NULL, NULL, NULL, override_resync_residual_storage, true);
if (BKE_collection_is_empty(override_resync_residual_storage)) {
BKE_collection_delete(bmain, override_resync_residual_storage, true);
@@ -1980,6 +2073,7 @@ void BKE_lib_override_library_delete(Main *bmain, ID *id_root)
LibOverrideGroupTagData data = {.bmain = bmain,
.scene = NULL,
.id_root = id_root,
+ .hierarchy_root_id = id_root->override_library->hierarchy_root,
.tag = LIB_TAG_DOIT,
.missing_tag = LIB_TAG_MISSING,
.is_override = true,
@@ -2904,6 +2998,8 @@ void BKE_lib_override_library_update(Main *bmain, ID *local)
return;
}
+ tmp_id->lib = local->lib;
+
/* This ID name is problematic, since it is an 'rna name property' it should not be editable or
* different from reference linked ID. But local ID names need to be unique in a given type
* list of Main, so we cannot always keep it identical, which is why we need this special
@@ -2916,6 +3012,7 @@ void BKE_lib_override_library_update(Main *bmain, ID *local)
Key *tmp_key = BKE_key_from_id(tmp_id);
if (local_key != NULL && tmp_key != NULL) {
tmp_key->id.flag |= (local_key->id.flag & LIB_EMBEDDED_DATA_LIB_OVERRIDE);
+ tmp_key->id.lib = local_key->id.lib;
}
PointerRNA rnaptr_src, rnaptr_dst, rnaptr_storage_stack, *rnaptr_storage = NULL;
diff --git a/source/blender/blenkernel/intern/lib_override_proxy_conversion.c b/source/blender/blenkernel/intern/lib_override_proxy_conversion.c
new file mode 100644
index 00000000000..d99a9b57a6e
--- /dev/null
+++ b/source/blender/blenkernel/intern/lib_override_proxy_conversion.c
@@ -0,0 +1,176 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * The Original Code is Copyright (C) 2016 by Blender Foundation.
+ * All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ */
+
+#include "CLG_log.h"
+
+#include "MEM_guardedalloc.h"
+
+#include "BLI_linklist.h"
+
+/* Required for proxy to liboverrides conversion code. */
+#define DNA_DEPRECATED_ALLOW
+
+#include "DNA_ID.h"
+#include "DNA_collection_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+
+#include "DEG_depsgraph.h"
+
+#include "BKE_collection.h"
+#include "BKE_idtype.h"
+#include "BKE_lib_id.h"
+#include "BKE_lib_override.h"
+#include "BKE_main.h"
+
+#include "BLO_readfile.h"
+
+static CLG_LogRef LOG = {"bke.liboverride_proxy_conversion"};
+
+bool BKE_lib_override_library_proxy_convert(Main *bmain,
+ Scene *scene,
+ ViewLayer *view_layer,
+ Object *ob_proxy)
+{
+ /* `proxy_group`, if defined, is the empty instantiating the collection from which the proxy is
+ * coming. */
+ Object *ob_proxy_group = ob_proxy->proxy_group;
+ const bool is_override_instancing_object = ob_proxy_group != NULL;
+ ID *id_root = is_override_instancing_object ? &ob_proxy_group->instance_collection->id :
+ &ob_proxy->proxy->id;
+ ID *id_reference = is_override_instancing_object ? &ob_proxy_group->id : &ob_proxy->id;
+
+ /* In some cases the instance collection of a proxy object may be local (see e.g. T83875). Not
+ * sure this is a valid state, but for now just abort the overriding process. */
+ if (!ID_IS_OVERRIDABLE_LIBRARY_HIERARCHY(id_root)) {
+ if (ob_proxy->proxy != NULL) {
+ ob_proxy->proxy->proxy_from = NULL;
+ }
+ id_us_min((ID *)ob_proxy->proxy);
+ ob_proxy->proxy = ob_proxy->proxy_group = NULL;
+ return false;
+ }
+
+ /* We manually convert the proxy object into a library override, further override handling will
+ * then be handled by `BKE_lib_override_library_create()` just as for a regular override
+ * creation.
+ */
+ ob_proxy->proxy->id.tag |= LIB_TAG_DOIT;
+ ob_proxy->proxy->id.newid = &ob_proxy->id;
+ BKE_lib_override_library_init(&ob_proxy->id, &ob_proxy->proxy->id);
+
+ ob_proxy->proxy->proxy_from = NULL;
+ ob_proxy->proxy = ob_proxy->proxy_group = NULL;
+
+ DEG_id_tag_update(&ob_proxy->id, ID_RECALC_COPY_ON_WRITE);
+
+ /* In case of proxy conversion, remap all local ID usages to linked IDs to their newly created
+ * overrides. Also do that for the IDs from the same lib as the proxy in case it is linked.
+ * While this might not be 100% the desired behavior, it is likely to be the case most of the
+ * time. Ref: T91711. */
+ ID *id_iter;
+ FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
+ if (!ID_IS_LINKED(id_iter) || id_iter->lib == ob_proxy->id.lib) {
+ id_iter->tag |= LIB_TAG_DOIT;
+ }
+ }
+ FOREACH_MAIN_ID_END;
+
+ return BKE_lib_override_library_create(
+ bmain, scene, view_layer, ob_proxy->id.lib, id_root, id_reference, NULL);
+}
+
+static void lib_override_library_proxy_convert_do(Main *bmain,
+ Scene *scene,
+ Object *ob_proxy,
+ BlendFileReadReport *reports)
+{
+ Object *ob_proxy_group = ob_proxy->proxy_group;
+ const bool is_override_instancing_object = ob_proxy_group != NULL;
+
+ const bool success = BKE_lib_override_library_proxy_convert(bmain, scene, NULL, ob_proxy);
+
+ if (success) {
+ CLOG_INFO(&LOG,
+ 4,
+ "Proxy object '%s' successfully converted to library overrides",
+ ob_proxy->id.name);
+ /* Remove the instance empty from this scene, the items now have an overridden collection
+ * instead. */
+ if (is_override_instancing_object) {
+ BKE_scene_collections_object_remove(bmain, scene, ob_proxy_group, true);
+ }
+ reports->count.proxies_to_lib_overrides_success++;
+ }
+}
+
+void BKE_lib_override_library_main_proxy_convert(Main *bmain, BlendFileReadReport *reports)
+{
+ LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
+ LinkNodePair proxy_objects = {NULL};
+
+ FOREACH_SCENE_OBJECT_BEGIN (scene, object) {
+ if (object->proxy_group != NULL) {
+ BLI_linklist_append(&proxy_objects, object);
+ }
+ }
+ FOREACH_SCENE_OBJECT_END;
+
+ FOREACH_SCENE_OBJECT_BEGIN (scene, object) {
+ if (object->proxy != NULL && object->proxy_group == NULL) {
+ BLI_linklist_append(&proxy_objects, object);
+ }
+ }
+ FOREACH_SCENE_OBJECT_END;
+
+ for (LinkNode *proxy_object_iter = proxy_objects.list; proxy_object_iter != NULL;
+ proxy_object_iter = proxy_object_iter->next) {
+ Object *proxy_object = proxy_object_iter->link;
+ lib_override_library_proxy_convert_do(bmain, scene, proxy_object, reports);
+ }
+
+ BLI_linklist_free(proxy_objects.list, NULL);
+ }
+
+ LISTBASE_FOREACH (Object *, object, &bmain->objects) {
+ if (object->proxy_group != NULL || object->proxy != NULL) {
+ if (ID_IS_LINKED(object)) {
+ CLOG_WARN(&LOG,
+ "Linked proxy object '%s' from '%s' failed to be converted to library override",
+ object->id.name + 2,
+ object->id.lib->filepath);
+ }
+ else {
+ CLOG_WARN(&LOG,
+ "Proxy object '%s' failed to be converted to library override",
+ object->id.name + 2);
+ }
+ reports->count.proxies_to_lib_overrides_failures++;
+ if (object->proxy != NULL) {
+ object->proxy->proxy_from = NULL;
+ }
+ id_us_min((ID *)object->proxy);
+ object->proxy = object->proxy_group = NULL;
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/lib_query.c b/source/blender/blenkernel/intern/lib_query.c
index 1f20a84098c..f49af9abffe 100644
--- a/source/blender/blenkernel/intern/lib_query.c
+++ b/source/blender/blenkernel/intern/lib_query.c
@@ -323,6 +323,8 @@ static bool library_foreach_ID_link(Main *bmain,
IDWALK_CB_USER | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE);
CALLBACK_INVOKE_ID(id->override_library->storage,
IDWALK_CB_USER | IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE);
+
+ CALLBACK_INVOKE_ID(id->override_library->hierarchy_root, IDWALK_CB_LOOPBACK);
}
IDP_foreach_property(id->properties,
@@ -471,7 +473,7 @@ bool BKE_library_id_can_use_idtype(ID *id_owner, const short id_type_used)
return ELEM(id_type_used, ID_MA);
case ID_WS:
return ELEM(id_type_used, ID_SCR, ID_SCE);
- case ID_HA:
+ case ID_CV:
return ELEM(id_type_used, ID_MA);
case ID_PT:
return ELEM(id_type_used, ID_MA);
@@ -517,7 +519,7 @@ static int foreach_libblock_id_users_callback(LibraryIDLinkCallbackData *cb_data
IDUsersIter *iter = cb_data->user_data;
if (*id_p) {
- /* 'Loopback' ID pointers (the ugly 'from' ones, Object->proxy_from and Key->from).
+ /* 'Loopback' ID pointers (the ugly 'from' ones, like Key->from).
* Those are not actually ID usage, we can ignore them here.
*/
if (cb_flag & IDWALK_CB_LOOPBACK) {
@@ -768,7 +770,7 @@ static int foreach_libblock_used_linked_data_tag_clear_cb(LibraryIDLinkCallbackD
bool *is_changed = cb_data->user_data;
if (*id_p) {
- /* The infamous 'from' pointers (Key.from, Object.proxy_from, ...).
+ /* The infamous 'from' pointers (Key.from, ...).
* those are not actually ID usage, so we ignore them here. */
if (cb_flag & IDWALK_CB_LOOPBACK) {
return IDWALK_RET_NOP;
diff --git a/source/blender/blenkernel/intern/lib_remap.c b/source/blender/blenkernel/intern/lib_remap.c
index c3ccedb9608..8e375ff16b5 100644
--- a/source/blender/blenkernel/intern/lib_remap.c
+++ b/source/blender/blenkernel/intern/lib_remap.c
@@ -91,28 +91,20 @@ enum {
ID_REMAP_IS_USER_ONE_SKIPPED = 1 << 1, /* There was some skipped 'user_one' usages of old_id. */
};
-static void foreach_libblock_remap_callback_skip(const ID *id_owner,
- ID **id_ptr,
+static void foreach_libblock_remap_callback_skip(const ID *UNUSED(id_owner),
+ ID **UNUSED(id_ptr),
IDRemap *id_remap_data,
const int cb_flag,
const bool is_indirect,
const bool is_reference,
- const bool is_never_null,
- const bool is_obj,
+ const bool violates_never_null,
+ const bool UNUSED(is_obj),
const bool is_obj_editmode)
{
if (is_indirect) {
id_remap_data->skipped_indirect++;
- if (is_obj) {
- Object *ob = (Object *)id_owner;
- if (ob->data == *id_ptr && ob->proxy != NULL) {
- /* And another 'Proudly brought to you by Proxy Hell' hack!
- * This will allow us to avoid clearing 'LIB_EXTERN' flag of obdata of proxies... */
- id_remap_data->skipped_direct++;
- }
- }
}
- else if (is_never_null || is_obj_editmode || is_reference) {
+ else if (violates_never_null || is_obj_editmode || is_reference) {
id_remap_data->skipped_direct++;
}
else {
@@ -135,11 +127,10 @@ static void foreach_libblock_remap_callback_apply(ID *id_owner,
IDRemap *id_remap_data,
const int cb_flag,
const bool is_indirect,
- const bool is_never_null,
- const bool force_user_refcount,
- const bool is_obj_proxy)
+ const bool violates_never_null,
+ const bool force_user_refcount)
{
- if (!is_never_null) {
+ if (!violates_never_null) {
*id_ptr = new_id;
DEG_id_tag_update_ex(id_remap_data->bmain,
id_self,
@@ -170,16 +161,9 @@ static void foreach_libblock_remap_callback_apply(ID *id_owner,
/* We cannot affect old_id->us directly, LIB_TAG_EXTRAUSER(_SET)
* are assumed to be set as needed, that extra user is processed in final handling. */
}
- if (!is_indirect || is_obj_proxy) {
+ if (!is_indirect) {
id_remap_data->status |= ID_REMAP_IS_LINKED_DIRECT;
}
- /* We need to remap proxy_from pointer of remapped proxy... sigh. */
- if (is_obj_proxy && new_id != NULL) {
- Object *ob = (Object *)id_owner;
- if (ob->proxy == (Object *)new_id) {
- ob->proxy->proxy_from = ob;
- }
- }
}
static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data)
@@ -221,16 +205,13 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data)
const bool is_reference = (cb_flag & IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE) != 0;
const bool is_indirect = (cb_flag & IDWALK_CB_INDIRECT_USAGE) != 0;
const bool skip_indirect = (id_remap_data->flag & ID_REMAP_SKIP_INDIRECT_USAGE) != 0;
- /* NOTE: proxy usage implies LIB_TAG_EXTERN, so on this aspect it is direct,
- * on the other hand since they get reset to lib data on file open/reload it is indirect too.
- * Edit Mode is also a 'skip direct' case. */
const bool is_obj = (GS(id_owner->name) == ID_OB);
- const bool is_obj_proxy = (is_obj &&
- (((Object *)id_owner)->proxy || ((Object *)id_owner)->proxy_group));
+ /* NOTE: Edit Mode is a 'skip direct' case, unless specifically requested, obdata should not be
+ * remapped in this situation. */
const bool is_obj_editmode = (is_obj && BKE_object_is_in_editmode((Object *)id_owner) &&
(id_remap_data->flag & ID_REMAP_FORCE_OBDATA_IN_EDITMODE) == 0);
- const bool is_never_null = ((cb_flag & IDWALK_CB_NEVER_NULL) && (new_id == NULL) &&
- (id_remap_data->flag & ID_REMAP_FORCE_NEVER_NULL_USAGE) == 0);
+ const bool violates_never_null = ((cb_flag & IDWALK_CB_NEVER_NULL) && (new_id == NULL) &&
+ (id_remap_data->flag & ID_REMAP_FORCE_NEVER_NULL_USAGE) == 0);
const bool skip_reference = (id_remap_data->flag & ID_REMAP_SKIP_OVERRIDE_LIBRARY) != 0;
const bool skip_never_null = (id_remap_data->flag & ID_REMAP_SKIP_NEVER_NULL_USAGE) != 0;
const bool force_user_refcount = (id_remap_data->flag & ID_REMAP_FORCE_USER_REFCOUNT) != 0;
@@ -258,7 +239,7 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data)
/* Special hack in case it's Object->data and we are in edit mode, and new_id is not NULL
* (otherwise, we follow common NEVER_NULL flags).
* (skipped_indirect too). */
- if ((is_never_null && skip_never_null) ||
+ if ((violates_never_null && skip_never_null) ||
(is_obj_editmode && (((Object *)id_owner)->data == *id_p) && new_id != NULL) ||
(skip_indirect && is_indirect) || (is_reference && skip_reference)) {
foreach_libblock_remap_callback_skip(id_owner,
@@ -267,7 +248,7 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data)
cb_flag,
is_indirect,
is_reference,
- is_never_null,
+ violates_never_null,
is_obj,
is_obj_editmode);
}
@@ -280,9 +261,8 @@ static int foreach_libblock_remap_callback(LibraryIDLinkCallbackData *cb_data)
id_remap_data,
cb_flag,
is_indirect,
- is_never_null,
- force_user_refcount,
- is_obj_proxy);
+ violates_never_null,
+ force_user_refcount);
}
return IDWALK_RET_NOP;
@@ -430,10 +410,7 @@ static void libblock_remap_data(
Main *bmain, ID *id, ID *old_id, ID *new_id, const short remap_flags, IDRemap *r_id_remap_data)
{
IDRemap id_remap_data;
- const int foreach_id_flags = ((remap_flags & ID_REMAP_NO_INDIRECT_PROXY_DATA_USAGE) != 0 ?
- IDWALK_NO_INDIRECT_PROXY_DATA_USAGE :
- IDWALK_NOP) |
- ((remap_flags & ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS) != 0 ?
+ const int foreach_id_flags = ((remap_flags & ID_REMAP_FORCE_INTERNAL_RUNTIME_POINTERS) != 0 ?
IDWALK_DO_INTERNAL_RUNTIME_POINTERS :
IDWALK_NOP);
@@ -581,7 +558,7 @@ static void libblock_remap_foreach_idpair_cb(ID *old_id, ID *new_id, void *user_
case ID_ME:
case ID_CU:
case ID_MB:
- case ID_HA:
+ case ID_CV:
case ID_PT:
case ID_VO:
if (new_id) { /* Only affects us in case obdata was relinked (changed). */
diff --git a/source/blender/blenkernel/intern/main.c b/source/blender/blenkernel/intern/main.c
index 64731be57ac..53b1a9c9e16 100644
--- a/source/blender/blenkernel/intern/main.c
+++ b/source/blender/blenkernel/intern/main.c
@@ -643,8 +643,8 @@ ListBase *which_libbase(Main *bmain, short type)
return &(bmain->cachefiles);
case ID_WS:
return &(bmain->workspaces);
- case ID_HA:
- return &(bmain->hairs);
+ case ID_CV:
+ return &(bmain->hair_curves);
case ID_PT:
return &(bmain->pointclouds);
case ID_VO:
@@ -688,7 +688,7 @@ int set_listbasepointers(Main *bmain, ListBase *lb[/*INDEX_ID_MAX*/])
lb[INDEX_ID_ME] = &(bmain->meshes);
lb[INDEX_ID_CU] = &(bmain->curves);
lb[INDEX_ID_MB] = &(bmain->metaballs);
- lb[INDEX_ID_HA] = &(bmain->hairs);
+ lb[INDEX_ID_CV] = &(bmain->hair_curves);
lb[INDEX_ID_PT] = &(bmain->pointclouds);
lb[INDEX_ID_VO] = &(bmain->volumes);
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 15469f910b4..1c1b2c2cd27 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -36,10 +36,10 @@
#include "DNA_anim_types.h"
#include "DNA_collection_types.h"
#include "DNA_curve_types.h"
+#include "DNA_curves_types.h"
#include "DNA_customdata_types.h"
#include "DNA_defaults.h"
#include "DNA_gpencil_types.h"
-#include "DNA_hair_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
@@ -341,9 +341,9 @@ Material ***BKE_object_material_array_p(Object *ob)
bGPdata *gpd = ob->data;
return &(gpd->mat);
}
- if (ob->type == OB_HAIR) {
- Hair *hair = ob->data;
- return &(hair->mat);
+ if (ob->type == OB_CURVES) {
+ Curves *curves = ob->data;
+ return &(curves->mat);
}
if (ob->type == OB_POINTCLOUD) {
PointCloud *pointcloud = ob->data;
@@ -374,9 +374,9 @@ short *BKE_object_material_len_p(Object *ob)
bGPdata *gpd = ob->data;
return &(gpd->totcol);
}
- if (ob->type == OB_HAIR) {
- Hair *hair = ob->data;
- return &(hair->totcol);
+ if (ob->type == OB_CURVES) {
+ Curves *curves = ob->data;
+ return &(curves->totcol);
}
if (ob->type == OB_POINTCLOUD) {
PointCloud *pointcloud = ob->data;
@@ -403,8 +403,8 @@ Material ***BKE_id_material_array_p(ID *id)
return &(((MetaBall *)id)->mat);
case ID_GD:
return &(((bGPdata *)id)->mat);
- case ID_HA:
- return &(((Hair *)id)->mat);
+ case ID_CV:
+ return &(((Curves *)id)->mat);
case ID_PT:
return &(((PointCloud *)id)->mat);
case ID_VO:
@@ -429,8 +429,8 @@ short *BKE_id_material_len_p(ID *id)
return &(((MetaBall *)id)->totcol);
case ID_GD:
return &(((bGPdata *)id)->totcol);
- case ID_HA:
- return &(((Hair *)id)->totcol);
+ case ID_CV:
+ return &(((Curves *)id)->totcol);
case ID_PT:
return &(((PointCloud *)id)->totcol);
case ID_VO:
@@ -454,7 +454,7 @@ static void material_data_index_remove_id(ID *id, short index)
BKE_curve_material_index_remove((Curve *)id, index);
break;
case ID_MB:
- case ID_HA:
+ case ID_CV:
case ID_PT:
case ID_VO:
/* No material indices for these object data types. */
@@ -509,7 +509,7 @@ static void material_data_index_clear_id(ID *id)
BKE_curve_material_index_clear((Curve *)id);
break;
case ID_MB:
- case ID_HA:
+ case ID_CV:
case ID_PT:
case ID_VO:
/* No material indices for these object data types. */
diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c
index ac6b0a04def..3c5cdb1ba78 100644
--- a/source/blender/blenkernel/intern/mball.c
+++ b/source/blender/blenkernel/intern/mball.c
@@ -15,6 +15,11 @@
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
+ *
* MetaBalls are created from a single Object (with a name without number in it),
* here the DispList and BoundBox also is located.
* All objects with the same name (but with a number in it) are added to this.
@@ -22,10 +27,6 @@
* texture coordinates are patched within the displist
*/
-/** \file
- * \ingroup bke
- */
-
#include <ctype.h>
#include <float.h>
#include <math.h>
diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc
index 76a15fd0a1c..4e534726922 100644
--- a/source/blender/blenkernel/intern/mesh.cc
+++ b/source/blender/blenkernel/intern/mesh.cc
@@ -685,6 +685,17 @@ static int customdata_compare(
}
break;
}
+ case CD_PROP_INT8: {
+ const int8_t *l1_data = (int8_t *)l1->data;
+ const int8_t *l2_data = (int8_t *)l2->data;
+
+ for (int i = 0; i < total_length; i++) {
+ if (l1_data[i] != l2_data[i]) {
+ return MESHCMP_ATTRIBUTE_VALUE_MISMATCH;
+ }
+ }
+ break;
+ }
case CD_PROP_BOOL: {
const bool *l1_data = (bool *)l1->data;
const bool *l2_data = (bool *)l2->data;
diff --git a/source/blender/blenkernel/intern/mesh_fair.cc b/source/blender/blenkernel/intern/mesh_fair.cc
index 50db1bc1564..d0a57310fcf 100644
--- a/source/blender/blenkernel/intern/mesh_fair.cc
+++ b/source/blender/blenkernel/intern/mesh_fair.cc
@@ -12,13 +12,12 @@
* 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.
- *
- * Mesh Fairing algorithm designed by Brett Fedack, used in the addon "Mesh Fairing":
- * https://github.com/fedackb/mesh-fairing.
*/
/** \file
* \ingroup bke
+ * Mesh Fairing algorithm designed by Brett Fedack, used in the addon "Mesh Fairing":
+ * https://github.com/fedackb/mesh-fairing.
*/
#include "BLI_map.hh"
diff --git a/source/blender/blenkernel/intern/mesh_iterators.c b/source/blender/blenkernel/intern/mesh_iterators.c
index 3f2d81b6dc2..4fb03c7b329 100644
--- a/source/blender/blenkernel/intern/mesh_iterators.c
+++ b/source/blender/blenkernel/intern/mesh_iterators.c
@@ -34,7 +34,7 @@
#include "MEM_guardedalloc.h"
-/* General note on iterating vers/loops/edges/polys and end mode.
+/* General note on iterating verts/loops/edges/polys and end mode.
*
* The edit mesh pointer is set for both final and cage meshes in both cases when there are
* modifiers applied and not. This helps consistency of checks in the draw manager, where the
diff --git a/source/blender/blenkernel/intern/mesh_merge.c b/source/blender/blenkernel/intern/mesh_merge.c
index 134a1344f83..3c01d5a4a50 100644
--- a/source/blender/blenkernel/intern/mesh_merge.c
+++ b/source/blender/blenkernel/intern/mesh_merge.c
@@ -27,6 +27,7 @@
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
+#include "BLI_bitmap.h"
#include "BLI_edgehash.h"
#include "BLI_ghash.h"
#include "BLI_utildefines.h"
@@ -351,6 +352,8 @@ Mesh *BKE_mesh_merge_verts(Mesh *mesh,
&poly_map, &poly_map_mem, mesh->mpoly, mesh->mloop, totvert, totpoly, totloop);
} /* done preparing for fast poly compare */
+ BLI_bitmap *vert_tag = BLI_BITMAP_NEW(mesh->totvert, __func__);
+
mp = mesh->mpoly;
mv = mesh->mvert;
for (i = 0; i < totpoly; i++, mp++) {
@@ -365,11 +368,11 @@ Mesh *BKE_mesh_merge_verts(Mesh *mesh,
if (vtargetmap[ml->v] == -1) {
all_vertices_merged = false;
/* This will be used to check for poly using several time the same vert. */
- mv[ml->v].flag &= ~ME_VERT_TMP_TAG;
+ BLI_BITMAP_DISABLE(vert_tag, ml->v);
}
else {
/* This will be used to check for poly using several time the same vert. */
- mv[vtargetmap[ml->v]].flag &= ~ME_VERT_TMP_TAG;
+ BLI_BITMAP_DISABLE(vert_tag, vtargetmap[ml->v]);
}
}
@@ -457,8 +460,8 @@ Mesh *BKE_mesh_merge_verts(Mesh *mesh,
#endif
/* A loop is only valid if its matching edge is,
* and it's not reusing a vertex already used by this poly. */
- if (LIKELY((newe[ml->e] != -1) && ((mv[mlv].flag & ME_VERT_TMP_TAG) == 0))) {
- mv[mlv].flag |= ME_VERT_TMP_TAG;
+ if (LIKELY((newe[ml->e] != -1) && !BLI_BITMAP_TEST(vert_tag, mlv))) {
+ BLI_BITMAP_ENABLE(vert_tag, mlv);
if (UNLIKELY(last_valid_ml != NULL && need_edge_from_last_valid_ml)) {
/* We need to create a new edge between last valid loop and this one! */
@@ -644,6 +647,8 @@ Mesh *BKE_mesh_merge_verts(Mesh *mesh,
MEM_freeN(oldl);
MEM_freeN(oldp);
+ MEM_freeN(vert_tag);
+
BLI_edgehash_free(ehash, NULL);
if (poly_map != NULL) {
diff --git a/source/blender/blenkernel/intern/mesh_validate.c b/source/blender/blenkernel/intern/mesh_validate.c
index 005c916b4e0..a5ba2767301 100644
--- a/source/blender/blenkernel/intern/mesh_validate.c
+++ b/source/blender/blenkernel/intern/mesh_validate.c
@@ -28,6 +28,7 @@
#include "CLG_log.h"
+#include "BLI_bitmap.h"
#include "DNA_mesh_types.h"
#include "DNA_meshdata_types.h"
#include "DNA_object_types.h"
@@ -560,6 +561,8 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
* so be sure to leave at most one poly per loop!
*/
{
+ BLI_bitmap *vert_tag = BLI_BITMAP_NEW(mesh->totvert, __func__);
+
SortPoly *sort_polys = MEM_callocN(sizeof(SortPoly) * totpoly, "mesh validate's sort_polys");
SortPoly *prev_sp, *sp = sort_polys;
int prev_end;
@@ -608,7 +611,7 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
* so we have to ensure here all verts of current poly are cleared. */
for (j = 0, ml = &mloops[sp->loopstart]; j < mp->totloop; j++, ml++) {
if (ml->v < totvert) {
- mverts[ml->v].flag &= ~ME_VERT_TMP_TAG;
+ BLI_BITMAP_DISABLE(vert_tag, ml->v);
}
}
@@ -619,12 +622,12 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
PRINT_ERR("\tLoop %u has invalid vert reference (%u)", sp->loopstart + j, ml->v);
sp->invalid = true;
}
- else if (mverts[ml->v].flag & ME_VERT_TMP_TAG) {
+ else if (BLI_BITMAP_TEST(vert_tag, ml->v)) {
PRINT_ERR("\tPoly %u has duplicated vert reference at corner (%u)", i, j);
sp->invalid = true;
}
else {
- mverts[ml->v].flag |= ME_VERT_TMP_TAG;
+ BLI_BITMAP_ENABLE(vert_tag, ml->v);
}
*v = ml->v;
}
@@ -698,6 +701,8 @@ bool BKE_mesh_validate_arrays(Mesh *mesh,
}
}
+ MEM_freeN(vert_tag);
+
/* Second check pass, testing polys using the same verts. */
qsort(sort_polys, totpoly, sizeof(SortPoly), search_poly_cmp);
sp = prev_sp = sort_polys;
diff --git a/source/blender/blenkernel/intern/modifier.c b/source/blender/blenkernel/intern/modifier.c
index 4f170535d18..4cedaff7c00 100644
--- a/source/blender/blenkernel/intern/modifier.c
+++ b/source/blender/blenkernel/intern/modifier.c
@@ -15,13 +15,12 @@
*
* The Original Code is Copyright (C) 2005 by the Blender Foundation.
* All rights reserved.
- * Modifier stack implementation.
- *
- * BKE_modifier.h contains the function prototypes for this file.
*/
/** \file
* \ingroup bke
+ * Modifier stack implementation.
+ * BKE_modifier.h contains the function prototypes for this file.
*/
/* Allow using deprecated functionality for .blend file I/O. */
@@ -1188,8 +1187,8 @@ void BKE_modifier_blend_write(BlendWriter *writer, ListBase *modbase)
#if 0
CollisionModifierData *collmd = (CollisionModifierData *)md;
- // TODO: CollisionModifier should use pointcache
- // + have proper reset events before enabling this
+ /* TODO: CollisionModifier should use pointcache
+ * + have proper reset events before enabling this. */
writestruct(wd, DATA, MVert, collmd->numverts, collmd->x);
writestruct(wd, DATA, MVert, collmd->numverts, collmd->xnew);
writestruct(wd, DATA, MFace, collmd->numfaces, collmd->mfaces);
diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc
index 40d0c24c9af..a1c10a733ce 100644
--- a/source/blender/blenkernel/intern/node.cc
+++ b/source/blender/blenkernel/intern/node.cc
@@ -648,7 +648,6 @@ static void ntree_blend_write(BlendWriter *writer, ID *id, const void *id_addres
bNodeTree *ntree = (bNodeTree *)id;
/* Clean up, important in undo case to reduce false detection of changed datablocks. */
- ntree->init = 0; /* to set callbacks and force setting types */
ntree->is_updating = false;
ntree->typeinfo = nullptr;
ntree->interface_type = nullptr;
@@ -677,7 +676,6 @@ static void direct_link_node_socket(BlendDataReader *reader, bNodeSocket *sock)
void ntreeBlendReadData(BlendDataReader *reader, bNodeTree *ntree)
{
/* NOTE: writing and reading goes in sync, for speed. */
- ntree->init = 0; /* to set callbacks and force setting types */
ntree->is_updating = false;
ntree->typeinfo = nullptr;
ntree->interface_type = nullptr;
@@ -1145,8 +1143,6 @@ static void ntree_set_typeinfo(bNodeTree *ntree, bNodeTreeType *typeinfo)
}
else {
ntree->typeinfo = &NodeTreeTypeUndefined;
-
- ntree->init &= ~NTREE_TYPE_INIT;
}
/* Deprecated integer type. */
@@ -1177,8 +1173,6 @@ static void node_set_typeinfo(const struct bContext *C,
}
else {
node->typeinfo = &NodeTypeUndefined;
-
- ntree->init &= ~NTREE_TYPE_INIT;
}
}
@@ -1199,8 +1193,6 @@ static void node_socket_set_typeinfo(bNodeTree *ntree,
}
else {
sock->typeinfo = &NodeSocketTypeUndefined;
-
- ntree->init &= ~NTREE_TYPE_INIT;
}
BKE_ntree_update_tag_socket_type(ntree, sock);
}
@@ -1218,8 +1210,6 @@ static void update_typeinfo(Main *bmain,
}
FOREACH_NODETREE_BEGIN (bmain, ntree, id) {
- ntree->init |= NTREE_TYPE_INIT;
-
if (treetype && STREQ(ntree->idname, treetype->idname)) {
ntree_set_typeinfo(ntree, unregister ? nullptr : treetype);
}
@@ -1260,8 +1250,6 @@ static void update_typeinfo(Main *bmain,
void ntreeSetTypes(const struct bContext *C, bNodeTree *ntree)
{
- ntree->init |= NTREE_TYPE_INIT;
-
ntree_set_typeinfo(ntree, ntreeTypeFind(ntree->idname));
LISTBASE_FOREACH (bNode *, node, &ntree->nodes) {
@@ -2674,11 +2662,6 @@ bNodeTree *ntreeAddTree(Main *bmain, const char *name, const char *idname)
ntree->id.flag |= LIB_EMBEDDED_DATA;
}
- /* Types are fully initialized at this point,
- * if an undefined node is added later this will be reset.
- */
- ntree->init |= NTREE_TYPE_INIT;
-
BLI_strncpy(ntree->idname, idname, sizeof(ntree->idname));
ntree_set_typeinfo(ntree, ntreeTypeFind(idname));
@@ -4503,6 +4486,8 @@ static void registerCompositNodes()
register_node_type_cmp_sepycca();
register_node_type_cmp_combycca();
register_node_type_cmp_premulkey();
+ register_node_type_cmp_separate_xyz();
+ register_node_type_cmp_combine_xyz();
register_node_type_cmp_diff_matte();
register_node_type_cmp_distance_matte();
diff --git a/source/blender/blenkernel/intern/object.cc b/source/blender/blenkernel/intern/object.cc
index f9484205ef6..8faae6efb26 100644
--- a/source/blender/blenkernel/intern/object.cc
+++ b/source/blender/blenkernel/intern/object.cc
@@ -89,6 +89,7 @@
#include "BKE_constraint.h"
#include "BKE_crazyspace.h"
#include "BKE_curve.h"
+#include "BKE_curves.h"
#include "BKE_deform.h"
#include "BKE_displist.h"
#include "BKE_duplilist.h"
@@ -103,7 +104,6 @@
#include "BKE_gpencil.h"
#include "BKE_gpencil_geom.h"
#include "BKE_gpencil_modifier.h"
-#include "BKE_hair.h"
#include "BKE_icons.h"
#include "BKE_idprop.h"
#include "BKE_idtype.h"
@@ -325,45 +325,6 @@ static void object_free_data(ID *id)
BKE_previewimg_free(&ob->preview);
}
-static void object_make_local(Main *bmain, ID *id, const int flags)
-{
- if (!ID_IS_LINKED(id)) {
- return;
- }
-
- Object *ob = (Object *)id;
- const bool lib_local = (flags & LIB_ID_MAKELOCAL_FULL_LIBRARY) != 0;
- const bool clear_proxy = (flags & LIB_ID_MAKELOCAL_OBJECT_NO_PROXY_CLEARING) == 0;
-
- bool force_local, force_copy;
- BKE_lib_id_make_local_generic_action_define(bmain, id, flags, &force_local, &force_copy);
-
- if (force_local) {
- BKE_lib_id_clear_library_data(bmain, &ob->id, flags);
- BKE_lib_id_expand_local(bmain, &ob->id, flags);
- if (clear_proxy) {
- if (ob->proxy_from != nullptr) {
- ob->proxy_from->proxy = nullptr;
- ob->proxy_from->proxy_group = nullptr;
- }
- ob->proxy = ob->proxy_from = ob->proxy_group = nullptr;
- }
- }
- else if (force_copy) {
- Object *ob_new = (Object *)BKE_id_copy(bmain, &ob->id);
- id_us_min(&ob_new->id);
-
- ob_new->proxy = ob_new->proxy_from = ob_new->proxy_group = nullptr;
-
- /* setting newid is mandatory for complex make_lib_local logic... */
- ID_NEW_SET(ob, ob_new);
-
- if (!lib_local) {
- BKE_libblock_remap(bmain, ob, ob_new, ID_REMAP_SKIP_INDIRECT_USAGE);
- }
- }
-}
-
static void library_foreach_modifiersForeachIDLink(void *user_data,
Object *UNUSED(object),
ID **id_pointer,
@@ -419,51 +380,25 @@ static void object_foreach_id(ID *id, LibraryForeachIDData *data)
{
Object *object = (Object *)id;
- /* Object is special, proxies make things hard... */
- const int proxy_cb_flag = ((BKE_lib_query_foreachid_process_flags_get(data) &
- IDWALK_NO_INDIRECT_PROXY_DATA_USAGE) == 0 &&
- (object->proxy || object->proxy_group)) ?
- IDWALK_CB_INDIRECT_USAGE :
- 0;
-
/* object data special case */
if (object->type == OB_EMPTY) {
/* empty can have nullptr or Image */
- BKE_LIB_FOREACHID_PROCESS_ID(data, object->data, proxy_cb_flag | IDWALK_CB_USER);
+ BKE_LIB_FOREACHID_PROCESS_ID(data, object->data, IDWALK_CB_USER);
}
else {
/* when set, this can't be nullptr */
if (object->data) {
- BKE_LIB_FOREACHID_PROCESS_ID(
- data, object->data, proxy_cb_flag | IDWALK_CB_USER | IDWALK_CB_NEVER_NULL);
+ BKE_LIB_FOREACHID_PROCESS_ID(data, object->data, IDWALK_CB_USER | IDWALK_CB_NEVER_NULL);
}
}
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, object->parent, IDWALK_CB_NEVER_SELF);
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, object->track, IDWALK_CB_NEVER_SELF);
- /* object->proxy is refcounted, but not object->proxy_group... *sigh* */
- BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, object->proxy, IDWALK_CB_USER | IDWALK_CB_NEVER_SELF);
- BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, object->proxy_group, IDWALK_CB_NOP);
-
- /* Special case!
- * Since this field is set/owned by 'user' of this ID (and not ID itself),
- * it is only indirect usage if proxy object is linked... Twisted. */
- {
- const int cb_flag_orig = BKE_lib_query_foreachid_process_callback_flag_override(
- data,
- (object->proxy_from != nullptr && ID_IS_LINKED(object->proxy_from)) ?
- IDWALK_CB_INDIRECT_USAGE :
- 0,
- true);
- BKE_LIB_FOREACHID_PROCESS_IDSUPER(
- data, object->proxy_from, IDWALK_CB_LOOPBACK | IDWALK_CB_NEVER_SELF);
- BKE_lib_query_foreachid_process_callback_flag_override(data, cb_flag_orig, true);
- }
BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, object->poselib, IDWALK_CB_USER);
for (int i = 0; i < object->totcol; i++) {
- BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, object->mat[i], proxy_cb_flag | IDWALK_CB_USER);
+ BKE_LIB_FOREACHID_PROCESS_IDSUPER(data, object->mat[i], IDWALK_CB_USER);
}
/* Note that ob->gpd is deprecated, so no need to handle it here. */
@@ -476,8 +411,6 @@ static void object_foreach_id(ID *id, LibraryForeachIDData *data)
/* Note that ob->effect is deprecated, so no need to handle it here. */
if (object->pose) {
- const int cb_flag_orig = BKE_lib_query_foreachid_process_callback_flag_override(
- data, proxy_cb_flag, false);
LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
BKE_LIB_FOREACHID_PROCESS_FUNCTION_CALL(
data,
@@ -492,7 +425,6 @@ static void object_foreach_id(ID *id, LibraryForeachIDData *data)
BKE_constraints_id_loop(
&pchan->constraints, library_foreach_constraintObjectLooper, data));
}
- BKE_lib_query_foreachid_process_callback_flag_override(data, cb_flag_orig, true);
}
if (object->rigidbody_constraint) {
@@ -627,9 +559,6 @@ static void object_blend_write(BlendWriter *writer, ID *id, const void *id_addre
bArmature *arm = nullptr;
if (ob->type == OB_ARMATURE) {
arm = (bArmature *)ob->data;
- if (arm && ob->pose && arm->act_bone) {
- BLI_strncpy(ob->pose->proxy_act_bone, arm->act_bone->name, sizeof(ob->pose->proxy_act_bone));
- }
}
BKE_pose_blend_write(writer, ob->pose, arm);
@@ -1305,7 +1234,7 @@ IDTypeInfo IDType_ID_OB = {
/* init_data */ object_init_data,
/* copy_data */ object_copy_data,
/* free_data */ object_free_data,
- /* make_local */ object_make_local,
+ /* make_local */ nullptr,
/* foreach_id */ object_foreach_id,
/* foreach_cache */ nullptr,
/* foreach_path */ object_foreach_path,
@@ -1486,10 +1415,7 @@ bool BKE_object_support_modifier_type_check(const Object *ob, int modifier_type)
}
/* Only geometry objects should be able to get modifiers T25291. */
- if (ob->type == OB_HAIR) {
- return (mti->modifyHair != nullptr) || (mti->flags & eModifierTypeFlag_AcceptsVertexCosOnly);
- }
- if (ELEM(ob->type, OB_POINTCLOUD, OB_VOLUME)) {
+ if (ELEM(ob->type, OB_POINTCLOUD, OB_VOLUME, OB_CURVES)) {
return (mti->modifyGeometrySet != nullptr);
}
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_LATTICE)) {
@@ -2172,8 +2098,8 @@ static const char *get_obdata_defname(int type)
return DATA_("Armature");
case OB_SPEAKER:
return DATA_("Speaker");
- case OB_HAIR:
- return DATA_("Hair");
+ case OB_CURVES:
+ return DATA_("HairCurves");
case OB_POINTCLOUD:
return DATA_("PointCloud");
case OB_VOLUME:
@@ -2247,8 +2173,8 @@ void *BKE_object_obdata_add_from_type(Main *bmain, int type, const char *name)
return BKE_lightprobe_add(bmain, name);
case OB_GPENCIL:
return BKE_gpencil_data_addnew(bmain, name);
- case OB_HAIR:
- return BKE_hair_add(bmain, name);
+ case OB_CURVES:
+ return BKE_curves_add(bmain, name);
case OB_POINTCLOUD:
return BKE_pointcloud_add_default(bmain, name);
case OB_VOLUME:
@@ -2285,8 +2211,8 @@ int BKE_object_obdata_to_type(const ID *id)
return OB_ARMATURE;
case ID_LP:
return OB_LIGHTPROBE;
- case ID_HA:
- return OB_HAIR;
+ case ID_CV:
+ return OB_CURVES;
case ID_PT:
return OB_POINTCLOUD;
case ID_VO:
@@ -2803,8 +2729,8 @@ Object *BKE_object_duplicate(Main *bmain, Object *ob, uint dupflag, uint duplica
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
}
break;
- case OB_HAIR:
- if (dupflag & USER_DUP_HAIR) {
+ case OB_CURVES:
+ if (dupflag & USER_DUP_CURVES) {
id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag, copy_flags);
}
break;
@@ -2876,161 +2802,6 @@ bool BKE_object_obdata_is_libdata(const Object *ob)
return (ob && ob->data && ID_IS_LINKED(ob->data));
}
-/* -------------------------------------------------------------------- */
-/** \name Object Proxy API
- * \{ */
-
-/* when you make proxy, ensure the exposed layers are extern */
-static void armature_set_id_extern(Object *ob)
-{
- bArmature *arm = (bArmature *)ob->data;
- unsigned int lay = arm->layer_protected;
-
- LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
- if (!(pchan->bone->layer & lay)) {
- id_lib_extern((ID *)pchan->custom);
- }
- }
-}
-
-void BKE_object_copy_proxy_drivers(Object *ob, Object *target)
-{
- if ((target->adt) && (target->adt->drivers.first)) {
-
- /* add new animdata block */
- if (!ob->adt) {
- ob->adt = BKE_animdata_ensure_id(&ob->id);
- }
-
- /* make a copy of all the drivers (for now), then correct any links that need fixing */
- BKE_fcurves_free(&ob->adt->drivers);
- BKE_fcurves_copy(&ob->adt->drivers, &target->adt->drivers);
-
- LISTBASE_FOREACH (FCurve *, fcu, &ob->adt->drivers) {
- ChannelDriver *driver = fcu->driver;
-
- LISTBASE_FOREACH (DriverVar *, dvar, &driver->variables) {
- /* all drivers */
- DRIVER_TARGETS_LOOPER_BEGIN (dvar) {
- if (dtar->id) {
- if ((Object *)dtar->id == target) {
- dtar->id = (ID *)ob;
- }
- else {
- /* only on local objects because this causes indirect links
- * 'a -> b -> c', blend to point directly to a.blend
- * when a.blend has a proxy that's linked into `c.blend`. */
- if (!ID_IS_LINKED(ob)) {
- id_lib_extern((ID *)dtar->id);
- }
- }
- }
- }
- DRIVER_TARGETS_LOOPER_END;
- }
- }
- }
-}
-
-void BKE_object_make_proxy(Main *bmain, Object *ob, Object *target, Object *cob)
-{
- /* paranoia checks */
- if (ID_IS_LINKED(ob) || !ID_IS_LINKED(target)) {
- CLOG_ERROR(&LOG, "cannot make proxy");
- return;
- }
-
- ob->proxy = target;
- id_us_plus(&target->id);
- ob->proxy_group = cob;
-
- DEG_id_tag_update(&ob->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
- DEG_id_tag_update(&target->id, ID_RECALC_TRANSFORM | ID_RECALC_GEOMETRY | ID_RECALC_ANIMATION);
-
- /* copy transform
- * - cob means this proxy comes from a collection, just apply the matrix
- * so the object won't move from its dupli-transform.
- *
- * - no cob means this is being made from a linked object,
- * this is closer to making a copy of the object - in-place. */
- if (cob) {
- ob->rotmode = target->rotmode;
- mul_m4_m4m4(ob->obmat, cob->obmat, target->obmat);
- if (cob->instance_collection) { /* should always be true */
- float tvec[3];
- mul_v3_mat3_m4v3(tvec, ob->obmat, cob->instance_collection->instance_offset);
- sub_v3_v3(ob->obmat[3], tvec);
- }
- BKE_object_apply_mat4(ob, ob->obmat, false, true);
- }
- else {
- BKE_object_transform_copy(ob, target);
- ob->parent = target->parent; /* libdata */
- copy_m4_m4(ob->parentinv, target->parentinv);
- }
-
- /* copy animdata stuff - drivers only for now... */
- BKE_object_copy_proxy_drivers(ob, target);
-
- /* skip constraints? */
- /* FIXME: this is considered by many as a bug */
-
- /* set object type and link to data */
- ob->type = target->type;
- ob->data = target->data;
- id_us_plus((ID *)ob->data); /* ensures lib data becomes LIB_TAG_EXTERN */
-
- /* copy material and index information */
- ob->actcol = ob->totcol = 0;
- if (ob->mat) {
- MEM_freeN(ob->mat);
- }
- if (ob->matbits) {
- MEM_freeN(ob->matbits);
- }
- ob->mat = nullptr;
- ob->matbits = nullptr;
- if ((target->totcol) && (target->mat) && OB_TYPE_SUPPORT_MATERIAL(ob->type)) {
- int i;
-
- ob->actcol = target->actcol;
- ob->totcol = target->totcol;
-
- ob->mat = (Material **)MEM_dupallocN(target->mat);
- ob->matbits = (char *)MEM_dupallocN(target->matbits);
- for (i = 0; i < target->totcol; i++) {
- /* don't need to run BKE_object_materials_test
- * since we know this object is new and not used elsewhere */
- id_us_plus((ID *)ob->mat[i]);
- }
- }
-
- /* type conversions */
- if (target->type == OB_ARMATURE) {
- copy_object_pose(ob, target, 0); /* data copy, object pointers in constraints */
- BKE_pose_rest(ob->pose, false); /* clear all transforms in channels */
- BKE_pose_rebuild(bmain, ob, (bArmature *)ob->data, true); /* set all internal links */
-
- armature_set_id_extern(ob);
- }
- else if (target->type == OB_EMPTY) {
- ob->empty_drawtype = target->empty_drawtype;
- ob->empty_drawsize = target->empty_drawsize;
- }
-
- /* copy IDProperties */
- if (ob->id.properties) {
- IDP_FreeProperty(ob->id.properties);
- ob->id.properties = nullptr;
- }
- if (target->id.properties) {
- ob->id.properties = IDP_CopyProperty(target->id.properties);
- }
-
- /* copy drawtype info */
- ob->dt = target->dt;
-}
-
void BKE_object_obdata_size_init(struct Object *ob, const float size)
{
/* apply radius as a scale to types that support it */
@@ -3072,8 +2843,6 @@ void BKE_object_obdata_size_init(struct Object *ob, const float size)
}
}
-/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Object Matrix Get/Set API
* \{ */
@@ -3855,8 +3624,8 @@ BoundBox *BKE_object_boundbox_get(Object *ob)
case OB_GPENCIL:
bb = BKE_gpencil_boundbox_get(ob);
break;
- case OB_HAIR:
- bb = BKE_hair_boundbox_get(ob);
+ case OB_CURVES:
+ bb = BKE_curves_boundbox_get(ob);
break;
case OB_POINTCLOUD:
bb = BKE_pointcloud_boundbox_get(ob);
@@ -4057,8 +3826,8 @@ void BKE_object_minmax(Object *ob, float r_min[3], float r_max[3], const bool us
}
break;
}
- case OB_HAIR: {
- BoundBox bb = *BKE_hair_boundbox_get(ob);
+ case OB_CURVES: {
+ BoundBox bb = *BKE_curves_boundbox_get(ob);
BKE_boundbox_minmax(&bb, ob->obmat, r_min, r_max);
changed = true;
break;
@@ -4365,33 +4134,10 @@ void BKE_object_tfm_restore(Object *ob, void *obtfm_pt)
/** \name Object Evaluation/Update API
* \{ */
-static void object_handle_update_proxy(Depsgraph *depsgraph,
- Scene *scene,
- Object *object,
- const bool do_proxy_update)
-{
- /* The case when this is a collection proxy, object_update is called in collection.c */
- if (object->proxy == nullptr) {
- return;
- }
- /* set pointer in library proxy target, for copying, but restore it */
- object->proxy->proxy_from = object;
- // printf("set proxy pointer for later collection stuff %s\n", ob->id.name);
-
- /* the no-group proxy case, we call update */
- if (object->proxy_group == nullptr) {
- if (do_proxy_update) {
- // printf("call update, lib ob %s proxy %s\n", ob->proxy->id.name, ob->id.name);
- BKE_object_handle_update(depsgraph, scene, object->proxy);
- }
- }
-}
-
void BKE_object_handle_update_ex(Depsgraph *depsgraph,
Scene *scene,
Object *ob,
- RigidBodyWorld *rbw,
- const bool do_proxy_update)
+ RigidBodyWorld *rbw)
{
const ID *object_data = (ID *)ob->data;
const bool recalc_object = (ob->id.recalc & ID_RECALC_ALL) != 0;
@@ -4399,7 +4145,6 @@ void BKE_object_handle_update_ex(Depsgraph *depsgraph,
((object_data->recalc & ID_RECALC_ALL) != 0) :
false;
if (!recalc_object && !recalc_data) {
- object_handle_update_proxy(depsgraph, scene, ob, do_proxy_update);
return;
}
/* Speed optimization for animation lookups. */
@@ -4428,22 +4173,17 @@ void BKE_object_handle_update_ex(Depsgraph *depsgraph,
if (G.debug & G_DEBUG_DEPSGRAPH_EVAL) {
printf("recalcob %s\n", ob->id.name + 2);
}
- /* Handle proxy copy for target. */
- if (!BKE_object_eval_proxy_copy(depsgraph, ob)) {
- BKE_object_where_is_calc_ex(depsgraph, scene, rbw, ob, nullptr);
- }
+ BKE_object_where_is_calc_ex(depsgraph, scene, rbw, ob, nullptr);
}
if (recalc_data) {
BKE_object_handle_data_update(depsgraph, scene, ob);
}
-
- object_handle_update_proxy(depsgraph, scene, ob, do_proxy_update);
}
void BKE_object_handle_update(Depsgraph *depsgraph, Scene *scene, Object *ob)
{
- BKE_object_handle_update_ex(depsgraph, scene, ob, nullptr, true);
+ BKE_object_handle_update_ex(depsgraph, scene, ob, nullptr);
}
void BKE_object_sculpt_data_create(Object *ob)
@@ -5201,7 +4941,7 @@ bool BKE_object_supports_material_slots(struct Object *ob)
OB_SURF,
OB_FONT,
OB_MBALL,
- OB_HAIR,
+ OB_CURVES,
OB_POINTCLOUD,
OB_VOLUME,
OB_GPENCIL);
diff --git a/source/blender/blenkernel/intern/object_update.c b/source/blender/blenkernel/intern/object_update.c
index 1a208355870..6352fd19239 100644
--- a/source/blender/blenkernel/intern/object_update.c
+++ b/source/blender/blenkernel/intern/object_update.c
@@ -13,7 +13,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * The Original Code is Copyright (C) 20014 by Blender Foundation.
+ * The Original Code is Copyright (C) 2014 by Blender Foundation.
* All rights reserved.
*/
@@ -41,12 +41,12 @@
#include "BKE_armature.h"
#include "BKE_constraint.h"
#include "BKE_curve.h"
+#include "BKE_curves.h"
#include "BKE_displist.h"
#include "BKE_editmesh.h"
#include "BKE_effect.h"
#include "BKE_gpencil.h"
#include "BKE_gpencil_modifier.h"
-#include "BKE_hair.h"
#include "BKE_image.h"
#include "BKE_key.h"
#include "BKE_lattice.h"
@@ -190,16 +190,7 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
break;
}
case OB_ARMATURE:
- if (ID_IS_LINKED(ob) && ob->proxy_from) {
- 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);
- }
- }
- else {
- BKE_pose_where_is(depsgraph, scene, ob);
- }
+ BKE_pose_where_is(depsgraph, scene, ob);
break;
case OB_MBALL:
@@ -223,8 +214,8 @@ void BKE_object_handle_data_update(Depsgraph *depsgraph, Scene *scene, Object *o
BKE_gpencil_update_layer_transforms(depsgraph, ob);
break;
}
- case OB_HAIR:
- BKE_hair_data_update(depsgraph, scene, ob);
+ case OB_CURVES:
+ BKE_curves_data_update(depsgraph, scene, ob);
break;
case OB_POINTCLOUD:
BKE_pointcloud_data_update(depsgraph, scene, ob);
@@ -311,33 +302,8 @@ void BKE_object_sync_to_original(Depsgraph *depsgraph, Object *object)
object_sync_boundbox_to_original(object_orig, object);
}
-bool BKE_object_eval_proxy_copy(Depsgraph *depsgraph, Object *object)
-{
- /* Handle proxy copy for target, */
- if (ID_IS_LINKED(object) && object->proxy_from) {
- DEG_debug_print_eval(depsgraph, __func__, object->id.name, object);
- if (object->proxy_from->proxy_group) {
- /* Transform proxy into group space. */
- Object *obg = object->proxy_from->proxy_group;
- float imat[4][4];
- invert_m4_m4(imat, obg->obmat);
- mul_m4_m4m4(object->obmat, imat, object->proxy_from->obmat);
- /* Should always be true. */
- if (obg->instance_collection) {
- add_v3_v3(object->obmat[3], obg->instance_collection->instance_offset);
- }
- }
- else {
- copy_m4_m4(object->obmat, object->proxy_from->obmat);
- }
- return true;
- }
- return false;
-}
-
-void BKE_object_eval_uber_transform(Depsgraph *depsgraph, Object *object)
+void BKE_object_eval_uber_transform(Depsgraph *UNUSED(depsgraph), Object *UNUSED(object))
{
- BKE_object_eval_proxy_copy(depsgraph, object);
}
void BKE_object_data_batch_cache_dirty_tag(ID *object_data)
@@ -359,8 +325,8 @@ void BKE_object_data_batch_cache_dirty_tag(ID *object_data)
case ID_GD:
BKE_gpencil_batch_cache_dirty_tag((struct bGPdata *)object_data);
break;
- case ID_HA:
- BKE_hair_batch_cache_dirty_tag((struct Hair *)object_data, BKE_HAIR_BATCH_DIRTY_ALL);
+ case ID_CV:
+ BKE_curves_batch_cache_dirty_tag((struct Curves *)object_data, BKE_CURVES_BATCH_DIRTY_ALL);
break;
case ID_PT:
BKE_pointcloud_batch_cache_dirty_tag((struct PointCloud *)object_data,
diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c
index 97326c24a61..dacc24c32da 100644
--- a/source/blender/blenkernel/intern/ocean.c
+++ b/source/blender/blenkernel/intern/ocean.c
@@ -15,13 +15,13 @@
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
- *
- * Based on original code by Drew Whitehouse / Houdini Ocean Toolkit
- * OpenMP hints by Christian Schnellhammer
*/
/** \file
* \ingroup bke
+ *
+ * Based on original code by Drew Whitehouse / Houdini Ocean Toolkit
+ * OpenMP hints by Christian Schnellhammer
*/
#include <math.h>
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 4dba13ce4c2..aa08a6494d1 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -4640,7 +4640,7 @@ void psys_get_particle_on_path(ParticleSimulationData *sim,
* account when subdividing for instance. */
pind.mesh = psys_in_edit_mode(sim->depsgraph, psys) ?
NULL :
- psys->hair_out_mesh; /* XXX(@sybren) EEK. */
+ psys->hair_out_mesh; /* XXX(@sybren): EEK. */
init_particle_interpolation(sim->ob, psys, pa, &pind);
do_particle_interpolation(psys, p, pa, t, &pind, state);
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index e489f9e2bac..6953ecf38c3 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -13,11 +13,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * The Original Code is Copyright (C) 2007 by Janne Karhu.
- * All rights reserved.
- * Adaptive time step
- * Classical SPH
- * Copyright 2011-2012 AutoCRC
+ * Copyright 2007 Janne Karhu. All rights reserved.
+ * 2011-2012 AutoCRC (adaptive time step, Classical SPH).
*/
/** \file
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index bfedd4d3f49..c925942d810 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -610,7 +610,9 @@ void BKE_pbvh_build_mesh(PBVH *pbvh,
}
MEM_freeN(prim_bbc);
- MEM_freeN(pbvh->vert_bitmap);
+
+ /* Clear the bitmap so it can be used as an update tag later on. */
+ BLI_bitmap_set_all(pbvh->vert_bitmap, false, totvert);
}
void BKE_pbvh_build_grids(PBVH *pbvh,
@@ -714,6 +716,8 @@ void BKE_pbvh_free(PBVH *pbvh)
MEM_freeN(pbvh->prim_indices);
}
+ MEM_SAFE_FREE(pbvh->vert_bitmap);
+
MEM_freeN(pbvh);
}
@@ -1021,8 +1025,7 @@ static void pbvh_update_normals_clear_task_cb(void *__restrict userdata,
const int totvert = node->uniq_verts;
for (int i = 0; i < totvert; i++) {
const int v = verts[i];
- const MVert *mvert = &pbvh->verts[v];
- if (mvert->flag & ME_VERT_PBVH_UPDATE) {
+ if (BLI_BITMAP_TEST(pbvh->vert_bitmap, v)) {
zero_v3(vnors[v]);
}
}
@@ -1065,7 +1068,7 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata,
for (int j = sides; j--;) {
const int v = vtri[j];
- if (pbvh->verts[v].flag & ME_VERT_PBVH_UPDATE) {
+ if (BLI_BITMAP_TEST(pbvh->vert_bitmap, v)) {
/* NOTE: This avoids `lock, add_v3_v3, unlock`
* and is five to ten times quicker than a spin-lock.
* Not exact equivalent though, since atomicity is only ensured for one component
@@ -1094,13 +1097,12 @@ static void pbvh_update_normals_store_task_cb(void *__restrict userdata,
for (int i = 0; i < totvert; i++) {
const int v = verts[i];
- MVert *mvert = &pbvh->verts[v];
/* No atomics necessary because we are iterating over uniq_verts only,
* so we know only this thread will handle this vertex. */
- if (mvert->flag & ME_VERT_PBVH_UPDATE) {
+ if (BLI_BITMAP_TEST(pbvh->vert_bitmap, v)) {
normalize_v3(vnors[v]);
- mvert->flag &= ~ME_VERT_PBVH_UPDATE;
+ BLI_BITMAP_DISABLE(pbvh->vert_bitmap, v);
}
}
@@ -1117,7 +1119,7 @@ static void pbvh_faces_update_normals(PBVH *pbvh, PBVHNode **nodes, int totnode)
* bounding box of its adjacent faces will be as well.
* - However this is only true for the vertices that have actually been
* edited, not for all vertices in the nodes marked for update, so we
- * can only update vertices marked with ME_VERT_PBVH_UPDATE.
+ * can only update vertices marked in the `vert_bitmap`.
*/
PBVHUpdateData data = {
@@ -1826,6 +1828,12 @@ bool BKE_pbvh_node_fully_unmasked_get(PBVHNode *node)
return (node->flag & PBVH_Leaf) && (node->flag & PBVH_FullyUnmasked);
}
+void BKE_pbvh_vert_mark_update(PBVH *pbvh, int index)
+{
+ BLI_assert(pbvh->type == PBVH_FACES);
+ BLI_BITMAP_ENABLE(pbvh->vert_bitmap, index);
+}
+
void BKE_pbvh_node_get_verts(PBVH *pbvh,
PBVHNode *node,
const int **r_vert_indices,
@@ -1971,9 +1979,8 @@ bool BKE_pbvh_node_vert_update_check_any(PBVH *pbvh, PBVHNode *node)
for (int i = 0; i < totvert; i++) {
const int v = verts[i];
- const MVert *mvert = &pbvh->verts[v];
- if (mvert->flag & ME_VERT_PBVH_UPDATE) {
+ if (BLI_BITMAP_TEST(pbvh->vert_bitmap, v)) {
return true;
}
}
@@ -2827,7 +2834,7 @@ void BKE_pbvh_vert_coords_apply(PBVH *pbvh, const float (*vertCos)[3], const int
/* no need for float comparison here (memory is exactly equal or not) */
if (memcmp(mvert->co, vertCos[a], sizeof(float[3])) != 0) {
copy_v3_v3(mvert->co, vertCos[a]);
- mvert->flag |= ME_VERT_PBVH_UPDATE;
+ BKE_pbvh_vert_mark_update(pbvh, a);
}
}
diff --git a/source/blender/blenkernel/intern/pbvh_intern.h b/source/blender/blenkernel/intern/pbvh_intern.h
index 9562cda5f28..53379d8a032 100644
--- a/source/blender/blenkernel/intern/pbvh_intern.h
+++ b/source/blender/blenkernel/intern/pbvh_intern.h
@@ -153,8 +153,8 @@ struct PBVH {
int totgrid;
BLI_bitmap **grid_hidden;
- /* Only used during BVH build and update,
- * don't need to remain valid after */
+ /* Used during BVH build and later to mark that a vertex needs to update
+ * (its normal must be recalculated). */
BLI_bitmap *vert_bitmap;
#ifdef PERFCNTRS
diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c
index 9d66c354b54..2f63edebb67 100644
--- a/source/blender/blenkernel/intern/subsurf_ccg.c
+++ b/source/blender/blenkernel/intern/subsurf_ccg.c
@@ -580,7 +580,6 @@ static void ss_sync_ccg_from_derivedmesh(CCGSubSurf *ss,
#endif
MVert *mvert = dm->getVertArray(dm);
MEdge *medge = dm->getEdgeArray(dm);
- // MFace *mface = dm->getTessFaceArray(dm); /* UNUSED */
MVert *mv;
MEdge *me;
MLoop *mloop = dm->getLoopArray(dm), *ml;
@@ -1129,44 +1128,6 @@ static void ccgDM_copyFinalEdgeArray(DerivedMesh *dm, MEdge *medge)
}
}
-static void ccgDM_copyFinalFaceArray(DerivedMesh *dm, MFace *mface)
-{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
- CCGSubSurf *ss = ccgdm->ss;
- int index;
- int totface;
- int gridSize = ccgSubSurf_getGridSize(ss);
- int edgeSize = ccgSubSurf_getEdgeSize(ss);
- int i = 0;
- DMFlagMat *faceFlags = ccgdm->faceFlags;
-
- totface = dm->getNumTessFaces(dm);
- for (index = 0; index < totface; index++) {
- CCGFace *f = ccgdm->faceMap[index].face;
- int x, y, S, numVerts = ccgSubSurf_getFaceNumVerts(f);
- /* keep types in sync with MFace, avoid many conversions */
- char flag = (faceFlags) ? faceFlags[index].flag : ME_SMOOTH;
- short mat_nr = (faceFlags) ? faceFlags[index].mat_nr : 0;
-
- for (S = 0; S < numVerts; S++) {
- for (y = 0; y < gridSize - 1; y++) {
- for (x = 0; x < gridSize - 1; x++) {
- MFace *mf = &mface[i];
- mf->v1 = getFaceIndex(ss, f, S, x + 0, y + 0, edgeSize, gridSize);
- mf->v2 = getFaceIndex(ss, f, S, x + 0, y + 1, edgeSize, gridSize);
- mf->v3 = getFaceIndex(ss, f, S, x + 1, y + 1, edgeSize, gridSize);
- mf->v4 = getFaceIndex(ss, f, S, x + 1, y + 0, edgeSize, gridSize);
- mf->mat_nr = mat_nr;
- mf->flag = flag;
- mf->edcode = 0;
-
- i++;
- }
- }
- }
- }
-}
-
typedef struct CopyFinalLoopArrayData {
CCGDerivedMesh *ccgdm;
MLoop *mloop;
@@ -1457,63 +1418,6 @@ static void *ccgDM_get_edge_data_layer(DerivedMesh *dm, int type)
return DM_get_edge_data_layer(dm, type);
}
-static void *ccgDM_get_tessface_data_layer(DerivedMesh *dm, int type)
-{
- if (type == CD_ORIGINDEX) {
- /* create origindex on demand to save memory */
- int *origindex;
-
- /* Avoid re-creation if the layer exists already */
- origindex = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
- if (origindex) {
- return origindex;
- }
-
- DM_add_tessface_layer(dm, CD_ORIGINDEX, CD_CALLOC, NULL);
- origindex = DM_get_tessface_data_layer(dm, CD_ORIGINDEX);
-
- /* silly loop counting up */
- range_vn_i(origindex, dm->getNumTessFaces(dm), 0);
-
- return origindex;
- }
-
- if (type == CD_TESSLOOPNORMAL) {
- /* Create tessloopnormal on demand to save memory. */
- /* Note that since tessellated face corners are the same a loops in CCGDM,
- * and since all faces have four loops/corners, we can simplify the code
- * here by converting tessloopnormals from 'short (*)[4][3]' to 'short (*)[3]'. */
- short(*tlnors)[3];
-
- /* Avoid re-creation if the layer exists already */
- tlnors = DM_get_tessface_data_layer(dm, CD_TESSLOOPNORMAL);
- if (!tlnors) {
- float(*lnors)[3];
- short(*tlnors_it)[3];
- const int numLoops = ccgDM_getNumLoops(dm);
- int i;
-
- lnors = dm->getLoopDataArray(dm, CD_NORMAL);
- if (!lnors) {
- return NULL;
- }
-
- DM_add_tessface_layer(dm, CD_TESSLOOPNORMAL, CD_CALLOC, NULL);
- tlnors = tlnors_it = (short(*)[3])DM_get_tessface_data_layer(dm, CD_TESSLOOPNORMAL);
-
- /* With ccgdm, we have a simple one to one mapping between loops
- * and tessellated face corners. */
- for (i = 0; i < numLoops; i++, tlnors_it++, lnors++) {
- normal_float_to_short_v3(*tlnors_it, *lnors);
- }
- }
-
- return tlnors;
- }
-
- return DM_get_tessface_data_layer(dm, type);
-}
-
static void *ccgDM_get_poly_data_layer(DerivedMesh *dm, int type)
{
if (type == CD_ORIGINDEX) {
@@ -1551,46 +1455,6 @@ static void *ccgDM_get_poly_data_layer(DerivedMesh *dm, int type)
return DM_get_poly_data_layer(dm, type);
}
-static void *ccgDM_get_vert_data(DerivedMesh *dm, int index, int type)
-{
- if (type == CD_ORIGINDEX) {
- /* ensure creation of CD_ORIGINDEX layer */
- ccgDM_get_vert_data_layer(dm, type);
- }
-
- return DM_get_vert_data(dm, index, type);
-}
-
-static void *ccgDM_get_edge_data(DerivedMesh *dm, int index, int type)
-{
- if (type == CD_ORIGINDEX) {
- /* ensure creation of CD_ORIGINDEX layer */
- ccgDM_get_edge_data_layer(dm, type);
- }
-
- return DM_get_edge_data(dm, index, type);
-}
-
-static void *ccgDM_get_tessface_data(DerivedMesh *dm, int index, int type)
-{
- if (ELEM(type, CD_ORIGINDEX, CD_TESSLOOPNORMAL)) {
- /* ensure creation of CD_ORIGINDEX/CD_TESSLOOPNORMAL layers */
- ccgDM_get_tessface_data_layer(dm, type);
- }
-
- return DM_get_tessface_data(dm, index, type);
-}
-
-static void *ccgDM_get_poly_data(DerivedMesh *dm, int index, int type)
-{
- if (type == CD_ORIGINDEX) {
- /* ensure creation of CD_ORIGINDEX layer */
- ccgDM_get_tessface_data_layer(dm, type);
- }
-
- return DM_get_poly_data(dm, index, type);
-}
-
static int ccgDM_getNumGrids(DerivedMesh *dm)
{
CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
@@ -1705,25 +1569,6 @@ static BLI_bitmap **ccgDM_getGridHidden(DerivedMesh *dm)
return ccgdm->gridHidden;
}
-static const MeshElemMap *ccgDM_getPolyMap(Object *ob, DerivedMesh *dm)
-{
- CCGDerivedMesh *ccgdm = (CCGDerivedMesh *)dm;
-
- if (!ccgdm->multires.mmd && !ccgdm->pmap && ob->type == OB_MESH) {
- Mesh *me = ob->data;
-
- BKE_mesh_vert_poly_map_create(&ccgdm->pmap,
- &ccgdm->pmap_mem,
- me->mpoly,
- me->mloop,
- me->totvert,
- me->totpoly,
- me->totloop);
- }
-
- return ccgdm->pmap;
-}
-
/* WARNING! *MUST* be called in an 'loops_cache_rwlock' protected thread context! */
static void ccgDM_recalcLoopTri(DerivedMesh *dm)
{
@@ -1773,17 +1618,11 @@ static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm)
ccgdm->dm.copyVertArray = ccgDM_copyFinalVertArray;
ccgdm->dm.copyEdgeArray = ccgDM_copyFinalEdgeArray;
- ccgdm->dm.copyTessFaceArray = ccgDM_copyFinalFaceArray;
ccgdm->dm.copyLoopArray = ccgDM_copyFinalLoopArray;
ccgdm->dm.copyPolyArray = ccgDM_copyFinalPolyArray;
- ccgdm->dm.getVertData = ccgDM_get_vert_data;
- ccgdm->dm.getEdgeData = ccgDM_get_edge_data;
- ccgdm->dm.getTessFaceData = ccgDM_get_tessface_data;
- ccgdm->dm.getPolyData = ccgDM_get_poly_data;
ccgdm->dm.getVertDataArray = ccgDM_get_vert_data_layer;
ccgdm->dm.getEdgeDataArray = ccgDM_get_edge_data_layer;
- ccgdm->dm.getTessFaceDataArray = ccgDM_get_tessface_data_layer;
ccgdm->dm.getPolyDataArray = ccgDM_get_poly_data_layer;
ccgdm->dm.getNumGrids = ccgDM_getNumGrids;
ccgdm->dm.getGridSize = ccgDM_getGridSize;
@@ -1792,7 +1631,6 @@ static void set_default_ccgdm_callbacks(CCGDerivedMesh *ccgdm)
ccgdm->dm.getGridKey = ccgDM_getGridKey;
ccgdm->dm.getGridFlagMats = ccgDM_getGridFlagMats;
ccgdm->dm.getGridHidden = ccgDM_getGridHidden;
- ccgdm->dm.getPolyMap = ccgDM_getPolyMap;
ccgdm->dm.recalcLoopTri = ccgDM_recalcLoopTri;
@@ -1848,7 +1686,7 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
int index;
int i;
int vertNum = 0, edgeNum = 0, faceNum = 0;
- int *vertOrigIndex, *faceOrigIndex, *polyOrigIndex, *base_polyOrigIndex, *edgeOrigIndex;
+ int *vertOrigIndex, *polyOrigIndex, *base_polyOrigIndex, *edgeOrigIndex;
short *edgeFlags = ccgdm->edgeFlags;
DMFlagMat *faceFlags = ccgdm->faceFlags;
int *polyidx = NULL;
@@ -1884,7 +1722,6 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
vertOrigIndex = DM_get_vert_data_layer(&ccgdm->dm, CD_ORIGINDEX);
edgeOrigIndex = DM_get_edge_data_layer(&ccgdm->dm, CD_ORIGINDEX);
- faceOrigIndex = DM_get_tessface_data_layer(&ccgdm->dm, CD_ORIGINDEX);
polyOrigIndex = DM_get_poly_data_layer(&ccgdm->dm, CD_ORIGINDEX);
has_edge_cd = ((ccgdm->dm.edgeData.totlayer - (edgeOrigIndex ? 1 : 0)) != 0);
@@ -2006,12 +1843,6 @@ static void set_ccgdm_all_geometry(CCGDerivedMesh *ccgdm,
/* Copy over poly data, e.g. #CD_FACEMAP. */
CustomData_copy_data(&dm->polyData, &ccgdm->dm.polyData, origIndex, faceNum, 1);
- /* Set original index data. */
- if (faceOrigIndex) {
- /* reference the index in 'polyOrigIndex' */
- *faceOrigIndex = faceNum;
- faceOrigIndex++;
- }
if (polyOrigIndex) {
*polyOrigIndex = base_polyOrigIndex ? base_polyOrigIndex[origIndex] : origIndex;
polyOrigIndex++;
diff --git a/source/blender/blenkernel/intern/type_conversions.cc b/source/blender/blenkernel/intern/type_conversions.cc
index cb05337ef2a..b2011d2baf7 100644
--- a/source/blender/blenkernel/intern/type_conversions.cc
+++ b/source/blender/blenkernel/intern/type_conversions.cc
@@ -62,6 +62,11 @@ static bool float_to_bool(const float &a)
{
return a > 0.0f;
}
+static int8_t float_to_int8(const float &a)
+{
+ return std::clamp(
+ a, float(std::numeric_limits<int8_t>::min()), float(std::numeric_limits<int8_t>::max()));
+}
static ColorGeometry4f float_to_color(const float &a)
{
return ColorGeometry4f(a, a, a, 1.0f);
@@ -83,6 +88,10 @@ static bool float2_to_bool(const float2 &a)
{
return !is_zero_v2(a);
}
+static int8_t float2_to_int8(const float2 &a)
+{
+ return float_to_int8((a.x + a.y) / 2.0f);
+}
static ColorGeometry4f float2_to_color(const float2 &a)
{
return ColorGeometry4f(a.x, a.y, 0.0f, 1.0f);
@@ -92,6 +101,10 @@ static bool float3_to_bool(const float3 &a)
{
return !is_zero_v3(a);
}
+static int8_t float3_to_int8(const float3 &a)
+{
+ return float_to_int8((a.x + a.y + a.z) / 3.0f);
+}
static float float3_to_float(const float3 &a)
{
return (a.x + a.y + a.z) / 3.0f;
@@ -113,6 +126,11 @@ static bool int_to_bool(const int32_t &a)
{
return a > 0;
}
+static int8_t int_to_int8(const int32_t &a)
+{
+ return std::clamp(
+ a, int(std::numeric_limits<int8_t>::min()), int(std::numeric_limits<int8_t>::max()));
+}
static float int_to_float(const int32_t &a)
{
return (float)a;
@@ -130,10 +148,39 @@ static ColorGeometry4f int_to_color(const int32_t &a)
return ColorGeometry4f((float)a, (float)a, (float)a, 1.0f);
}
+static bool int8_to_bool(const int8_t &a)
+{
+ return a > 0;
+}
+static int int8_to_int(const int8_t &a)
+{
+ return static_cast<int>(a);
+}
+static float int8_to_float(const int8_t &a)
+{
+ return (float)a;
+}
+static float2 int8_to_float2(const int8_t &a)
+{
+ return float2((float)a);
+}
+static float3 int8_to_float3(const int8_t &a)
+{
+ return float3((float)a);
+}
+static ColorGeometry4f int8_to_color(const int8_t &a)
+{
+ return ColorGeometry4f((float)a, (float)a, (float)a, 1.0f);
+}
+
static float bool_to_float(const bool &a)
{
return (bool)a;
}
+static int8_t bool_to_int8(const bool &a)
+{
+ return static_cast<int8_t>(a);
+}
static int32_t bool_to_int(const bool &a)
{
return (int32_t)a;
@@ -163,6 +210,10 @@ static int32_t color_to_int(const ColorGeometry4f &a)
{
return (int)rgb_to_grayscale(a);
}
+static int8_t color_to_int8(const ColorGeometry4f &a)
+{
+ return int_to_int8(color_to_int(a));
+}
static float2 color_to_float2(const ColorGeometry4f &a)
{
return float2(a.r, a.g);
@@ -180,33 +231,46 @@ static DataTypeConversions create_implicit_conversions()
add_implicit_conversion<float, float3, float_to_float3>(conversions);
add_implicit_conversion<float, int32_t, float_to_int>(conversions);
add_implicit_conversion<float, bool, float_to_bool>(conversions);
+ add_implicit_conversion<float, int8_t, float_to_int8>(conversions);
add_implicit_conversion<float, ColorGeometry4f, float_to_color>(conversions);
add_implicit_conversion<float2, float3, float2_to_float3>(conversions);
add_implicit_conversion<float2, float, float2_to_float>(conversions);
add_implicit_conversion<float2, int32_t, float2_to_int>(conversions);
add_implicit_conversion<float2, bool, float2_to_bool>(conversions);
+ add_implicit_conversion<float2, int8_t, float2_to_int8>(conversions);
add_implicit_conversion<float2, ColorGeometry4f, float2_to_color>(conversions);
add_implicit_conversion<float3, bool, float3_to_bool>(conversions);
+ add_implicit_conversion<float3, int8_t, float3_to_int8>(conversions);
add_implicit_conversion<float3, float, float3_to_float>(conversions);
add_implicit_conversion<float3, int32_t, float3_to_int>(conversions);
add_implicit_conversion<float3, float2, float3_to_float2>(conversions);
add_implicit_conversion<float3, ColorGeometry4f, float3_to_color>(conversions);
add_implicit_conversion<int32_t, bool, int_to_bool>(conversions);
+ add_implicit_conversion<int32_t, int8_t, int_to_int8>(conversions);
add_implicit_conversion<int32_t, float, int_to_float>(conversions);
add_implicit_conversion<int32_t, float2, int_to_float2>(conversions);
add_implicit_conversion<int32_t, float3, int_to_float3>(conversions);
add_implicit_conversion<int32_t, ColorGeometry4f, int_to_color>(conversions);
+ add_implicit_conversion<int8_t, bool, int8_to_bool>(conversions);
+ add_implicit_conversion<int8_t, int32_t, int8_to_int>(conversions);
+ add_implicit_conversion<int8_t, float, int8_to_float>(conversions);
+ add_implicit_conversion<int8_t, float2, int8_to_float2>(conversions);
+ add_implicit_conversion<int8_t, float3, int8_to_float3>(conversions);
+ add_implicit_conversion<int8_t, ColorGeometry4f, int8_to_color>(conversions);
+
add_implicit_conversion<bool, float, bool_to_float>(conversions);
+ add_implicit_conversion<bool, int8_t, bool_to_int8>(conversions);
add_implicit_conversion<bool, int32_t, bool_to_int>(conversions);
add_implicit_conversion<bool, float2, bool_to_float2>(conversions);
add_implicit_conversion<bool, float3, bool_to_float3>(conversions);
add_implicit_conversion<bool, ColorGeometry4f, bool_to_color>(conversions);
add_implicit_conversion<ColorGeometry4f, bool, color_to_bool>(conversions);
+ add_implicit_conversion<ColorGeometry4f, int8_t, color_to_int8>(conversions);
add_implicit_conversion<ColorGeometry4f, float, color_to_float>(conversions);
add_implicit_conversion<ColorGeometry4f, int32_t, color_to_int>(conversions);
add_implicit_conversion<ColorGeometry4f, float2, color_to_float2>(conversions);
diff --git a/source/blender/blenkernel/intern/vfontdata_freetype.c b/source/blender/blenkernel/intern/vfontdata_freetype.c
index 9b79d5635d1..60b7e4e5c8b 100644
--- a/source/blender/blenkernel/intern/vfontdata_freetype.c
+++ b/source/blender/blenkernel/intern/vfontdata_freetype.c
@@ -15,6 +15,10 @@
*
* The Original Code is written by Rob Haarsma (phase)
* All rights reserved.
+ */
+
+/** \file
+ * \ingroup bke
*
* This code parses the Freetype font outline data to chains of Blender's bezier-triples.
* Additional information can be found at the bottom of this file.
@@ -22,10 +26,6 @@
* Code that uses exotic character maps is present but commented out.
*/
-/** \file
- * \ingroup bke
- */
-
#include <ft2build.h>
#include FT_FREETYPE_H
/* not needed yet */
diff --git a/source/blender/blenkernel/intern/writeavi.c b/source/blender/blenkernel/intern/writeavi.c
index a4f20f980b4..138c75acd7b 100644
--- a/source/blender/blenkernel/intern/writeavi.c
+++ b/source/blender/blenkernel/intern/writeavi.c
@@ -15,11 +15,11 @@
*
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
* All rights reserved.
- * Functions for writing avi-format files.
- * Added interface for generic movie support (ton)
*/
/** \file
+ * Functions for writing AVI-format files.
+ * Added interface for generic movie support (ton)
* \ingroup bke
*/