diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py index 5bb9c151c2c..4ad178bc064 100644 --- a/release/scripts/startup/bl_ui/properties_constraint.py +++ b/release/scripts/startup/bl_ui/properties_constraint.py @@ -726,9 +726,12 @@ class ConstraintButtonsPanel(): if con.shrinkwrap_type == 'PROJECT': row = layout.row(align=True) - row.prop(con, "use_x") - row.prop(con, "use_y") - row.prop(con, "use_z") + row.prop(con, "project_axis", expand=True) + split = layout.split(percentage=0.4) + split.label(text="Axis Space:") + rowsub = split.row() + rowsub.prop(con, "project_axis_space", text="") + layout.prop(con, "project_limit") def DAMPED_TRACK(self, context, layout, con): self.target_template(layout, con) diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index 13fd4b2bab7..6507999e9db 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 268 -#define BLENDER_SUBVERSION 3 +#define BLENDER_SUBVERSION 4 /* 262 was the last editmesh release but it has compatibility code for bmesh data */ #define BLENDER_MINVERSION 262 #define BLENDER_MINSUBVERSION 0 diff --git a/source/blender/blenkernel/BKE_shrinkwrap.h b/source/blender/blenkernel/BKE_shrinkwrap.h index 61d82e6c604..323a926863c 100644 --- a/source/blender/blenkernel/BKE_shrinkwrap.h +++ b/source/blender/blenkernel/BKE_shrinkwrap.h @@ -134,9 +134,9 @@ void shrinkwrapModifier_deform(struct ShrinkwrapModifierData *smd, struct Object * Thus it provides an easy way to cast the same ray across several trees * (where each tree was built on its own coords space) */ -int normal_projection_project_vertex(char options, const float vert[3], const float dir[3], - const SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit, - BVHTree_RayCastCallback callback, void *userdata); +int BKE_shrinkwrap_project_normal(char options, const float vert[3], const float dir[3], + const SpaceTransform *transf, BVHTree *tree, BVHTreeRayHit *hit, + BVHTree_RayCastCallback callback, void *userdata); /* * NULL initializers to local data diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 7b7d20a54e0..1f892432d80 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -3308,6 +3308,14 @@ static void shrinkwrap_id_looper(bConstraint *con, ConstraintIDFunc func, void * func(con, (ID **)&data->target, FALSE, userdata); } +static void shrinkwrap_new_data(void *cdata) +{ + bShrinkwrapConstraint *data = (bShrinkwrapConstraint *)cdata; + + data->projAxis = OB_POSZ; + data->projAxisSpace = CONSTRAINT_SPACE_LOCAL; +} + static int shrinkwrap_get_tars(bConstraint *con, ListBase *list) { if (con && list) { @@ -3339,24 +3347,14 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra bShrinkwrapConstraint *scon = (bShrinkwrapConstraint *) con->data; if (VALID_CONS_TARGET(ct) && (ct->tar->type == OB_MESH) ) { - int fail = FALSE; + bool fail = false; float co[3] = {0.0f, 0.0f, 0.0f}; - float no[3] = {0.0f, 0.0f, 0.0f}; - float dist; SpaceTransform transform; DerivedMesh *target = object_get_derived_final(ct->tar); - BVHTreeRayHit hit; - BVHTreeNearest nearest; BVHTreeFromMesh treeData = {NULL}; - nearest.index = -1; - nearest.dist = FLT_MAX; - - hit.index = -1; - hit.dist = 100000.0f; //TODO should use FLT_MAX.. but normal projection doenst yet supports it - unit_m4(ct->matrix); if (target != NULL) { @@ -3365,7 +3363,13 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra switch (scon->shrinkType) { case MOD_SHRINKWRAP_NEAREST_SURFACE: case MOD_SHRINKWRAP_NEAREST_VERTEX: - + { + BVHTreeNearest nearest; + float dist; + + nearest.index = -1; + nearest.dist = FLT_MAX; + if (scon->shrinkType == MOD_SHRINKWRAP_NEAREST_VERTEX) bvhtree_from_mesh_verts(&treeData, target, 0.0, 2, 6); else @@ -3386,30 +3390,54 @@ static void shrinkwrap_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra } space_transform_invert(&transform, co); break; - + } case MOD_SHRINKWRAP_PROJECT: - if (scon->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS) no[0] = 1.0f; - if (scon->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS) no[1] = 1.0f; - if (scon->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS) no[2] = 1.0f; + { + BVHTreeRayHit hit; + + float mat[4][4]; + float no[3] = {0.0f, 0.0f, 0.0f}; + + /* TODO should use FLT_MAX.. but normal projection doenst yet supports it */ + hit.index = -1; + hit.dist = (scon->projLimit == 0.0f) ? 100000.0f : scon->projLimit; + + switch (scon->projAxis) { + case OB_POSX: case OB_POSY: case OB_POSZ: + no[scon->projAxis - OB_POSX] = 1.0f; + break; + case OB_NEGX: case OB_NEGY: case OB_NEGZ: + no[scon->projAxis - OB_NEGX] = -1.0f; + break; + } + /* transform normal into requested space */ + unit_m4(mat); + BKE_constraint_mat_convertspace(cob->ob, cob->pchan, mat, CONSTRAINT_SPACE_LOCAL, scon->projAxisSpace); + invert_m4(mat); + mul_mat3_m4_v3(mat, no); + if (normalize_v3(no) < FLT_EPSILON) { fail = TRUE; break; } - - + bvhtree_from_mesh_faces(&treeData, target, scon->dist, 4, 6); if (treeData.tree == NULL) { fail = TRUE; break; } + - if (normal_projection_project_vertex(0, co, no, &transform, treeData.tree, &hit, treeData.raycast_callback, &treeData) == FALSE) { + if (BKE_shrinkwrap_project_normal(0, co, no, &transform, treeData.tree, &hit, + treeData.raycast_callback, &treeData) == false) + { fail = TRUE; break; } copy_v3_v3(co, hit.co); break; + } } free_bvhtree_from_mesh(&treeData); @@ -3446,7 +3474,7 @@ static bConstraintTypeInfo CTI_SHRINKWRAP = { NULL, /* free data */ shrinkwrap_id_looper, /* id looper */ NULL, /* copy data */ - NULL, /* new data */ + shrinkwrap_new_data, /* new data */ shrinkwrap_get_tars, /* get constraint targets */ shrinkwrap_flush_tars, /* flush constraint targets */ shrinkwrap_get_tarmat, /* get a target matrix */ diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index b9843ad0619..9bc7f4b9e2b 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -198,10 +198,10 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) * MOD_SHRINKWRAP_CULL_TARGET_FRONTFACE (front faces hits are ignored) * MOD_SHRINKWRAP_CULL_TARGET_BACKFACE (back faces hits are ignored) */ -int normal_projection_project_vertex(char options, const float vert[3], const float dir[3], - const SpaceTransform *transf, - BVHTree *tree, BVHTreeRayHit *hit, - BVHTree_RayCastCallback callback, void *userdata) +int BKE_shrinkwrap_project_normal(char options, const float vert[3], + const float dir[3], const SpaceTransform *transf, + BVHTree *tree, BVHTreeRayHit *hit, + BVHTree_RayCastCallback callback, void *userdata) { /* don't use this because this dist value could be incompatible * this value used by the callback for comparing prev/new dist values. @@ -368,14 +368,14 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) if (use_normal & MOD_SHRINKWRAP_PROJECT_ALLOW_POS_DIR) { if (auxData.tree) { - normal_projection_project_vertex(0, tmp_co, tmp_no, - &local2aux, auxData.tree, &hit, - auxData.raycast_callback, &auxData); + BKE_shrinkwrap_project_normal(0, tmp_co, tmp_no, + &local2aux, auxData.tree, &hit, + auxData.raycast_callback, &auxData); } - normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, tmp_no, - &calc->local2target, treeData.tree, &hit, - treeData.raycast_callback, &treeData); + BKE_shrinkwrap_project_normal(calc->smd->shrinkOpts, tmp_co, tmp_no, + &calc->local2target, treeData.tree, &hit, + treeData.raycast_callback, &treeData); } /* Project over negative direction of axis */ @@ -384,14 +384,14 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) negate_v3_v3(inv_no, tmp_no); if (auxData.tree) { - normal_projection_project_vertex(0, tmp_co, inv_no, - &local2aux, auxData.tree, &hit, - auxData.raycast_callback, &auxData); + BKE_shrinkwrap_project_normal(0, tmp_co, inv_no, + &local2aux, auxData.tree, &hit, + auxData.raycast_callback, &auxData); } - normal_projection_project_vertex(calc->smd->shrinkOpts, tmp_co, inv_no, - &calc->local2target, treeData.tree, &hit, - treeData.raycast_callback, &treeData); + BKE_shrinkwrap_project_normal(calc->smd->shrinkOpts, tmp_co, inv_no, + &calc->local2target, treeData.tree, &hit, + treeData.raycast_callback, &treeData); } /* don't set the initial dist (which is more efficient), diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 0cd473fd74d..af2da2361d3 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -9530,8 +9530,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main) } } - if (MAIN_VERSION_OLDER(main, 267, 1)) - { + if (MAIN_VERSION_OLDER(main, 267, 1)) { Object *ob; for (ob = main->object.first; ob; ob = ob->id.next) { @@ -9575,10 +9574,24 @@ static void do_versions(FileData *fd, Library *lib, Main *main) #undef BRUSH_FIXED } - { + + if (!MAIN_VERSION_ATLEAST(main, 268, 4)) { bScreen *sc; Object *ob; + for (ob = main->object.first; ob; ob = ob->id.next) { + bConstraint *con; + for (con = ob->constraints.first; con; con = con->next) { + if (con->type == CONSTRAINT_TYPE_SHRINKWRAP) { + bShrinkwrapConstraint *data = (bShrinkwrapConstraint *)con->data; + if (data->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS) data->projAxis = OB_POSX; + else if (data->projAxis & MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS) data->projAxis = OB_POSY; + else data->projAxis = OB_POSZ; + data->projAxisSpace = CONSTRAINT_SPACE_LOCAL; + } + } + } + for (ob = main->object.first; ob; ob = ob->id.next) { ModifierData *md; for (md = ob->modifiers.first; md; md = md->next) { diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index f1b7a7c3cc3..29e49a970d8 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -407,8 +407,10 @@ typedef struct bShrinkwrapConstraint { struct Object *target; float dist; /* distance to kept from target */ short shrinkType; /* shrink type (look on MOD shrinkwrap for values) */ - char projAxis; /* axis to project over UP_X, UP_Y, UP_Z */ - char pad[9]; + char projAxis; /* axis to project/constrain */ + char projAxisSpace; /* space to project axis in */ + float projLimit; /* distance to search */ + char pad[4]; } bShrinkwrapConstraint; /* Follow Track constraints */ diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 6a1aa37d0cc..8c7857a3f0b 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -37,6 +37,7 @@ #include "DNA_scene_types.h" #include "RNA_define.h" +#include "RNA_enum_types.h" #include "rna_internal.h" @@ -2025,20 +2026,23 @@ static void rna_def_constraint_shrinkwrap(BlenderRNA *brna) RNA_def_property_range(prop, 0.0, 100.f); RNA_def_property_ui_text(prop, "Distance", "Distance to Target"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - - prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "projAxis", MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS); - RNA_def_property_ui_text(prop, "Axis X", "Projection over X Axis"); + + prop = RNA_def_property(srna, "project_axis", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "projAxis"); + RNA_def_property_enum_items(prop, object_axis_items); + RNA_def_property_ui_text(prop, "Project Axis", "Axis constrain to"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - - prop = RNA_def_property(srna, "use_y", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "projAxis", MOD_SHRINKWRAP_PROJECT_OVER_Y_AXIS); - RNA_def_property_ui_text(prop, "Axis Y", "Projection over Y Axis"); - RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); - - prop = RNA_def_property(srna, "use_z", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "projAxis", MOD_SHRINKWRAP_PROJECT_OVER_Z_AXIS); - RNA_def_property_ui_text(prop, "Axis Z", "Projection over Z Axis"); + + prop = RNA_def_property(srna, "project_axis_space", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_sdna(prop, NULL, "projAxisSpace"); + RNA_def_property_enum_items(prop, owner_space_pchan_items); + RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Constraint_owner_space_itemf"); + RNA_def_property_ui_text(prop, "Axis Space", "Space for the projection axis"); + + prop = RNA_def_property(srna, "project_limit", PROP_FLOAT, PROP_DISTANCE); + RNA_def_property_float_sdna(prop, NULL, "projLimit"); + RNA_def_property_range(prop, 0.0, 100.f); + RNA_def_property_ui_text(prop, "Project Distance", "Limit the distance used for projection (zero disables)"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); }