True grid snapping for nodes: This snaps nodes to the actual background grid instead of using incremental offset (which is not useful for nodes). Increment snapping has been disabled for nodes to avoid

confusion, grid snap is now the default as it seems to be the most wanted and easy to use mode.

Absolute grid snapping happens in a somewhat generic function 'applyGridAbsolute', which could also be used for objects and other transforms later on. It is conceptually similar to the 'project' snapping
option, in that it calculates a delta vector for each element on top of the overall transform, which places each node on the grid.

Node transform now uses the top-left node corner for TransformData->loc. The transform center is still the average of node centers, so that scaling and rotation works nicely.

snapGrid*** functions have been renamed to snapGridIncrement*** to distinguish better between incremental and absolute grid snapping.
This commit is contained in:
Lukas Toenne 2013-11-06 17:46:32 +00:00
parent 480d4317de
commit 7398600090
12 changed files with 132 additions and 57 deletions

View File

@ -105,7 +105,7 @@ class NODE_HT_header(Header):
row = layout.row(align=True)
row.prop(toolsettings, "use_snap", text="")
row.prop(toolsettings, "snap_node_element", text="", icon_only=True)
if toolsettings.snap_node_element != 'INCREMENT':
if toolsettings.snap_node_element != 'GRID':
row.prop(toolsettings, "snap_target", text="")
row = layout.row(align=True)

View File

@ -504,6 +504,8 @@ Scene *BKE_scene_add(Main *bmain, const char *name)
sce->toolsettings->normalsize = 0.1;
sce->toolsettings->autokey_mode = U.autokey_mode;
sce->toolsettings->snap_node_mode = SCE_SNAP_MODE_GRID;
sce->toolsettings->skgen_resolution = 100;
sce->toolsettings->skgen_threshold_internal = 0.01f;
sce->toolsettings->skgen_threshold_external = 0.01f;

View File

@ -9818,6 +9818,12 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
scene->gm.matmode = GAME_MAT_MULTITEX;
}
}
/* 'Increment' mode disabled for nodes, use true grid snapping instead */
for (scene = main->scene.first; scene; scene = scene->id.next) {
if (scene->toolsettings->snap_node_mode == SCE_SNAP_MODE_INCREMENT)
scene->toolsettings->snap_node_mode = SCE_SNAP_MODE_GRID;
}
}
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */

View File

@ -54,6 +54,8 @@ typedef enum {
NODE_RIGHT = 8
} NodeBorder;
#define NODE_GRID_STEPS 5
/* space_node.c */
int ED_node_tree_path_length(struct SpaceNode *snode);
void ED_node_tree_path_get(struct SpaceNode *snode, char *value);
@ -81,6 +83,7 @@ void ED_node_tree_update(const struct bContext *C);
void ED_node_tag_update_id(struct ID *id);
void ED_node_tag_update_nodetree(struct Main *bmain, struct bNodeTree *ntree);
void ED_node_sort(struct bNodeTree *ntree);
float ED_node_grid_size(void);
/* node_relationships.c */
void ED_node_link_intersect_test(struct ScrArea *sa, int test);

View File

@ -72,6 +72,11 @@
/* XXX interface.h */
extern void ui_dropshadow(const rctf *rct, float radius, float aspect, float alpha, int select);
float ED_node_grid_size(void)
{
return U.widget_unit;
}
void ED_node_tree_update(const bContext *C)
{
SpaceNode *snode = CTX_wm_space_node(C);
@ -1325,7 +1330,7 @@ void drawnodespace(const bContext *C, ARegion *ar)
snode_setup_v2d(snode, ar, center);
/* grid, uses theme color based on node path depth */
UI_view2d_multi_grid_draw(v2d, (depth > 0 ? TH_NODE_GROUP : TH_BACK), U.widget_unit, 5, 2);
UI_view2d_multi_grid_draw(v2d, (depth > 0 ? TH_NODE_GROUP : TH_BACK), ED_node_grid_size(), NODE_GRID_STEPS, 2);
/* backdrop */
draw_nodespace_back_pix(C, ar, snode, path->parent_key);
@ -1350,7 +1355,7 @@ void drawnodespace(const bContext *C, ARegion *ar)
}
else {
/* default grid */
UI_view2d_multi_grid_draw(v2d, TH_BACK, U.widget_unit, 5, 2);
UI_view2d_multi_grid_draw(v2d, TH_BACK, ED_node_grid_size(), NODE_GRID_STEPS, 2);
/* backdrop */
draw_nodespace_back_pix(C, ar, snode, NODE_INSTANCE_KEY_NONE);

View File

@ -82,6 +82,7 @@
#include "ED_mesh.h"
#include "ED_clip.h"
#include "ED_mask.h"
#include "ED_node.h"
#include "WM_types.h"
#include "WM_api.h"
@ -2778,7 +2779,7 @@ static void Warp(TransInfo *t, const int UNUSED(mval[2]))
const float radius_snap = 0.1f;
const float snap_hack = (t->snap[1] * data->warp_init_dist) / radius_snap;
values.scale *= snap_hack;
snapGrid(t, values.vector);
snapGridIncrement(t, values.vector);
values.scale /= snap_hack;
}
#endif
@ -2950,7 +2951,7 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
value = t->values[0];
snapGrid(t, &value);
snapGridIncrement(t, &value);
applyNumInput(&t->num, &value);
@ -3238,7 +3239,7 @@ static void applyResize(TransInfo *t, const int mval[2])
size[0] = size[1] = size[2] = ratio;
snapGrid(t, size);
snapGridIncrement(t, size);
if (hasNumInput(&t->num)) {
applyNumInput(&t->num, size);
@ -3340,7 +3341,7 @@ static void applySkinResize(TransInfo *t, const int UNUSED(mval[2]))
ratio = t->values[0];
size[0] = size[1] = size[2] = ratio;
snapGrid(t, size);
snapGridIncrement(t, size);
if (hasNumInput(&t->num)) {
applyNumInput(&t->num, size);
@ -3438,7 +3439,7 @@ static void applyToSphere(TransInfo *t, const int UNUSED(mval[2]))
ratio = t->values[0];
snapGrid(t, &ratio);
snapGridIncrement(t, &ratio);
applyNumInput(&t->num, &ratio);
@ -3789,7 +3790,7 @@ static void applyRotation(TransInfo *t, const int UNUSED(mval[2]))
final = t->values[0];
snapGrid(t, &final);
snapGridIncrement(t, &final);
if ((t->con.mode & CON_APPLY) && t->con.applyRot) {
t->con.applyRot(t, NULL, t->axis, NULL);
@ -3902,7 +3903,7 @@ static void applyTrackball(TransInfo *t, const int UNUSED(mval[2]))
phi[0] = t->values[0];
phi[1] = t->values[1];
snapGrid(t, phi);
snapGridIncrement(t, phi);
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN * 2];
@ -3981,8 +3982,8 @@ static void initTranslation(TransInfo *t)
}
else if (t->spacetype == SPACE_NODE) {
t->snap[0] = 0.0f;
t->snap[1] = 125.0f;
t->snap[2] = 25.0f;
t->snap[1] = ED_node_grid_size() * NODE_GRID_STEPS;
t->snap[2] = ED_node_grid_size();
}
else {
t->snap[0] = 0.0f;
@ -4162,7 +4163,7 @@ static void applyTranslation(TransInfo *t, const int UNUSED(mval[2]))
headerTranslation(t, pvec, str);
}
else {
snapGrid(t, t->values);
snapGridIncrement(t, t->values);
applyNumInput(&t->num, t->values);
if (hasNumInput(&t->num)) {
removeAspectRatio(t, t->values);
@ -4234,7 +4235,7 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
distance = -t->values[0];
snapGrid(t, &distance);
snapGridIncrement(t, &distance);
applyNumInput(&t->num, &distance);
@ -4327,7 +4328,7 @@ static void applyTilt(TransInfo *t, const int UNUSED(mval[2]))
final = t->values[0];
snapGrid(t, &final);
snapGridIncrement(t, &final);
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@ -4402,7 +4403,7 @@ static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
ratio = t->values[0];
snapGrid(t, &ratio);
snapGridIncrement(t, &ratio);
applyNumInput(&t->num, &ratio);
@ -4475,7 +4476,7 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
ratio = t->values[0];
snapGrid(t, &ratio);
snapGridIncrement(t, &ratio);
applyNumInput(&t->num, &ratio);
@ -4566,7 +4567,7 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2]))
distance = t->values[0];
snapGrid(t, &distance);
snapGridIncrement(t, &distance);
applyNumInput(&t->num, &distance);
@ -4658,7 +4659,7 @@ static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2]))
weight -= 1.0f;
if (weight > 1.0f) weight = 1.0f;
snapGrid(t, &weight);
snapGridIncrement(t, &weight);
applyNumInput(&t->num, &weight);
@ -4735,7 +4736,7 @@ static void applyCrease(TransInfo *t, const int UNUSED(mval[2]))
crease -= 1.0f;
if (crease > 1.0f) crease = 1.0f;
snapGrid(t, &crease);
snapGridIncrement(t, &crease);
applyNumInput(&t->num, &crease);
@ -4868,7 +4869,7 @@ static void applyBoneSize(TransInfo *t, const int mval[2])
size[0] = size[1] = size[2] = ratio;
snapGrid(t, size);
snapGridIncrement(t, size);
if (hasNumInput(&t->num)) {
applyNumInput(&t->num, size);
@ -4935,7 +4936,7 @@ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2]))
ratio = t->values[0];
snapGrid(t, &ratio);
snapGridIncrement(t, &ratio);
applyNumInput(&t->num, &ratio);
@ -6066,7 +6067,7 @@ static void applyEdgeSlide(TransInfo *t, const int UNUSED(mval[2]))
final = t->values[0];
snapGrid(t, &final);
snapGridIncrement(t, &final);
/* only do this so out of range values are not displayed */
CLAMP(final, -1.0f, 1.0f);
@ -6574,7 +6575,7 @@ static void applyVertSlide(TransInfo *t, const int UNUSED(mval[2]))
final = t->values[0];
snapGrid(t, &final);
snapGridIncrement(t, &final);
/* only do this so out of range values are not displayed */
if (is_constrained) {
@ -6643,7 +6644,7 @@ static void applyBoneRoll(TransInfo *t, const int UNUSED(mval[2]))
final = t->values[0];
snapGrid(t, &final);
snapGridIncrement(t, &final);
if (hasNumInput(&t->num)) {
char c[NUM_STR_REP_LEN];
@ -6716,7 +6717,7 @@ static void applyBakeTime(TransInfo *t, const int mval[2])
time = (float)(t->center2d[0] - mval[0]) * fac;
}
snapGrid(t, &time);
snapGridIncrement(t, &time);
applyNumInput(&t->num, &time);
@ -6983,7 +6984,7 @@ static void applySeqSlide(TransInfo *t, const int UNUSED(mval[2]))
copy_v3_v3(t->values, tvec);
}
else {
snapGrid(t, t->values);
snapGridIncrement(t, t->values);
applyNumInput(&t->num, t->values);
}

View File

@ -566,14 +566,15 @@ typedef enum {
SMALL_GEARS = 2
} GearsType;
void snapGrid(TransInfo *t, float *val);
void snapGridAction(TransInfo *t, float *val, GearsType action);
void snapGridIncrement(TransInfo *t, float *val);
void snapGridIncrementAction(TransInfo *t, float *val, GearsType action);
bool activeSnap(TransInfo *t);
bool validSnap(TransInfo *t);
void initSnapping(struct TransInfo *t, struct wmOperator *op);
void applyProject(TransInfo *t);
void applyGridAbsolute(TransInfo *t);
void applySnapping(TransInfo *t, float *vec);
void resetSnapping(TransInfo *t);
eRedrawFlag handleSnapping(TransInfo *t, const struct wmEvent *event);

View File

@ -135,7 +135,7 @@ static void postConstraintChecks(TransInfo *t, float vec[3], float pvec[3])
mul_m3_v3(t->con.imtx, vec);
snapGrid(t, vec);
snapGridIncrement(t, vec);
if (t->num.flag & T_NULL_ONE) {
if (!(t->con.mode & CON_AXIS0))

View File

@ -2381,16 +2381,16 @@ void flushTransNodes(TransInfo *t)
int a;
TransData *td;
TransData2D *td2d;
applyGridAbsolute(t);
/* flush to 2d vector from internally used 3d vector */
for (a = 0, td = t->data, td2d = t->data2d; a < t->total; a++, td++, td2d++) {
bNode *node = td->extra;
float vec[2];
/* weirdo - but the node system is a mix of free 2d elements and dpi sensitive UI */
add_v2_v2v2(vec, td2d->loc, td2d->ih1);
node->locx = vec[0] / UI_DPI_FAC;
node->locy = vec[1] / UI_DPI_FAC;
node->locx = td2d->loc[0] / UI_DPI_FAC;
node->locy = td2d->loc[1] / UI_DPI_FAC;
}
/* handle intersection with noodles */
@ -5962,12 +5962,9 @@ static void createTransObject(bContext *C, TransInfo *t)
/* transcribe given node into TransData2D for Transforming */
static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node)
{
/* hold original location */
float locxy[2] = {BLI_rctf_cent_x(&node->totr),
BLI_rctf_cent_y(&node->totr)};
float nodeloc[2];
copy_v2_v2(td2d->loc, locxy);
/* use top-left corner as the transform origin for nodes */
td2d->loc[0] = node->totr.xmin;
td2d->loc[1] = node->totr.ymax;
td2d->loc[2] = 0.0f;
td2d->loc2d = td2d->loc; /* current location */
@ -5976,8 +5973,8 @@ static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node)
td->loc = td2d->loc;
copy_v3_v3(td->iloc, td->loc);
/* use node center instead of origin (top-left corner) */
td->center[0] = locxy[0];
td->center[1] = locxy[1];
td->center[0] = BLI_rctf_cent_x(&node->totr);
td->center[1] = BLI_rctf_cent_y(&node->totr);
td->center[2] = 0.0f;
memset(td->axismtx, 0, sizeof(td->axismtx));
@ -5991,11 +5988,6 @@ static void NodeToTransData(TransData *td, TransData2D *td2d, bNode *node)
unit_m3(td->mtx);
unit_m3(td->smtx);
/* weirdo - but the node system is a mix of free 2d elements and dpi sensitive UI */
nodeloc[0] = UI_DPI_FAC * node->locx;
nodeloc[1] = UI_DPI_FAC * node->locy;
sub_v2_v2v2(td2d->ih1, nodeloc, locxy);
td->extra = node;
}

View File

@ -344,6 +344,70 @@ void applyProject(TransInfo *t)
}
}
void applyGridAbsolute(TransInfo *t)
{
float grid_size = 0.0f;
GearsType grid_action;
TransData *td;
float imat[4][4];
int i;
if (!(activeSnap(t) && (t->tsnap.mode == SCE_SNAP_MODE_GRID)))
return;
grid_action = BIG_GEARS;
if (t->modifiers & MOD_PRECISION)
grid_action = SMALL_GEARS;
switch (grid_action) {
case NO_GEARS: grid_size = t->snap[0]; break;
case BIG_GEARS: grid_size = t->snap[1]; break;
case SMALL_GEARS: grid_size = t->snap[2]; break;
}
/* early exit on unusable grid size */
if (grid_size == 0.0f)
return;
if (t->flag & (T_EDIT | T_POSE)) {
Object *ob = t->obedit ? t->obedit : t->poseobj;
invert_m4_m4(imat, ob->obmat);
}
for (i = 0, td = t->data; i < t->total; i++, td++) {
float iloc[3], loc[3], tvec[3];
if (td->flag & TD_NOACTION)
break;
if (td->flag & TD_SKIP)
continue;
if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f))
continue;
copy_v3_v3(iloc, td->loc);
if (t->flag & (T_EDIT | T_POSE)) {
Object *ob = t->obedit ? t->obedit : t->poseobj;
mul_m4_v3(ob->obmat, iloc);
}
else if (t->flag & T_OBJECT) {
td->ob->recalc |= OB_RECALC_OB | OB_RECALC_DATA | OB_RECALC_TIME;
BKE_object_handle_update(t->scene, td->ob);
copy_v3_v3(iloc, td->ob->obmat[3]);
}
mul_v3_v3fl(loc, iloc, 1.0f/grid_size);
loc[0] = floorf(loc[0]);
loc[1] = floorf(loc[1]);
loc[2] = floorf(loc[2]);
mul_v3_fl(loc, grid_size);
sub_v3_v3v3(tvec, loc, iloc);
mul_m3_v3(td->smtx, tvec);
add_v3_v3(td->loc, tvec);
}
}
void applySnapping(TransInfo *t, float *vec)
{
/* project is not applied this way */
@ -818,7 +882,7 @@ static float ResizeBetween(TransInfo *t, float p1[3], float p2[3])
static void UNUSED_FUNCTION(CalcSnapGrid) (TransInfo *t, float *UNUSED(vec))
{
snapGridAction(t, t->tsnap.snapPoint, BIG_GEARS);
snapGridIncrementAction(t, t->tsnap.snapPoint, BIG_GEARS);
}
static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec))
@ -2169,10 +2233,10 @@ bool snapNodesContext(bContext *C, const int mval[2], float *r_dist_px, float r_
/*================================================================*/
static void applyGrid(TransInfo *t, float *val, int max_index, float fac[3], GearsType action);
static void applyGridIncrement(TransInfo *t, float *val, int max_index, float fac[3], GearsType action);
void snapGridAction(TransInfo *t, float *val, GearsType action)
void snapGridIncrementAction(TransInfo *t, float *val, GearsType action)
{
float fac[3];
@ -2180,11 +2244,11 @@ void snapGridAction(TransInfo *t, float *val, GearsType action)
fac[BIG_GEARS] = t->snap[1];
fac[SMALL_GEARS] = t->snap[2];
applyGrid(t, val, t->idx_max, fac, action);
applyGridIncrement(t, val, t->idx_max, fac, action);
}
void snapGrid(TransInfo *t, float *val)
void snapGridIncrement(TransInfo *t, float *val)
{
GearsType action;
@ -2198,17 +2262,17 @@ void snapGrid(TransInfo *t, float *val)
action = SMALL_GEARS;
}
snapGridAction(t, val, action);
snapGridIncrementAction(t, val, action);
}
static void applyGrid(TransInfo *t, float *val, int max_index, float fac[3], GearsType action)
static void applyGridIncrement(TransInfo *t, float *val, int max_index, float fac[3], GearsType action)
{
int i;
float asp[3] = {1.0f, 1.0f, 1.0f}; // TODO: Remove hard coded limit here (3)
if (max_index > 2) {
printf("applyGrid: invalid index %d, clamping\n", max_index);
printf("applyGridIncrement: invalid index %d, clamping\n", max_index);
max_index = 2;
}

View File

@ -1457,6 +1457,7 @@ typedef struct Scene {
#define SCE_SNAP_MODE_NODE_X 5
#define SCE_SNAP_MODE_NODE_Y 6
#define SCE_SNAP_MODE_NODE_XY 7
#define SCE_SNAP_MODE_GRID 8
/* toolsettings->selectmode */
#define SCE_SELECT_VERTEX 1 /* for mesh */

View File

@ -145,7 +145,7 @@ EnumPropertyItem snap_element_items[] = {
};
EnumPropertyItem snap_node_element_items[] = {
{SCE_SNAP_MODE_INCREMENT, "INCREMENT", ICON_SNAP_INCREMENT, "Increment", "Snap to increments of grid"},
{SCE_SNAP_MODE_GRID, "GRID", ICON_SNAP_INCREMENT, "Grid", "Snap to grid"},
{SCE_SNAP_MODE_NODE_X, "NODE_X", ICON_SNAP_EDGE, "Node X", "Snap to left/right node border"},
{SCE_SNAP_MODE_NODE_Y, "NODE_Y", ICON_SNAP_EDGE, "Node Y", "Snap to top/bottom node border"},
{SCE_SNAP_MODE_NODE_XY, "NODE_XY", ICON_SNAP_EDGE, "Node X / Y", "Snap to any node border"},