Project option for snap to faces.

This is similar to the old retopo all option but uses the snapping code and not the openGL depth buffer (it's thus more precise).

Not sure if making it available as a snap option is sensible, this is up for discussion.

NOTE: it will get slow fast on large meshes, we need to plug in an acceleration structure into snapping.

This will need an icon too.
This commit is contained in:
Martin Poirier 2009-10-12 22:33:32 +00:00
parent 1fc616351b
commit 3a1216a2f2
14 changed files with 322 additions and 260 deletions

@ -1174,6 +1174,7 @@ int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Strok
SK_Stroke *snap_stk;
float vec[3];
float no[3];
float mval[2];
int found = 0;
int dist = SNAP_MIN_DISTANCE; // Use a user defined value here
@ -1197,9 +1198,12 @@ int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, SK_Strok
point_added = 1;
}
}
mval[0] = dd->mval[0];
mval[1] = dd->mval[1];
/* try to snap to closer object */
found = snapObjectsContext(C, dd->mval, &dist, vec, no, SNAP_NOT_SELECTED);
found = snapObjectsContext(C, mval, &dist, vec, no, SNAP_NOT_SELECTED);
if (found == 1)
{
pt->type = dd->type;

@ -166,10 +166,10 @@ typedef enum SnapMode
#define SNAP_MIN_DISTANCE 30
int peelObjectsTransForm(struct TransInfo *t, struct ListBase *depth_peels, short mval[2]);
int peelObjectsContext(struct bContext *C, struct ListBase *depth_peels, short mval[2]);
int snapObjectsTransform(struct TransInfo *t, short mval[2], int *dist, float *loc, float *no, SnapMode mode);
int snapObjectsContext(struct bContext *C, short mval[2], int *dist, float *loc, float *no, SnapMode mode);
int peelObjectsTransForm(struct TransInfo *t, struct ListBase *depth_peels, float mval[2]);
int peelObjectsContext(struct bContext *C, struct ListBase *depth_peels, float mval[2]);
int snapObjectsTransform(struct TransInfo *t, float mval[2], int *dist, float *loc, float *no, SnapMode mode);
int snapObjectsContext(struct bContext *C, float mval[2], int *dist, float *loc, float *no, SnapMode mode);
#endif

@ -88,8 +88,8 @@ void project_int_noclip(struct ARegion *ar, float *vec, int *adr);
void project_float(struct ARegion *ar, float *vec, float *adr);
void project_float_noclip(struct ARegion *ar, float *vec, float *adr);
void viewline(struct ARegion *ar, struct View3D *v3d, short mval[2], float ray_start[3], float ray_end[3]);
void viewray(struct ARegion *ar, struct View3D *v3d, short mval[2], float ray_start[3], float ray_normal[3]);
void viewline(struct ARegion *ar, struct View3D *v3d, float mval[2], float ray_start[3], float ray_end[3]);
void viewray(struct ARegion *ar, struct View3D *v3d, float mval[2], float ray_start[3], float ray_normal[3]);
int get_view3d_viewplane(struct View3D *v3d, struct RegionView3D *rv3d, int winxi, int winyi, rctf *viewplane, float *clipsta, float *clipend, float *pixsize);
int get_view3d_ortho(struct View3D *v3d, struct RegionView3D *rv3d);

@ -2144,6 +2144,10 @@ void uiTemplateHeader3D(uiLayout *layout, struct bContext *C)
uiDefIconButBitS(block, TOG, SCE_SNAP_PEEL_OBJECT, B_REDR, ICON_SNAP_PEEL_OBJECT,xco,yco,XIC,YIC, &ts->snap_flag, 0, 0, 0, 0, "Consider objects as whole when finding volume center");
xco+= XIC;
}
if (ts->snap_mode == SCE_SNAP_MODE_FACE) {
uiDefIconButBitS(block, TOG, SCE_SNAP_PROJECT, B_REDR, ICON_ROTATECOLLECTION,xco,yco,XIC,YIC, &ts->snap_flag, 0, 0, 0, 0, "Project elements instead of snapping them");
xco+= XIC;
}
uiDefIconTextButS(block, ICONTEXTROW,B_REDR, ICON_SNAP_VERTEX, snapmode_pup(), xco,yco,XIC+10,YIC, &(ts->snap_mode), 0.0, 0.0, 0, 0, "Snapping mode");
xco+= XIC + 10;
uiDefButS(block, MENU, B_NOP, "Snap Mode%t|Closest%x0|Center%x1|Median%x2|Active%x3",xco,yco,70,YIC, &ts->snap_target, 0, 0, 0, 0, "Snap Target Mode");

@ -482,7 +482,7 @@ void VIEW3D_OT_setobjectascamera(wmOperatorType *ot)
/* ********************************** */
/* create intersection coordinates in view Z direction at mouse coordinates */
void viewline(ARegion *ar, View3D *v3d, short mval[2], float ray_start[3], float ray_end[3])
void viewline(ARegion *ar, View3D *v3d, float mval[2], float ray_start[3], float ray_end[3])
{
RegionView3D *rv3d= ar->regiondata;
float vec[4];
@ -517,7 +517,7 @@ void viewline(ARegion *ar, View3D *v3d, short mval[2], float ray_start[3], float
}
/* create intersection ray in view Z direction at mouse coordinates */
void viewray(ARegion *ar, View3D *v3d, short mval[2], float ray_start[3], float ray_normal[3])
void viewray(ARegion *ar, View3D *v3d, float mval[2], float ray_start[3], float ray_normal[3])
{
float ray_end[3];

@ -2605,7 +2605,6 @@ static void ElementRotation(TransInfo *t, TransData *td, float mat[3][3], short
center = td->center;
}
else {
/* !TODO! Make this if not rely on G */
if(around==V3D_LOCAL && (t->settings->selectmode & SCE_SELECT_FACE)) {
center = td->center;
}

@ -87,6 +87,7 @@ typedef struct TransSnap {
short modeTarget;
short mode;
short align;
short project;
short status;
float snapPoint[3]; /* snapping from this point */
float snapTarget[3]; /* to this point */
@ -578,6 +579,7 @@ void snapGrid(TransInfo *t, float *val);
void snapGridAction(TransInfo *t, float *val, GearsType action);
void initSnapping(struct TransInfo *t, struct wmOperator *op);
void applyProject(TransInfo *t);
void applySnapping(TransInfo *t, float *vec);
void resetSnapping(TransInfo *t);
int handleSnapping(TransInfo *t, struct wmEvent *event);

@ -125,7 +125,6 @@
#include "ED_object.h"
#include "ED_markers.h"
#include "ED_mesh.h"
#include "ED_retopo.h"
#include "ED_types.h"
#include "ED_uvedit.h"
#include "ED_view3d.h"
@ -4478,12 +4477,6 @@ void special_aftertrans_update(TransInfo *t)
if (t->obedit) {
if (cancelled==0) {
EM_automerge(t->scene, t->obedit, 1);
#if 0 // TRANSFORM_FIX_ME
/* when snapping, delay retopo until after automerge */
if (G.qual & LR_CTRLKEY) {
retopo_do_all();
}
#endif
}
}
}

@ -91,7 +91,6 @@
#include "ED_keyframing.h"
#include "ED_markers.h"
#include "ED_mesh.h"
#include "ED_retopo.h"
#include "ED_particle.h"
#include "ED_screen_types.h"
#include "ED_space_api.h"
@ -617,201 +616,201 @@ void recalcData(TransInfo *t)
}
}
}
else if (t->obedit) {
if ELEM(t->obedit->type, OB_CURVE, OB_SURF) {
Curve *cu= t->obedit->data;
Nurb *nu= cu->editnurb->first;
DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */
if (t->state == TRANS_CANCEL) {
while(nu) {
calchandlesNurb(nu); /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */
nu= nu->next;
}
} else {
/* Normal updating */
while(nu) {
test2DNurb(nu);
calchandlesNurb(nu);
nu= nu->next;
}
/* TRANSFORM_FIX_ME */
// retopo_do_all();
}
else if (t->spacetype == SPACE_VIEW3D) {
/* project */
if(t->state != TRANS_CANCEL) {
applyProject(t);
}
else if(t->obedit->type==OB_LATTICE) {
Lattice *la= t->obedit->data;
DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */
if(la->editlatt->flag & LT_OUTSIDE) outside_lattice(la->editlatt);
}
else if (t->obedit->type == OB_MESH) {
if(t->spacetype==SPACE_IMAGE) {
SpaceImage *sima= t->sa->spacedata.first;
if (t->obedit) {
if ELEM(t->obedit->type, OB_CURVE, OB_SURF) {
Curve *cu= t->obedit->data;
Nurb *nu= cu->editnurb->first;
flushTransUVs(t);
if(sima->flag & SI_LIVE_UNWRAP)
ED_uvedit_live_unwrap_re_solve();
DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA);
} else {
EditMesh *em = ((Mesh*)t->obedit->data)->edit_mesh;
/* mirror modifier clipping? */
if(t->state != TRANS_CANCEL) {
/* TRANSFORM_FIX_ME */
// if ((G.qual & LR_CTRLKEY)==0) {
// /* Only retopo if not snapping, Note, this is the only case of G.qual being used, but we have no T_SHIFT_MOD - Campbell */
// retopo_do_all();
// }
clipMirrorModifier(t, t->obedit);
}
if((t->options & CTX_NO_MIRROR) == 0 && (t->flag & T_MIRROR))
editmesh_apply_to_mirror(t);
DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */
recalc_editnormals(em);
}
}
else if(t->obedit->type==OB_ARMATURE) { /* no recalc flag, does pose */
bArmature *arm= t->obedit->data;
ListBase *edbo = arm->edbo;
EditBone *ebo;
TransData *td = t->data;
int i;
/* Ensure all bones are correctly adjusted */
for (ebo = edbo->first; ebo; ebo = ebo->next){
if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
/* If this bone has a parent tip that has been moved */
if (ebo->parent->flag & BONE_TIPSEL){
VECCOPY (ebo->head, ebo->parent->tail);
if(t->mode==TFM_BONE_ENVELOPE) ebo->rad_head= ebo->parent->rad_tail;
if (t->state == TRANS_CANCEL) {
while(nu) {
calchandlesNurb(nu); /* Cant do testhandlesNurb here, it messes up the h1 and h2 flags */
nu= nu->next;
}
/* If this bone has a parent tip that has NOT been moved */
else{
VECCOPY (ebo->parent->tail, ebo->head);
if(t->mode==TFM_BONE_ENVELOPE) ebo->parent->rad_tail= ebo->rad_head;
}
}
/* on extrude bones, oldlength==0.0f, so we scale radius of points */
ebo->length= VecLenf(ebo->head, ebo->tail);
if(ebo->oldlength==0.0f) {
ebo->rad_head= 0.25f*ebo->length;
ebo->rad_tail= 0.10f*ebo->length;
ebo->dist= 0.25f*ebo->length;
if(ebo->parent) {
if(ebo->rad_head > ebo->parent->rad_tail)
ebo->rad_head= ebo->parent->rad_tail;
}
}
else if(t->mode!=TFM_BONE_ENVELOPE) {
/* if bones change length, lets do that for the deform distance as well */
ebo->dist*= ebo->length/ebo->oldlength;
ebo->rad_head*= ebo->length/ebo->oldlength;
ebo->rad_tail*= ebo->length/ebo->oldlength;
ebo->oldlength= ebo->length;
}
}
if (t->mode != TFM_BONE_ROLL)
{
/* fix roll */
for(i = 0; i < t->total; i++, td++)
{
if (td->extra)
{
float vec[3], up_axis[3];
float qrot[4];
ebo = td->extra;
VECCOPY(up_axis, td->axismtx[2]);
if (t->mode != TFM_ROTATION)
{
VecSubf(vec, ebo->tail, ebo->head);
Normalize(vec);
RotationBetweenVectorsToQuat(qrot, td->axismtx[1], vec);
QuatMulVecf(qrot, up_axis);
}
else
{
Mat3MulVecfl(t->mat, up_axis);
}
ebo->roll = ED_rollBoneToVector(ebo, up_axis);
} else {
/* Normal updating */
while(nu) {
test2DNurb(nu);
calchandlesNurb(nu);
nu= nu->next;
}
}
}
if(arm->flag & ARM_MIRROR_EDIT)
transform_armature_mirror_update(t->obedit);
}
else
DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */
}
else if( (t->flag & T_POSE) && t->poseobj) {
Object *ob= t->poseobj;
bArmature *arm= ob->data;
/* if animtimer is running, and the object already has animation data,
* check if the auto-record feature means that we should record 'samples'
* (i.e. uneditable animation values)
*/
// TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) {
int targetless_ik= (t->flag & T_AUTOIK); // XXX this currently doesn't work, since flags aren't set yet!
animrecord_check_state(t->scene, &ob->id, t->animtimer);
autokeyframe_pose_cb_func(t->scene, (View3D *)t->view, ob, t->mode, targetless_ik);
}
/* old optimize trick... this enforces to bypass the depgraph */
if (!(arm->flag & ARM_DELAYDEFORM)) {
DAG_id_flush_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */
}
else
where_is_pose(scene, ob);
}
else {
for(base= FIRSTBASE; base; base= base->next) {
Object *ob= base->object;
/* this flag is from depgraph, was stored in initialize phase, handled in drawview.c */
if(base->flag & BA_HAS_RECALC_OB)
ob->recalc |= OB_RECALC_OB;
if(base->flag & BA_HAS_RECALC_DATA)
ob->recalc |= OB_RECALC_DATA;
/* if object/base is selected */
if ((base->flag & SELECT) || (ob->flag & SELECT)) {
/* if animtimer is running, and the object already has animation data,
* check if the auto-record feature means that we should record 'samples'
* (i.e. uneditable animation values)
*/
// TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) {
animrecord_check_state(t->scene, &ob->id, t->animtimer);
autokeyframe_ob_cb_func(t->scene, (View3D *)t->view, ob, t->mode);
}
}
/* proxy exception */
if(ob->proxy)
ob->proxy->recalc |= ob->recalc;
if(ob->proxy_group)
group_tag_recalc(ob->proxy_group->dup_group);
}
}
else if(t->obedit->type==OB_LATTICE) {
Lattice *la= t->obedit->data;
DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */
/* update shaded drawmode while transform */
if(t->spacetype==SPACE_VIEW3D && ((View3D*)t->view)->drawtype == OB_SHADED)
reshadeall_displist(t->scene);
if(la->editlatt->flag & LT_OUTSIDE) outside_lattice(la->editlatt);
}
else if (t->obedit->type == OB_MESH) {
if(t->spacetype==SPACE_IMAGE) {
SpaceImage *sima= t->sa->spacedata.first;
flushTransUVs(t);
if(sima->flag & SI_LIVE_UNWRAP)
ED_uvedit_live_unwrap_re_solve();
DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA);
} else {
EditMesh *em = ((Mesh*)t->obedit->data)->edit_mesh;
/* mirror modifier clipping? */
if(t->state != TRANS_CANCEL) {
clipMirrorModifier(t, t->obedit);
}
if((t->options & CTX_NO_MIRROR) == 0 && (t->flag & T_MIRROR))
editmesh_apply_to_mirror(t);
DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */
recalc_editnormals(em);
}
}
else if(t->obedit->type==OB_ARMATURE) { /* no recalc flag, does pose */
bArmature *arm= t->obedit->data;
ListBase *edbo = arm->edbo;
EditBone *ebo;
TransData *td = t->data;
int i;
/* Ensure all bones are correctly adjusted */
for (ebo = edbo->first; ebo; ebo = ebo->next){
if ((ebo->flag & BONE_CONNECTED) && ebo->parent){
/* If this bone has a parent tip that has been moved */
if (ebo->parent->flag & BONE_TIPSEL){
VECCOPY (ebo->head, ebo->parent->tail);
if(t->mode==TFM_BONE_ENVELOPE) ebo->rad_head= ebo->parent->rad_tail;
}
/* If this bone has a parent tip that has NOT been moved */
else{
VECCOPY (ebo->parent->tail, ebo->head);
if(t->mode==TFM_BONE_ENVELOPE) ebo->parent->rad_tail= ebo->rad_head;
}
}
/* on extrude bones, oldlength==0.0f, so we scale radius of points */
ebo->length= VecLenf(ebo->head, ebo->tail);
if(ebo->oldlength==0.0f) {
ebo->rad_head= 0.25f*ebo->length;
ebo->rad_tail= 0.10f*ebo->length;
ebo->dist= 0.25f*ebo->length;
if(ebo->parent) {
if(ebo->rad_head > ebo->parent->rad_tail)
ebo->rad_head= ebo->parent->rad_tail;
}
}
else if(t->mode!=TFM_BONE_ENVELOPE) {
/* if bones change length, lets do that for the deform distance as well */
ebo->dist*= ebo->length/ebo->oldlength;
ebo->rad_head*= ebo->length/ebo->oldlength;
ebo->rad_tail*= ebo->length/ebo->oldlength;
ebo->oldlength= ebo->length;
}
}
if (t->mode != TFM_BONE_ROLL)
{
/* fix roll */
for(i = 0; i < t->total; i++, td++)
{
if (td->extra)
{
float vec[3], up_axis[3];
float qrot[4];
ebo = td->extra;
VECCOPY(up_axis, td->axismtx[2]);
if (t->mode != TFM_ROTATION)
{
VecSubf(vec, ebo->tail, ebo->head);
Normalize(vec);
RotationBetweenVectorsToQuat(qrot, td->axismtx[1], vec);
QuatMulVecf(qrot, up_axis);
}
else
{
Mat3MulVecfl(t->mat, up_axis);
}
ebo->roll = ED_rollBoneToVector(ebo, up_axis);
}
}
}
if(arm->flag & ARM_MIRROR_EDIT)
transform_armature_mirror_update(t->obedit);
}
else
DAG_id_flush_update(t->obedit->data, OB_RECALC_DATA); /* sets recalc flags */
}
else if( (t->flag & T_POSE) && t->poseobj) {
Object *ob= t->poseobj;
bArmature *arm= ob->data;
/* if animtimer is running, and the object already has animation data,
* check if the auto-record feature means that we should record 'samples'
* (i.e. uneditable animation values)
*/
// TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) {
int targetless_ik= (t->flag & T_AUTOIK); // XXX this currently doesn't work, since flags aren't set yet!
animrecord_check_state(t->scene, &ob->id, t->animtimer);
autokeyframe_pose_cb_func(t->scene, (View3D *)t->view, ob, t->mode, targetless_ik);
}
/* old optimize trick... this enforces to bypass the depgraph */
if (!(arm->flag & ARM_DELAYDEFORM)) {
DAG_id_flush_update(&ob->id, OB_RECALC_DATA); /* sets recalc flags */
}
else
where_is_pose(scene, ob);
}
else {
for(base= FIRSTBASE; base; base= base->next) {
Object *ob= base->object;
/* this flag is from depgraph, was stored in initialize phase, handled in drawview.c */
if(base->flag & BA_HAS_RECALC_OB)
ob->recalc |= OB_RECALC_OB;
if(base->flag & BA_HAS_RECALC_DATA)
ob->recalc |= OB_RECALC_DATA;
/* if object/base is selected */
if ((base->flag & SELECT) || (ob->flag & SELECT)) {
/* if animtimer is running, and the object already has animation data,
* check if the auto-record feature means that we should record 'samples'
* (i.e. uneditable animation values)
*/
// TODO: autokeyframe calls need some setting to specify to add samples (FPoints) instead of keyframes?
if ((t->animtimer) && IS_AUTOKEY_ON(t->scene)) {
animrecord_check_state(t->scene, &ob->id, t->animtimer);
autokeyframe_ob_cb_func(t->scene, (View3D *)t->view, ob, t->mode);
}
}
/* proxy exception */
if(ob->proxy)
ob->proxy->recalc |= ob->recalc;
if(ob->proxy_group)
group_tag_recalc(ob->proxy_group->dup_group);
}
}
if(t->spacetype==SPACE_VIEW3D && ((View3D*)t->view)->drawtype == OB_SHADED)
reshadeall_displist(t->scene);
}
}
void drawLine(TransInfo *t, float *center, float *dir, char axis, short options)

@ -63,32 +63,6 @@ EnumPropertyItem proportional_mode_types[] = {
{0, NULL, 0, NULL, NULL}
};
EnumPropertyItem snap_mode_types[] = {
{SCE_SNAP_TARGET_CLOSEST, "CLOSEST", 0, "Closest", ""},
{SCE_SNAP_TARGET_CENTER, "CENTER", 0, "Center", ""},
{SCE_SNAP_TARGET_MEDIAN, "MEDIAN", 0, "Median", ""},
{SCE_SNAP_TARGET_ACTIVE, "ACTIVE", 0, "Active", ""},
{0, NULL, 0, NULL, NULL}
};
EnumPropertyItem proportional_falloff_types[] = {
{PROP_SMOOTH, "SMOOTH", 0, "Smooth", ""},
{PROP_SPHERE, "SPHERE", 0, "Sphere", ""},
{PROP_ROOT, "ROOT", 0, "Root", ""},
{PROP_SHARP, "SHARP", 0, "Sharp", ""},
{PROP_LIN, "LINEAR", 0, "Linear", ""},
{PROP_CONST, "CONSTANT", 0, "Constant", ""},
{PROP_RANDOM, "RANDOM", 0, "Random", ""},
{0, NULL, 0, NULL, NULL}
};
EnumPropertyItem orientation_items[]= {
{V3D_MANIP_GLOBAL, "GLOBAL", 0, "Global", ""},
{V3D_MANIP_NORMAL, "NORMAL", 0, "Normal", ""},
{V3D_MANIP_LOCAL, "LOCAL", 0, "Local", ""},
{V3D_MANIP_VIEW, "VIEW", 0, "View", ""},
{0, NULL, 0, NULL, NULL}};
char OP_TRANSLATION[] = "TFM_OT_translate";
char OP_ROTATION[] = "TFM_OT_rotate";
char OP_TOSPHERE[] = "TFM_OT_tosphere";
@ -157,7 +131,8 @@ void TFM_OT_select_orientation(struct wmOperatorType *ot)
ot->exec = select_orientation_exec;
ot->poll = ED_operator_areaactive;
prop= RNA_def_enum(ot->srna, "orientation", orientation_items, V3D_MANIP_GLOBAL, "Orientation", "DOC_BROKEN");
prop= RNA_def_property(ot->srna, "orientation", PROP_ENUM, PROP_NONE);
RNA_def_property_ui_text(prop, "Orientation", "Transformation orientation.");
RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf);
}
@ -374,7 +349,7 @@ void Properties_Proportional(struct wmOperatorType *ot)
void Properties_Snapping(struct wmOperatorType *ot, short align)
{
RNA_def_boolean(ot->srna, "snap", 0, "Snap to Point", "");
RNA_def_enum(ot->srna, "snap_mode", snap_mode_types, 0, "Mode", "");
RNA_def_enum(ot->srna, "snap_mode", snap_mode_items, 0, "Mode", "");
RNA_def_float_vector(ot->srna, "snap_point", 3, NULL, -FLT_MAX, FLT_MAX, "Point", "", -FLT_MAX, FLT_MAX);
if (align)
@ -389,7 +364,8 @@ void Properties_Constraints(struct wmOperatorType *ot)
PropertyRNA *prop;
RNA_def_boolean_vector(ot->srna, "constraint_axis", 3, NULL, "Constraint Axis", "");
prop= RNA_def_enum(ot->srna, "constraint_orientation", orientation_items, V3D_MANIP_GLOBAL, "Orientation", "DOC_BROKEN");
prop= RNA_def_property(ot->srna, "constraint_orientation", PROP_ENUM, PROP_NONE);
RNA_def_property_ui_text(prop, "Orientation", "Transformation orientation.");
RNA_def_enum_funcs(prop, rna_TransformOrientation_itemf);
}

@ -217,8 +217,69 @@ int handleSnapping(TransInfo *t, wmEvent *event)
return status;
}
void applyProject(TransInfo *t)
{
/* XXX FLICKER IN OBJECT MODE */
if ((t->tsnap.project) && (t->tsnap.status & SNAP_ON) && (t->modifiers & MOD_SNAP_GEARS))
{
TransData *td = t->data;
float tvec[3];
float imat[4][4];
int i;
if(t->flag & (T_EDIT|T_POSE)) {
Object *ob = t->obedit?t->obedit:t->poseobj;
Mat4Invert(imat, ob->obmat);
}
for(i = 0 ; i < t->total; i++, td++) {
float iloc[3], loc[3], no[3];
float mval[2];
int dist = 1000;
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
VECCOPY(iloc, td->loc);
if (t->flag & (T_EDIT|T_POSE))
{
Object *ob = t->obedit?t->obedit:t->poseobj;
Mat4MulVecfl(ob->obmat, iloc);
}
else if (t->flag & T_OBJECT)
{
VECCOPY(iloc, td->ob->obmat[3]);
}
project_float(t->ar, iloc, mval);
if (snapObjectsTransform(t, mval, &dist, loc, no, t->tsnap.mode))
{
// if(t->flag & (T_EDIT|T_POSE)) {
// Mat4MulVecfl(imat, loc);
// }
//
VecSubf(tvec, loc, iloc);
Mat3MulVecfl(td->smtx, tvec);
VecAddf(td->loc, td->loc, tvec);
}
//XXX constraintTransLim(t, td);
}
}
}
void applySnapping(TransInfo *t, float *vec)
{
/* project is not applied this way */
if (t->tsnap.project)
return;
if (t->tsnap.status & SNAP_FORCED)
{
t->tsnap.targetSnap(t);
@ -305,12 +366,24 @@ void initSnapping(TransInfo *t, wmOperator *op)
RNA_float_get_array(op->ptr, "snap_normal", t->tsnap.snapNormal);
Normalize(t->tsnap.snapNormal);
}
if (RNA_struct_find_property(op->ptr, "snap_project"))
{
t->tsnap.project = RNA_boolean_get(op->ptr, "snap_project");
}
}
}
else
{
snapping = ((ts->snap_flag & SCE_SNAP) == SCE_SNAP);
t->tsnap.align = ((t->settings->snap_flag & SCE_SNAP_ROTATE) == SCE_SNAP_ROTATE);
t->tsnap.project = ((t->settings->snap_flag & SCE_SNAP_PROJECT) == SCE_SNAP_PROJECT);
}
/* force project off when not supported */
if (ts->snap_mode != SCE_SNAP_MODE_FACE)
{
t->tsnap.project = 0;
}
if ((t->spacetype == SPACE_VIEW3D || t->spacetype == SPACE_IMAGE) && // Only 3D view or UV
@ -537,9 +610,13 @@ void CalcSnapGeometry(TransInfo *t, float *vec)
{
float loc[3];
float no[3];
float mval[2];
int found = 0;
int dist = SNAP_MIN_DISTANCE; // Use a user defined value here
mval[0] = t->mval[0];
mval[1] = t->mval[1];
if (t->settings->snap_mode == SCE_SNAP_MODE_VOLUME)
{
ListBase depth_peels;
@ -550,7 +627,7 @@ void CalcSnapGeometry(TransInfo *t, float *vec)
depth_peels.first = depth_peels.last = NULL;
peelObjectsTransForm(t, &depth_peels, t->mval);
peelObjectsTransForm(t, &depth_peels, mval);
// if (LAST_SNAP_POINT_VALID)
// {
@ -633,7 +710,7 @@ void CalcSnapGeometry(TransInfo *t, float *vec)
}
else
{
found = snapObjectsTransform(t, t->mval, &dist, loc, no, t->tsnap.mode);
found = snapObjectsTransform(t, mval, &dist, loc, no, t->tsnap.mode);
}
if (found == 1)
@ -854,7 +931,7 @@ void TargetSnapClosest(TransInfo *t)
}
/*================================================================*/
int snapFace(ARegion *ar, float v1co[3], float v2co[3], float v3co[3], float *v4co, short mval[2], float ray_start[3], float ray_start_local[3], float ray_normal_local[3], float obmat[][4], float timat[][3], float *loc, float *no, int *dist, float *depth)
int snapFace(ARegion *ar, float v1co[3], float v2co[3], float v3co[3], float *v4co, float mval[2], float ray_start[3], float ray_start_local[3], float ray_normal_local[3], float obmat[][4], float timat[][3], float *loc, float *no, int *dist, float *depth)
{
float lambda;
int result;
@ -885,7 +962,7 @@ int snapFace(ARegion *ar, float v1co[3], float v2co[3], float v3co[3], float *v4
new_depth = VecLenf(location, ray_start);
project_int(ar, location, screen_loc);
new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]);
new_dist = abs(screen_loc[0] - (int)mval[0]) + abs(screen_loc[1] - (int)mval[1]);
if (new_dist <= *dist && new_depth < *depth)
{
@ -905,7 +982,7 @@ int snapFace(ARegion *ar, float v1co[3], float v2co[3], float v3co[3], float *v4
return retval;
}
int snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], short v2no[3], short mval[2], float ray_start[3], float ray_start_local[3], float ray_normal_local[3], float obmat[][4], float timat[][3], float *loc, float *no, int *dist, float *depth)
int snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], short v2no[3], float mval[2], float ray_start[3], float ray_start_local[3], float ray_normal_local[3], float obmat[][4], float timat[][3], float *loc, float *no, int *dist, float *depth)
{
float intersect[3] = {0, 0, 0}, ray_end[3], dvec[3];
int result;
@ -953,7 +1030,7 @@ int snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], short v2n
new_depth = VecLenf(location, ray_start);
project_int(ar, location, screen_loc);
new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]);
new_dist = abs(screen_loc[0] - (int)mval[0]) + abs(screen_loc[1] - (int)mval[1]);
/* 10% threshold if edge is closer but a bit further
* this takes care of series of connected edges a bit slanted w.r.t the viewport
@ -990,7 +1067,7 @@ int snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], short v2n
return retval;
}
int snapVertex(ARegion *ar, float vco[3], short vno[3], short mval[2], float ray_start[3], float ray_start_local[3], float ray_normal_local[3], float obmat[][4], float timat[][3], float *loc, float *no, int *dist, float *depth)
int snapVertex(ARegion *ar, float vco[3], short vno[3], float mval[2], float ray_start[3], float ray_start_local[3], float ray_normal_local[3], float obmat[][4], float timat[][3], float *loc, float *no, int *dist, float *depth)
{
int retval = 0;
float dvec[3];
@ -1011,7 +1088,7 @@ int snapVertex(ARegion *ar, float vco[3], short vno[3], short mval[2], float ray
new_depth = VecLenf(location, ray_start);
project_int(ar, location, screen_loc);
new_dist = abs(screen_loc[0] - mval[0]) + abs(screen_loc[1] - mval[1]);
new_dist = abs(screen_loc[0] - (int)mval[0]) + abs(screen_loc[1] - (int)mval[1]);
if (new_dist <= *dist && new_depth < *depth)
{
@ -1034,7 +1111,7 @@ int snapVertex(ARegion *ar, float vco[3], short vno[3], short mval[2], float ray
return retval;
}
int snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *arm, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], float *loc, float *no, int *dist, float *depth)
int snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *arm, float obmat[][4], float ray_start[3], float ray_normal[3], float mval[2], float *loc, float *no, int *dist, float *depth)
{
float imat[4][4];
float ray_start_local[3], ray_normal_local[3];
@ -1099,7 +1176,7 @@ int snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *arm, float
return retval;
}
int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, EditMesh *em, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], float *loc, float *no, int *dist, float *depth)
int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, EditMesh *em, float obmat[][4], float ray_start[3], float ray_normal[3], float mval[2], float *loc, float *no, int *dist, float *depth)
{
int retval = 0;
int totvert = dm->getNumVerts(dm);
@ -1333,7 +1410,7 @@ int snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, E
return retval;
}
int snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], float *loc, float *no, int *dist, float *depth)
int snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, float obmat[][4], float ray_start[3], float ray_normal[3], float mval[2], float *loc, float *no, int *dist, float *depth)
{
ToolSettings *ts= scene->toolsettings;
int retval = 0;
@ -1365,7 +1442,7 @@ int snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, float obma
return retval;
}
int snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, short mval[2], int *dist, float *loc, float *no, SnapMode mode) {
int snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, float mval[2], int *dist, float *loc, float *no, SnapMode mode) {
Base *base;
float depth = FLT_MAX;
int retval = 0;
@ -1382,7 +1459,7 @@ int snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, short mv
base= FIRSTBASE;
for ( base = FIRSTBASE; base != NULL; base = base->next ) {
if ( BASE_SELECTABLE(v3d, base) && (base->flag & (BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA)) == 0 && ((mode == SNAP_NOT_SELECTED && (base->flag & (SELECT|BA_WAS_SEL)) == 0) || (mode == SNAP_NOT_OBEDIT && base != BASACT)) ) {
if ( BASE_SELECTABLE(v3d, base) && (base->flag & (BA_HAS_RECALC_OB|BA_HAS_RECALC_DATA)) == 0 && ((mode == SNAP_NOT_SELECTED && (base->flag & (SELECT|BA_WAS_SEL)) == 0) || (ELEM(mode, SNAP_ALL, SNAP_NOT_OBEDIT) && base != BASACT)) ) {
Object *ob = base->object;
if (ob->transflag & OB_DUPLI)
@ -1407,12 +1484,12 @@ int snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, short mv
return retval;
}
int snapObjectsTransform(TransInfo *t, short mval[2], int *dist, float *loc, float *no, SnapMode mode)
int snapObjectsTransform(TransInfo *t, float mval[2], int *dist, float *loc, float *no, SnapMode mode)
{
return snapObjects(t->scene, t->view, t->ar, t->obedit, mval, dist, loc, no, mode);
}
int snapObjectsContext(bContext *C, short mval[2], int *dist, float *loc, float *no, SnapMode mode)
int snapObjectsContext(bContext *C, float mval[2], int *dist, float *loc, float *no, SnapMode mode)
{
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = sa->spacedata.first;
@ -1477,7 +1554,7 @@ void addDepthPeel(ListBase *depth_peels, float depth, float p[3], float no[3], O
peel->flag = 0;
}
int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_start[3], float ray_normal[3], short mval[2], ListBase *depth_peels)
int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_start[3], float ray_normal[3], float mval[2], ListBase *depth_peels)
{
int retval = 0;
int totvert = dm->getNumVerts(dm);
@ -1585,7 +1662,7 @@ int peelDerivedMesh(Object *ob, DerivedMesh *dm, float obmat[][4], float ray_sta
return retval;
}
int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, ListBase *depth_peels, short mval[2])
int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, ListBase *depth_peels, float mval[2])
{
Base *base;
int retval = 0;
@ -1666,12 +1743,12 @@ int peelObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, ListBase
return retval;
}
int peelObjectsTransForm(TransInfo *t, ListBase *depth_peels, short mval[2])
int peelObjectsTransForm(TransInfo *t, ListBase *depth_peels, float mval[2])
{
return peelObjects(t->scene, t->view, t->ar, t->obedit, depth_peels, mval);
}
int peelObjectsContext(bContext *C, ListBase *depth_peels, short mval[2])
int peelObjectsContext(bContext *C, ListBase *depth_peels, float mval[2])
{
ScrArea *sa = CTX_wm_area(C);
View3D *v3d = sa->spacedata.first;

@ -982,6 +982,7 @@ typedef struct Scene {
#define SCE_SNAP 1
#define SCE_SNAP_ROTATE 2
#define SCE_SNAP_PEEL_OBJECT 4
#define SCE_SNAP_PROJECT 8
/* toolsettings->snap_target */
#define SCE_SNAP_TARGET_CLOSEST 0
#define SCE_SNAP_TARGET_CENTER 1

@ -32,6 +32,7 @@
extern EnumPropertyItem object_mode_items[];
extern EnumPropertyItem prop_mode_items[];
extern EnumPropertyItem snap_mode_items[];
extern EnumPropertyItem space_type_items[];
extern EnumPropertyItem region_type_items[];
extern EnumPropertyItem modifier_type_items[];

@ -43,7 +43,14 @@
#include "WM_types.h"
/* prop_mode needs to be accessible from transform operator */
EnumPropertyItem snap_mode_items[] = {
{SCE_SNAP_TARGET_CLOSEST, "CLOSEST", 0, "Closest", "Snap closest point onto target."},
{SCE_SNAP_TARGET_CENTER, "CENTER", 0, "Center", "Snap center onto target."},
{SCE_SNAP_TARGET_MEDIAN, "MEDIAN", 0, "Median", "Snap median onto target."},
{SCE_SNAP_TARGET_ACTIVE, "ACTIVE", 0, "Active", "Snap active onto target."},
{0, NULL, 0, NULL, NULL}};
EnumPropertyItem prop_mode_items[] ={
{PROP_SMOOTH, "SMOOTH", 0, "Smooth", ""},
{PROP_SPHERE, "SPHERE", 0, "Sphere", ""},
@ -54,6 +61,7 @@ EnumPropertyItem prop_mode_items[] ={
{PROP_RANDOM, "RANDOM", 0, "Random", ""},
{0, NULL, 0, NULL, NULL}};
#ifdef RNA_RUNTIME
#include "DNA_anim_types.h"
@ -489,13 +497,6 @@ static void rna_def_tool_settings(BlenderRNA *brna)
{SCE_SNAP_MODE_VOLUME, "VOLUME", ICON_SNAP_VOLUME, "Volume", "Snap to volume."},
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem snap_mode_items[] = {
{SCE_SNAP_TARGET_CLOSEST, "CLOSEST", 0, "Closest", "Snap closest point onto target."},
{SCE_SNAP_TARGET_CENTER, "CENTER", 0, "Center", "Snap center onto target."},
{SCE_SNAP_TARGET_MEDIAN, "MEDIAN", 0, "Median", "Snap median onto target."},
{SCE_SNAP_TARGET_ACTIVE, "ACTIVE", 0, "Active", "Snap active onto target."},
{0, NULL, 0, NULL, NULL}};
static EnumPropertyItem auto_key_items[] = {
{AUTOKEY_MODE_NORMAL, "ADD_REPLACE_KEYS", 0, "Add & Replace", ""},
{AUTOKEY_MODE_EDITKEYS, "REPLACE_KEYS", 0, "Replace", ""},
@ -570,6 +571,11 @@ static void rna_def_tool_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Snap Peel Object", "Consider objects as whole when finding volume center.");
RNA_def_property_ui_icon(prop, ICON_SNAP_PEEL_OBJECT, 0);
prop= RNA_def_property(srna, "snap_project", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "snap_flag", SCE_SNAP_PROJECT);
RNA_def_property_ui_text(prop, "Project Individual Elements", "DOC_BROKEN");
RNA_def_property_ui_icon(prop, ICON_ROTATECOLLECTION, 0);
/* Auto Keying */
prop= RNA_def_property(srna, "enable_auto_key", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "autokey_mode", AUTOKEY_ON);