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:
-rw-r--r--doc/python_api/examples/bpy.types.Depsgraph.7.py64
-rw-r--r--source/blender/blenkernel/BKE_curve.h12
-rw-r--r--source/blender/blenkernel/BKE_displist.h7
-rw-r--r--source/blender/blenkernel/BKE_object.h16
-rw-r--r--source/blender/blenkernel/CMakeLists.txt1
-rw-r--r--source/blender/blenkernel/intern/curve_convert.c81
-rw-r--r--source/blender/blenkernel/intern/displist.c24
-rw-r--r--source/blender/blenkernel/intern/object.c20
-rw-r--r--source/blender/makesdna/DNA_object_types.h9
-rw-r--r--source/blender/makesrna/intern/rna_object_api.c46
10 files changed, 270 insertions, 10 deletions
diff --git a/doc/python_api/examples/bpy.types.Depsgraph.7.py b/doc/python_api/examples/bpy.types.Depsgraph.7.py
new file mode 100644
index 00000000000..61209a6b9d2
--- /dev/null
+++ b/doc/python_api/examples/bpy.types.Depsgraph.7.py
@@ -0,0 +1,64 @@
+"""
+Dependency graph: Object.to_curve()
++++++++++++++++++++++++++++++++++++
+
+Function to get a curve from text and curve objects. It is typically used by exporters, render
+engines, and tools that need to access the curve representing the object.
+
+The function takes the evaluated dependency graph as a required parameter and optionally a boolean
+apply_modifiers which defaults to false. If apply_modifiers is true and the object is a curve object,
+the spline deform modifiers are applied on the control points. Note that constructive modifiers and
+modifiers that are not spline-enabled will not be applied. So modifiers like Array will not be applied
+and deform modifiers that have Apply On Spline disabled will not be applied.
+
+If the object is a text object. The text will be converted into a 3D curve and returned. Modifiers are
+never applied on text objects and apply_modifiers will be ignored. If the object is neither a curve nor
+a text object, an error will be reported.
+
+.. note:: The resulting curve is owned by the object. It can be freed by calling `object.to_curve_clear()`.
+.. note::
+ The resulting curve must be treated as temporary, and can not be referenced from objects in the main
+ database.
+"""
+import bpy
+
+
+class OBJECT_OT_object_to_curve(bpy.types.Operator):
+ """Convert selected object to curve and show number of splines"""
+ bl_label = "DEG Object to Curve"
+ bl_idname = "object.object_to_curve"
+
+ def execute(self, context):
+ # Access input original object.
+ obj = context.object
+ if obj is None:
+ self.report({'INFO'}, "No active object to convert to curve")
+ return {'CANCELLED'}
+ if obj.type not in {'CURVE', 'FONT'}:
+ self.report({'INFO'}, "Object can not be converted to curve")
+ return {'CANCELLED'}
+ depsgraph = context.evaluated_depsgraph_get()
+ # Invoke to_curve() without applying modifiers.
+ curve_without_modifiers = obj.to_curve(depsgraph)
+ self.report({'INFO'}, f"{len(curve_without_modifiers.splines)} splines in a new curve without modifiers.")
+ # Remove temporary curve.
+ obj.to_curve_clear()
+ # Invoke to_curve() with applying modifiers.
+ curve_with_modifiers = obj.to_curve(depsgraph, apply_modifiers = True)
+ self.report({'INFO'}, f"{len(curve_with_modifiers.splines)} splines in new curve with modifiers.")
+ # Remove temporary curve.
+ obj.to_curve_clear()
+ return {'FINISHED'}
+
+
+def register():
+ bpy.utils.register_class(OBJECT_OT_object_to_curve)
+
+
+def unregister():
+ bpy.utils.unregister_class(OBJECT_OT_object_to_curve)
+
+
+if __name__ == "__main__":
+ register()
+
diff --git a/source/blender/blenkernel/BKE_curve.h b/source/blender/blenkernel/BKE_curve.h
index 881b93fe709..660e7c08062 100644
--- a/source/blender/blenkernel/BKE_curve.h
+++ b/source/blender/blenkernel/BKE_curve.h
@@ -338,6 +338,18 @@ void BKE_curve_deform_co(const struct Object *ob_curve,
/** \} */
+/* curve_convert.c */
+
+/* Create a new curve from the given object at its current state. This only works for curve and
+ * text objects, otherwise NULL is returned.
+ *
+ * If apply_modifiers is true and the object is a curve one, then spline deform modifiers are
+ * applied on the control points of the splines.
+ */
+struct Curve *BKE_curve_new_from_object(struct Object *object,
+ struct Depsgraph *depsgraph,
+ bool apply_modifiers);
+
#ifdef __cplusplus
}
#endif
diff --git a/source/blender/blenkernel/BKE_displist.h b/source/blender/blenkernel/BKE_displist.h
index 83adbf6f1fd..05e60d38487 100644
--- a/source/blender/blenkernel/BKE_displist.h
+++ b/source/blender/blenkernel/BKE_displist.h
@@ -112,6 +112,13 @@ void BKE_displist_make_mball_forRender(struct Depsgraph *depsgraph,
struct Object *ob,
struct ListBase *dispbase);
+bool BKE_curve_calc_modifiers_pre(struct Depsgraph *depsgraph,
+ struct Scene *scene,
+ struct Object *ob,
+ struct ListBase *source_nurb,
+ struct ListBase *target_nurb,
+ const bool for_render);
+
bool BKE_displist_surfindex_get(DispList *dl, int a, int *b, int *p1, int *p2, int *p3, int *p4);
void BKE_displist_fill(const struct ListBase *dispbase,
struct ListBase *to,
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 904db053717..12c40e891c9 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -32,6 +32,7 @@ extern "C" {
struct Base;
struct BoundBox;
+struct Curve;
struct Depsgraph;
struct GpencilModifierData;
struct HookGpencilModifierData;
@@ -424,6 +425,21 @@ struct Mesh *BKE_object_to_mesh(struct Depsgraph *depsgraph,
void BKE_object_to_mesh_clear(struct Object *object);
+/* This is an utility function for Python's object.to_curve().
+ * The result is owned by the object.
+ *
+ * The curve will be freed when object is re-evaluated or is destroyed. It is possible to force
+ * clear memory used by this curve by calling BKE_object_to_curve_clear().
+ *
+ * If apply_modifiers is true and the object is a curve one, then spline deform modifiers are
+ * applied on the curve control points.
+ */
+struct Curve *BKE_object_to_curve(struct Object *object,
+ struct Depsgraph *depsgraph,
+ bool apply_modifiers);
+
+void BKE_object_to_curve_clear(struct Object *object);
+
void BKE_object_check_uuids_unique_and_report(const struct Object *object);
void BKE_object_modifiers_lib_link_common(void *userData,
diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt
index f288bf9aabc..325744f4006 100644
--- a/source/blender/blenkernel/CMakeLists.txt
+++ b/source/blender/blenkernel/CMakeLists.txt
@@ -107,6 +107,7 @@ set(SRC
intern/cryptomatte.cc
intern/curve.c
intern/curve_bevel.c
+ intern/curve_convert.c
intern/curve_decimate.c
intern/curve_deform.c
intern/curveprofile.c
diff --git a/source/blender/blenkernel/intern/curve_convert.c b/source/blender/blenkernel/intern/curve_convert.c
new file mode 100644
index 00000000000..988ddb3bbc0
--- /dev/null
+++ b/source/blender/blenkernel/intern/curve_convert.c
@@ -0,0 +1,81 @@
+/*
+ * 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 "DNA_curve_types.h"
+#include "DNA_object_types.h"
+#include "DNA_vfont_types.h"
+
+#include "BLI_utildefines.h"
+
+#include "BKE_curve.h"
+#include "BKE_displist.h"
+#include "BKE_font.h"
+#include "BKE_lib_id.h"
+#include "BKE_modifier.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
+
+static Curve *curve_from_font_object(Object *object, Depsgraph *depsgraph)
+{
+ Curve *curve = (Curve *)object->data;
+ Curve *new_curve = (Curve *)BKE_id_copy_ex(NULL, &curve->id, NULL, LIB_ID_COPY_LOCALIZE);
+
+ Object *evaluated_object = DEG_get_evaluated_object(depsgraph, object);
+ BKE_vfont_to_curve_nubase(evaluated_object, FO_EDIT, &new_curve->nurb);
+
+ new_curve->type = OB_CURVE;
+
+ new_curve->flag &= ~CU_3D;
+ BKE_curve_curve_dimension_update(new_curve);
+
+ return new_curve;
+}
+
+static Curve *curve_from_curve_object(Object *object, Depsgraph *depsgraph, bool apply_modifiers)
+{
+ Object *evaluated_object = DEG_get_evaluated_object(depsgraph, object);
+ Curve *curve = (Curve *)evaluated_object->data;
+ Curve *new_curve = (Curve *)BKE_id_copy_ex(NULL, &curve->id, NULL, LIB_ID_COPY_LOCALIZE);
+
+ if (apply_modifiers) {
+ BKE_curve_calc_modifiers_pre(depsgraph,
+ DEG_get_input_scene(depsgraph),
+ evaluated_object,
+ BKE_curve_nurbs_get(curve),
+ &new_curve->nurb,
+ DEG_get_mode(depsgraph) == DAG_EVAL_RENDER);
+ }
+
+ return new_curve;
+}
+
+Curve *BKE_curve_new_from_object(Object *object, Depsgraph *depsgraph, bool apply_modifiers)
+{
+ if (!ELEM(object->type, OB_FONT, OB_CURVE)) {
+ return NULL;
+ }
+
+ if (object->type == OB_FONT) {
+ return curve_from_font_object(object, depsgraph);
+ }
+
+ return curve_from_curve_object(object, depsgraph, apply_modifiers);
+}
diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c
index 1fcc1b1bcef..c860e57520d 100644
--- a/source/blender/blenkernel/intern/displist.c
+++ b/source/blender/blenkernel/intern/displist.c
@@ -770,8 +770,12 @@ static ModifierData *curve_get_tessellate_point(Scene *scene,
}
/* Return true if any modifier was applied. */
-static bool curve_calc_modifiers_pre(
- Depsgraph *depsgraph, Scene *scene, Object *ob, ListBase *nurb, const bool for_render)
+bool BKE_curve_calc_modifiers_pre(Depsgraph *depsgraph,
+ Scene *scene,
+ Object *ob,
+ ListBase *source_nurb,
+ ListBase *target_nurb,
+ const bool for_render)
{
VirtualModifierData virtualModifierData;
ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob, &virtualModifierData);
@@ -810,13 +814,13 @@ static bool curve_calc_modifiers_pre(
keyVerts = BKE_key_evaluate_object(ob, &numElems);
if (keyVerts) {
- BLI_assert(BKE_keyblock_curve_element_count(nurb) == numElems);
+ BLI_assert(BKE_keyblock_curve_element_count(source_nurb) == numElems);
/* split coords from key data, the latter also includes
* tilts, which is passed through in the modifier stack.
* this is also the reason curves do not use a virtual
* shape key modifier yet. */
- deformedVerts = BKE_curve_nurbs_key_vert_coords_alloc(nurb, keyVerts, &numVerts);
+ deformedVerts = BKE_curve_nurbs_key_vert_coords_alloc(source_nurb, keyVerts, &numVerts);
}
}
@@ -832,7 +836,7 @@ static bool curve_calc_modifiers_pre(
}
if (!deformedVerts) {
- deformedVerts = BKE_curve_nurbs_vert_coords_alloc(nurb, &numVerts);
+ deformedVerts = BKE_curve_nurbs_vert_coords_alloc(source_nurb, &numVerts);
}
mti->deformVerts(md, &mectx, NULL, deformedVerts, numVerts);
@@ -845,11 +849,11 @@ static bool curve_calc_modifiers_pre(
}
if (deformedVerts) {
- BKE_curve_nurbs_vert_coords_apply(nurb, deformedVerts, false);
+ BKE_curve_nurbs_vert_coords_apply(target_nurb, deformedVerts, false);
MEM_freeN(deformedVerts);
}
if (keyVerts) { /* these are not passed through modifier stack */
- BKE_curve_nurbs_key_vert_tilts_apply(nurb, keyVerts);
+ BKE_curve_nurbs_key_vert_tilts_apply(target_nurb, keyVerts);
}
if (keyVerts) {
@@ -1151,7 +1155,8 @@ void BKE_displist_make_surf(Depsgraph *depsgraph,
}
if (!for_orco) {
- force_mesh_conversion = curve_calc_modifiers_pre(depsgraph, scene, ob, &nubase, for_render);
+ force_mesh_conversion = BKE_curve_calc_modifiers_pre(
+ depsgraph, scene, ob, &nubase, &nubase, for_render);
}
LISTBASE_FOREACH (Nurb *, nu, &nubase) {
@@ -1501,7 +1506,8 @@ static void do_makeDispListCurveTypes(Depsgraph *depsgraph,
}
if (!for_orco) {
- force_mesh_conversion = curve_calc_modifiers_pre(depsgraph, scene, ob, &nubase, for_render);
+ force_mesh_conversion = BKE_curve_calc_modifiers_pre(
+ depsgraph, scene, ob, &nubase, &nubase, for_render);
}
BKE_curve_bevelList_make(ob, &nubase, for_render);
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 9b5a1614dc0..04071282a52 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -1742,6 +1742,7 @@ void BKE_object_free_derived_caches(Object *ob)
}
BKE_object_to_mesh_clear(ob);
+ BKE_object_to_curve_clear(ob);
BKE_object_free_curve_cache(ob);
/* Clear grease pencil data. */
@@ -5057,6 +5058,7 @@ void BKE_object_runtime_reset_on_copy(Object *object, const int UNUSED(flag))
runtime->mesh_deform_eval = NULL;
runtime->curve_cache = NULL;
runtime->object_as_temp_mesh = NULL;
+ runtime->object_as_temp_curve = NULL;
runtime->geometry_set_eval = NULL;
}
@@ -5615,6 +5617,24 @@ void BKE_object_to_mesh_clear(Object *object)
object->runtime.object_as_temp_mesh = NULL;
}
+Curve *BKE_object_to_curve(Object *object, Depsgraph *depsgraph, bool apply_modifiers)
+{
+ BKE_object_to_curve_clear(object);
+
+ Curve *curve = BKE_curve_new_from_object(object, depsgraph, apply_modifiers);
+ object->runtime.object_as_temp_curve = curve;
+ return curve;
+}
+
+void BKE_object_to_curve_clear(Object *object)
+{
+ if (object->runtime.object_as_temp_curve == NULL) {
+ return;
+ }
+ BKE_id_free(NULL, object->runtime.object_as_temp_curve);
+ object->runtime.object_as_temp_curve = NULL;
+}
+
void BKE_object_check_uuids_unique_and_report(const Object *object)
{
BKE_pose_check_uuids_unique_and_report(object->pose);
diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h
index 8b13db8a012..5f414aa2bdd 100644
--- a/source/blender/makesdna/DNA_object_types.h
+++ b/source/blender/makesdna/DNA_object_types.h
@@ -38,6 +38,7 @@ extern "C" {
struct AnimData;
struct BoundBox;
+struct Curve;
struct FluidsimSettings;
struct GeometrySet;
struct Ipo;
@@ -186,6 +187,12 @@ typedef struct Object_Runtime {
*/
struct Mesh *object_as_temp_mesh;
+ /**
+ * This is a curve representation of corresponding object.
+ * It created when Python calls `object.to_curve()`.
+ */
+ struct Curve *object_as_temp_curve;
+
/** Runtime evaluated curve-specific data, not stored in the file. */
struct CurveCache *curve_cache;
@@ -623,7 +630,7 @@ enum {
*/
#define BA_TRANSFORM_LOCKED_IN_PLACE (1 << 7)
-#define BA_TRANSFORM_CHILD (1 << 8) /* child of a transformed object */
+#define BA_TRANSFORM_CHILD (1 << 8) /* child of a transformed object */
#define BA_TRANSFORM_PARENT (1 << 13) /* parent of a transformed object */
#define OB_FROMDUPLI (1 << 9)
diff --git a/source/blender/makesrna/intern/rna_object_api.c b/source/blender/makesrna/intern/rna_object_api.c
index 9fb883568c9..df628caa000 100644
--- a/source/blender/makesrna/intern/rna_object_api.c
+++ b/source/blender/makesrna/intern/rna_object_api.c
@@ -404,6 +404,29 @@ static void rna_Object_to_mesh_clear(Object *object)
BKE_object_to_mesh_clear(object);
}
+static Curve *rna_Object_to_curve(Object *object,
+ ReportList *reports,
+ Depsgraph *depsgraph,
+ bool apply_modifiers)
+{
+ if (!ELEM(object->type, OB_FONT, OB_CURVE)) {
+ BKE_report(reports, RPT_ERROR, "Object is not a curve or a text");
+ return NULL;
+ }
+
+ if (depsgraph == NULL) {
+ BKE_report(reports, RPT_ERROR, "Invalid depsgraph");
+ return NULL;
+ }
+
+ return BKE_object_to_curve(object, depsgraph, apply_modifiers);
+}
+
+static void rna_Object_to_curve_clear(Object *object)
+{
+ BKE_object_to_curve_clear(object);
+}
+
static PointerRNA rna_Object_shape_key_add(
Object *ob, bContext *C, ReportList *reports, const char *name, bool from_mix)
{
@@ -977,6 +1000,29 @@ void RNA_api_object(StructRNA *srna)
func = RNA_def_function(srna, "to_mesh_clear", "rna_Object_to_mesh_clear");
RNA_def_function_ui_description(func, "Clears mesh data-block created by to_mesh()");
+ /* curve */
+ func = RNA_def_function(srna, "to_curve", "rna_Object_to_curve");
+ RNA_def_function_ui_description(
+ func,
+ "Create a Curve data-block from the current state of the object. This only works for curve "
+ "and text objects. The object owns the data-block. To force free it, use to_curve_clear(). "
+ "The result is temporary and can not be used by objects from the main database");
+ RNA_def_function_flag(func, FUNC_USE_REPORTS);
+ parm = RNA_def_pointer(
+ func, "depsgraph", "Depsgraph", "Dependency Graph", "Evaluated dependency graph");
+ RNA_def_parameter_flags(parm, 0, PARM_REQUIRED);
+ RNA_def_boolean(func,
+ "apply_modifiers",
+ false,
+ "",
+ "Apply the deform modifiers on the control points of the curve. This is only "
+ "supported for curve objects");
+ parm = RNA_def_pointer(func, "curve", "Curve", "", "Curve created from object");
+ RNA_def_function_return(func, parm);
+
+ func = RNA_def_function(srna, "to_curve_clear", "rna_Object_to_curve_clear");
+ RNA_def_function_ui_description(func, "Clears curve data-block created by to_curve()");
+
/* Armature */
func = RNA_def_function(srna, "find_armature", "BKE_modifiers_is_deformed_by_armature");
RNA_def_function_ui_description(